mirror of
https://github.com/DrKLO/Telegram.git
synced 2024-12-22 06:25:14 +01:00
update to 10.13.1 (4845)
This commit is contained in:
parent
d494ea8cb5
commit
5bc1c3dce0
580 changed files with 23071 additions and 5933 deletions
|
@ -39,13 +39,15 @@ dependencies {
|
||||||
implementation 'com.google.android.gms:play-services-wearable:18.0.0'
|
implementation 'com.google.android.gms:play-services-wearable:18.0.0'
|
||||||
implementation 'com.google.android.gms:play-services-location:21.0.1'
|
implementation 'com.google.android.gms:play-services-location:21.0.1'
|
||||||
implementation 'com.google.android.gms:play-services-wallet:19.1.0'
|
implementation 'com.google.android.gms:play-services-wallet:19.1.0'
|
||||||
implementation 'com.google.android.gms:play-services-safetynet:18.0.1'
|
|
||||||
implementation 'com.googlecode.mp4parser:isoparser:1.0.6'
|
implementation 'com.googlecode.mp4parser:isoparser:1.0.6'
|
||||||
implementation 'com.stripe:stripe-android:2.0.2'
|
implementation 'com.stripe:stripe-android:2.0.2'
|
||||||
implementation 'com.google.mlkit:language-id:16.1.1'
|
implementation 'com.google.mlkit:language-id:16.1.1'
|
||||||
implementation 'com.android.billingclient:billing:5.1.0'
|
implementation 'com.android.billingclient:billing:5.1.0'
|
||||||
implementation 'com.google.code.gson:gson:2.10'
|
implementation 'com.google.code.gson:gson:2.10'
|
||||||
implementation 'com.google.guava:guava:31.1-android'
|
implementation 'com.google.guava:guava:31.1-android'
|
||||||
|
implementation 'com.airbnb.android:lottie:6.4.0'
|
||||||
|
implementation 'com.google.android.play:integrity:1.3.0'
|
||||||
|
implementation 'com.google.android.gms:play-services-safetynet:18.0.1'
|
||||||
|
|
||||||
implementation 'com.google.android.gms:play-services-mlkit-subject-segmentation:16.0.0-beta1'
|
implementation 'com.google.android.gms:play-services-mlkit-subject-segmentation:16.0.0-beta1'
|
||||||
implementation 'com.google.android.gms:play-services-mlkit-image-labeling:16.0.8'
|
implementation 'com.google.android.gms:play-services-mlkit-image-labeling:16.0.8'
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
#include "tgnet/MTProtoScheme.h"
|
#include "tgnet/MTProtoScheme.h"
|
||||||
#include "tgnet/ConnectionSocket.h"
|
#include "tgnet/ConnectionSocket.h"
|
||||||
#include "tgnet/FileLog.h"
|
#include "tgnet/FileLog.h"
|
||||||
|
#include "tgnet/Handshake.h"
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/aes.h>
|
||||||
|
|
||||||
JavaVM *java;
|
JavaVM *java;
|
||||||
|
|
||||||
|
@ -31,6 +37,7 @@ jmethodID jclass_ConnectionsManager_onProxyError;
|
||||||
jmethodID jclass_ConnectionsManager_getHostByName;
|
jmethodID jclass_ConnectionsManager_getHostByName;
|
||||||
jmethodID jclass_ConnectionsManager_getInitFlags;
|
jmethodID jclass_ConnectionsManager_getInitFlags;
|
||||||
jmethodID jclass_ConnectionsManager_onPremiumFloodWait;
|
jmethodID jclass_ConnectionsManager_onPremiumFloodWait;
|
||||||
|
jmethodID jclass_ConnectionsManager_onIntegrityCheckClassic;
|
||||||
|
|
||||||
bool check_utf8(const char *data, size_t len);
|
bool check_utf8(const char *data, size_t len);
|
||||||
|
|
||||||
|
@ -133,6 +140,40 @@ void failNotRunningRequest(JNIEnv *env, jclass c, jint instanceNum, jint token)
|
||||||
return ConnectionsManager::getInstance(instanceNum).failNotRunningRequest(token);
|
return ConnectionsManager::getInstance(instanceNum).failNotRunningRequest(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void receivedIntegrityCheckClassic(JNIEnv *env, jclass c, jint instanceNum, jint requestToken, jstring nonce, jstring token) {
|
||||||
|
const char* nonceStr = env->GetStringUTFChars(nonce, 0);
|
||||||
|
const char* tokenStr = env->GetStringUTFChars(token, 0);
|
||||||
|
std::string nonceString = nonceStr;
|
||||||
|
std::string tokenString = tokenStr;
|
||||||
|
ConnectionsManager::getInstance(instanceNum).receivedIntegrityCheckClassic(requestToken, nonceString, tokenString);
|
||||||
|
if (nonceStr != nullptr) {
|
||||||
|
env->ReleaseStringUTFChars(nonce, nonceStr);
|
||||||
|
}
|
||||||
|
if (tokenStr != nullptr) {
|
||||||
|
env->ReleaseStringUTFChars(token, tokenStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jboolean isGoodPrime(JNIEnv *env, jclass c, jbyteArray prime, jint g) {
|
||||||
|
jsize length = env->GetArrayLength(prime);
|
||||||
|
jbyte *bytes = env->GetByteArrayElements(prime, NULL);
|
||||||
|
if (bytes == NULL) {
|
||||||
|
DEBUG_E("isGoodPrime: failed to get byte array");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsigned char *unsignedBytes = (unsigned char *)bytes;
|
||||||
|
BIGNUM *bn = BN_bin2bn(unsignedBytes, length, NULL);
|
||||||
|
if (bn == NULL) {
|
||||||
|
env->ReleaseByteArrayElements(prime, bytes, 0);
|
||||||
|
DEBUG_E("isGoodPrime: failed to convert byte array into BIGNUM");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool result = Handshake::isGoodPrime(bn, g);
|
||||||
|
BN_free(bn);
|
||||||
|
env->ReleaseByteArrayElements(prime, bytes, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void cleanUp(JNIEnv *env, jclass c, jint instanceNum, jboolean resetKeys) {
|
void cleanUp(JNIEnv *env, jclass c, jint instanceNum, jboolean resetKeys) {
|
||||||
return ConnectionsManager::getInstance(instanceNum).cleanUp(resetKeys, -1);
|
return ConnectionsManager::getInstance(instanceNum).cleanUp(resetKeys, -1);
|
||||||
}
|
}
|
||||||
|
@ -324,6 +365,13 @@ class Delegate : public ConnectiosManagerDelegate {
|
||||||
void onPremiumFloodWait(int32_t instanceNum, int32_t requestToken, bool isUpload) {
|
void onPremiumFloodWait(int32_t instanceNum, int32_t requestToken, bool isUpload) {
|
||||||
jniEnv[instanceNum]->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onPremiumFloodWait, instanceNum, requestToken, isUpload);
|
jniEnv[instanceNum]->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onPremiumFloodWait, instanceNum, requestToken, isUpload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onIntegrityCheckClassic(int32_t instanceNum, int32_t requestToken, std::string nonce) {
|
||||||
|
jstring nonceStr = jniEnv[instanceNum]->NewStringUTF(nonce.c_str());
|
||||||
|
jniEnv[instanceNum]->CallStaticVoidMethod(jclass_ConnectionsManager, jclass_ConnectionsManager_onIntegrityCheckClassic, instanceNum, requestToken, nonceStr);
|
||||||
|
jniEnv[instanceNum]->DeleteLocalRef(nonceStr);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void onHostNameResolved(JNIEnv *env, jclass c, jstring host, jlong address, jstring ip) {
|
void onHostNameResolved(JNIEnv *env, jclass c, jstring host, jlong address, jstring ip) {
|
||||||
|
@ -465,6 +513,8 @@ static JNINativeMethod ConnectionsManagerMethods[] = {
|
||||||
{"native_onHostNameResolved", "(Ljava/lang/String;JLjava/lang/String;)V", (void *) onHostNameResolved},
|
{"native_onHostNameResolved", "(Ljava/lang/String;JLjava/lang/String;)V", (void *) onHostNameResolved},
|
||||||
{"native_discardConnection", "(III)V", (void *) discardConnection},
|
{"native_discardConnection", "(III)V", (void *) discardConnection},
|
||||||
{"native_failNotRunningRequest", "(II)V", (void *) failNotRunningRequest},
|
{"native_failNotRunningRequest", "(II)V", (void *) failNotRunningRequest},
|
||||||
|
{"native_receivedIntegrityCheckClassic", "(IILjava/lang/String;Ljava/lang/String;)V", (void *) receivedIntegrityCheckClassic},
|
||||||
|
{"native_isGoodPrime", "([BI)Z", (void *) isGoodPrime},
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodsCount) {
|
inline int registerNativeMethods(JNIEnv *env, const char *className, JNINativeMethod *methods, int methodsCount) {
|
||||||
|
@ -577,6 +627,10 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
|
||||||
if (jclass_ConnectionsManager_onPremiumFloodWait == 0) {
|
if (jclass_ConnectionsManager_onPremiumFloodWait == 0) {
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
|
jclass_ConnectionsManager_onIntegrityCheckClassic = env->GetStaticMethodID(jclass_ConnectionsManager, "onIntegrityCheckClassic", "(IILjava/lang/String;)V");
|
||||||
|
if (jclass_ConnectionsManager_onIntegrityCheckClassic == 0) {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -810,6 +810,9 @@ MessageEntity *MessageEntity::TLdeserialize(NativeByteBuffer *stream, uint32_t c
|
||||||
result = new TL_messageEntityStrike();
|
result = new TL_messageEntityStrike();
|
||||||
break;
|
break;
|
||||||
case 0x20df5d0:
|
case 0x20df5d0:
|
||||||
|
result = new TL_messageEntityBlockquote_layer180();
|
||||||
|
break;
|
||||||
|
case 0xf1ccaaac:
|
||||||
result = new TL_messageEntityBlockquote();
|
result = new TL_messageEntityBlockquote();
|
||||||
break;
|
break;
|
||||||
case 0x9c4e7e8b:
|
case 0x9c4e7e8b:
|
||||||
|
@ -1001,11 +1004,24 @@ void TL_messageEntityStrike::serializeToStream(NativeByteBuffer *stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TL_messageEntityBlockquote::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
void TL_messageEntityBlockquote::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||||
|
flags = stream->readInt32(&error);
|
||||||
|
offset = stream->readInt32(&error);
|
||||||
|
length = stream->readInt32(&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TL_messageEntityBlockquote_layer180::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||||
offset = stream->readInt32(&error);
|
offset = stream->readInt32(&error);
|
||||||
length = stream->readInt32(&error);
|
length = stream->readInt32(&error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TL_messageEntityBlockquote::serializeToStream(NativeByteBuffer *stream) {
|
void TL_messageEntityBlockquote::serializeToStream(NativeByteBuffer *stream) {
|
||||||
|
stream->writeInt32(constructor);
|
||||||
|
stream->writeInt32(flags);
|
||||||
|
stream->writeInt32(offset);
|
||||||
|
stream->writeInt32(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TL_messageEntityBlockquote_layer180::serializeToStream(NativeByteBuffer *stream) {
|
||||||
stream->writeInt32(constructor);
|
stream->writeInt32(constructor);
|
||||||
stream->writeInt32(offset);
|
stream->writeInt32(offset);
|
||||||
stream->writeInt32(length);
|
stream->writeInt32(length);
|
||||||
|
|
|
@ -537,6 +537,7 @@ public:
|
||||||
class MessageEntity : public TLObject {
|
class MessageEntity : public TLObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int32_t flags;
|
||||||
int32_t offset;
|
int32_t offset;
|
||||||
int32_t length;
|
int32_t length;
|
||||||
std::string url;
|
std::string url;
|
||||||
|
@ -685,6 +686,15 @@ public:
|
||||||
|
|
||||||
class TL_messageEntityBlockquote : public MessageEntity {
|
class TL_messageEntityBlockquote : public MessageEntity {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const uint32_t constructor = 0xf1ccaaac;
|
||||||
|
|
||||||
|
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||||
|
void serializeToStream(NativeByteBuffer *stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
class TL_messageEntityBlockquote_layer180 : public MessageEntity {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint32_t constructor = 0x20df5d0;
|
static const uint32_t constructor = 0x20df5d0;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ void Connection::suspendConnection(bool idle) {
|
||||||
connectionState = idle ? TcpConnectionStageIdle : TcpConnectionStageSuspended;
|
connectionState = idle ? TcpConnectionStageIdle : TcpConnectionStageSuspended;
|
||||||
dropConnection();
|
dropConnection();
|
||||||
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionClosed(this, 0);
|
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionClosed(this, 0);
|
||||||
|
generation++;
|
||||||
firstPacketSent = false;
|
firstPacketSent = false;
|
||||||
if (restOfTheData != nullptr) {
|
if (restOfTheData != nullptr) {
|
||||||
restOfTheData->reuse();
|
restOfTheData->reuse();
|
||||||
|
@ -243,7 +244,11 @@ void Connection::onReceivedData(NativeByteBuffer *buffer) {
|
||||||
|
|
||||||
uint32_t old = buffer->limit();
|
uint32_t old = buffer->limit();
|
||||||
buffer->limit(buffer->position() + currentPacketLength);
|
buffer->limit(buffer->position() + currentPacketLength);
|
||||||
|
uint32_t current_generation = generation;
|
||||||
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionDataReceived(this, buffer, currentPacketLength);
|
ConnectionsManager::getInstance(currentDatacenter->instanceNum).onConnectionDataReceived(this, buffer, currentPacketLength);
|
||||||
|
if (current_generation != generation) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
buffer->position(buffer->limit());
|
buffer->position(buffer->limit());
|
||||||
buffer->limit(old);
|
buffer->limit(old);
|
||||||
|
|
||||||
|
@ -350,6 +355,7 @@ void Connection::connect() {
|
||||||
reconnectTimer->stop();
|
reconnectTimer->stop();
|
||||||
|
|
||||||
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) connecting (%s:%hu)", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, hostAddress.c_str(), hostPort);
|
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) connecting (%s:%hu)", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType, hostAddress.c_str(), hostPort);
|
||||||
|
generation++;
|
||||||
firstPacketSent = false;
|
firstPacketSent = false;
|
||||||
if (restOfTheData != nullptr) {
|
if (restOfTheData != nullptr) {
|
||||||
restOfTheData->reuse();
|
restOfTheData->reuse();
|
||||||
|
@ -657,6 +663,7 @@ void Connection::onDisconnectedInternal(int32_t reason, int32_t error) {
|
||||||
currentTimeout += 2;
|
currentTimeout += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
generation++;
|
||||||
firstPacketSent = false;
|
firstPacketSent = false;
|
||||||
if (restOfTheData != nullptr) {
|
if (restOfTheData != nullptr) {
|
||||||
restOfTheData->reuse();
|
restOfTheData->reuse();
|
||||||
|
|
|
@ -101,6 +101,7 @@ private:
|
||||||
int64_t usefullDataReceiveTime;
|
int64_t usefullDataReceiveTime;
|
||||||
uint32_t currentTimeout = 4;
|
uint32_t currentTimeout = 4;
|
||||||
uint32_t receivedDataAmount = 0;
|
uint32_t receivedDataAmount = 0;
|
||||||
|
uint32_t generation = 0;
|
||||||
|
|
||||||
uint8_t temp[64];
|
uint8_t temp[64];
|
||||||
|
|
||||||
|
|
|
@ -891,8 +891,11 @@ void ConnectionsManager::onConnectionDataReceived(Connection *connection, Native
|
||||||
TLObject *request;
|
TLObject *request;
|
||||||
if (datacenter->isHandshaking(connection->isMediaConnection)) {
|
if (datacenter->isHandshaking(connection->isMediaConnection)) {
|
||||||
request = datacenter->getCurrentHandshakeRequest(connection->isMediaConnection);
|
request = datacenter->getCurrentHandshakeRequest(connection->isMediaConnection);
|
||||||
|
if (request == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
request = getRequestWithMessageId(messageId);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
deserializingDatacenter = datacenter;
|
deserializingDatacenter = datacenter;
|
||||||
|
@ -1287,6 +1290,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
||||||
static std::string authRestart = "AUTH_RESTART";
|
static std::string authRestart = "AUTH_RESTART";
|
||||||
static std::string authKeyPermEmpty = "AUTH_KEY_PERM_EMPTY";
|
static std::string authKeyPermEmpty = "AUTH_KEY_PERM_EMPTY";
|
||||||
static std::string workerBusy = "WORKER_BUSY_TOO_LONG_RETRY";
|
static std::string workerBusy = "WORKER_BUSY_TOO_LONG_RETRY";
|
||||||
|
static std::string integrityCheckClassic = "INTEGRITY_CHECK_CLASSIC_";
|
||||||
bool processEvenFailed = error->error_code == 500 && error->error_message.find(authRestart) != std::string::npos;
|
bool processEvenFailed = error->error_code == 500 && error->error_message.find(authRestart) != std::string::npos;
|
||||||
bool isWorkerBusy = error->error_code == 500 && error->error_message.find(workerBusy) != std::string::npos;
|
bool isWorkerBusy = error->error_code == 500 && error->error_message.find(workerBusy) != std::string::npos;
|
||||||
if (LOGS_ENABLED) DEBUG_E("request %p rpc error %d: %s", request, error->error_code, error->error_message.c_str());
|
if (LOGS_ENABLED) DEBUG_E("request %p rpc error %d: %s", request, error->error_code, error->error_message.c_str());
|
||||||
|
@ -1301,8 +1305,19 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
||||||
saveConfig();
|
saveConfig();
|
||||||
datacenter->beginHandshake(connection->isMediaConnection ? HandshakeTypeMediaTemp : HandshakeTypeTemp, false);
|
datacenter->beginHandshake(connection->isMediaConnection ? HandshakeTypeMediaTemp : HandshakeTypeTemp, false);
|
||||||
}
|
}
|
||||||
} else if ((request->requestFlags & RequestFlagFailOnServerErrors) == 0 || processEvenFailed) {
|
} else if (error->error_code == 403 && error->error_message.find(integrityCheckClassic) != std::string::npos) {
|
||||||
if (error->error_code == 500 || error->error_code < 0) {
|
discardResponse = true;
|
||||||
|
std::string nonce = error->error_message.substr(integrityCheckClassic.size(), error->error_message.size() - integrityCheckClassic.size());
|
||||||
|
request->awaitingIntegrityCheck = true;
|
||||||
|
request->startTime = 0;
|
||||||
|
request->startTimeMillis = 0;
|
||||||
|
if (delegate != nullptr) {
|
||||||
|
delegate->onIntegrityCheckClassic(instanceNum, request->requestToken, nonce);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bool failServerErrors = (request->requestFlags & RequestFlagFailOnServerErrors) == 0 || processEvenFailed;
|
||||||
|
bool exceptFloodWait = (request->requestFlags & RequestFlagFailOnServerErrorsExceptFloodWait) != 0;
|
||||||
|
if (failServerErrors && (error->error_code == 500 || error->error_code < 0)) {
|
||||||
static std::string waitFailed = "MSG_WAIT_FAILED";
|
static std::string waitFailed = "MSG_WAIT_FAILED";
|
||||||
static std::string waitTimeout = "MSG_WAIT_TIMEOUT";
|
static std::string waitTimeout = "MSG_WAIT_TIMEOUT";
|
||||||
if (error->error_message.find(waitFailed) != std::string::npos) {
|
if (error->error_message.find(waitFailed) != std::string::npos) {
|
||||||
|
@ -1318,13 +1333,14 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
||||||
request->serverFailureCount++;
|
request->serverFailureCount++;
|
||||||
}
|
}
|
||||||
discardResponse = true;
|
discardResponse = true;
|
||||||
} else if (error->error_code == -504) {
|
} else if (failServerErrors && error->error_code == -504) {
|
||||||
discardResponse = (request->requestFlags & RequestFlagIgnoreFloodWait) == 0;
|
discardResponse = (request->requestFlags & RequestFlagIgnoreFloodWait) == 0;
|
||||||
request->failedByFloodWait = 2;
|
request->failedByFloodWait = 2;
|
||||||
request->startTime = 0;
|
request->startTime = 0;
|
||||||
request->startTimeMillis = 0;
|
request->startTimeMillis = 0;
|
||||||
request->minStartTime = (int32_t) (getCurrentTimeMonotonicMillis() / 1000 + 2);
|
request->minStartTime = (int32_t) (getCurrentTimeMonotonicMillis() / 1000 + 2);
|
||||||
} else if (
|
} else if (
|
||||||
|
(failServerErrors || exceptFloodWait) &&
|
||||||
error->error_code == 420 && (request->requestFlags & RequestFlagIgnoreFloodWait) == 0 &&
|
error->error_code == 420 && (request->requestFlags & RequestFlagIgnoreFloodWait) == 0 &&
|
||||||
error->error_message.find("STORY_SEND_FLOOD") == std::string::npos
|
error->error_message.find("STORY_SEND_FLOOD") == std::string::npos
|
||||||
) {
|
) {
|
||||||
|
@ -1363,7 +1379,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
||||||
if (isPremiumFloodWait && delegate != nullptr) {
|
if (isPremiumFloodWait && delegate != nullptr) {
|
||||||
delegate->onPremiumFloodWait(instanceNum, request->requestToken, (request->connectionType & ConnectionTypeUpload) != 0);
|
delegate->onPremiumFloodWait(instanceNum, request->requestToken, (request->connectionType & ConnectionTypeUpload) != 0);
|
||||||
}
|
}
|
||||||
} else if (error->error_code == 400) {
|
} else if (failServerErrors && error->error_code == 400) {
|
||||||
static std::string waitFailed = "MSG_WAIT_FAILED";
|
static std::string waitFailed = "MSG_WAIT_FAILED";
|
||||||
static std::string bindFailed = "ENCRYPTED_MESSAGE_INVALID";
|
static std::string bindFailed = "ENCRYPTED_MESSAGE_INVALID";
|
||||||
static std::string waitTimeout = "MSG_WAIT_TIMEOUT";
|
static std::string waitTimeout = "MSG_WAIT_TIMEOUT";
|
||||||
|
@ -2154,6 +2170,32 @@ void ConnectionsManager::failNotRunningRequest(int32_t token) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConnectionsManager::receivedIntegrityCheckClassic(int32_t requestToken, std::string nonce, std::string token) {
|
||||||
|
scheduleTask([&, requestToken, nonce, token] {
|
||||||
|
for (auto iter = runningRequests.begin(); iter != runningRequests.end(); iter++) {
|
||||||
|
Request *request = iter->get();
|
||||||
|
if (requestToken != 0 && request->requestToken == requestToken) {
|
||||||
|
auto invokeIntegrity = new invokeWithGooglePlayIntegrity();
|
||||||
|
invokeIntegrity->nonce = nonce;
|
||||||
|
invokeIntegrity->token = token;
|
||||||
|
invokeIntegrity->query = std::move(request->rpcRequest);
|
||||||
|
request->rpcRequest = std::unique_ptr<invokeWithGooglePlayIntegrity>(invokeIntegrity);
|
||||||
|
|
||||||
|
request->awaitingIntegrityCheck = false;
|
||||||
|
request->requestFlags &=~ RequestFlagFailOnServerErrors;
|
||||||
|
|
||||||
|
if (LOGS_ENABLED) DEBUG_D("account%d: received integrity token, wrapping %s", instanceNum, token.c_str());
|
||||||
|
|
||||||
|
processRequestQueue(request->connectionType, request->datacenterId);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LOGS_ENABLED) DEBUG_E("account%d: received integrity token but no request %d found", instanceNum, requestToken);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void ConnectionsManager::onDatacenterHandshakeComplete(Datacenter *datacenter, HandshakeType type, int32_t timeDiff) {
|
void ConnectionsManager::onDatacenterHandshakeComplete(Datacenter *datacenter, HandshakeType type, int32_t timeDiff) {
|
||||||
saveConfig();
|
saveConfig();
|
||||||
uint32_t datacenterId = datacenter->getDatacenterId();
|
uint32_t datacenterId = datacenter->getDatacenterId();
|
||||||
|
@ -2474,13 +2516,13 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
|
||||||
forceThisRequest = false;
|
forceThisRequest = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forceThisRequest || (
|
if ((forceThisRequest || (
|
||||||
abs(currentTime - request->startTime) > maxTimeout && (
|
abs(currentTime - request->startTime) > maxTimeout && (
|
||||||
currentTime >= request->minStartTime ||
|
currentTime >= request->minStartTime ||
|
||||||
(request->failedByFloodWait != 0 && (request->minStartTime - currentTime) > request->failedByFloodWait) ||
|
(request->failedByFloodWait != 0 && (request->minStartTime - currentTime) > request->failedByFloodWait) ||
|
||||||
(request->failedByFloodWait == 0 && abs(currentTime - request->minStartTime) >= 60)
|
(request->failedByFloodWait == 0 && abs(currentTime - request->minStartTime) >= 60)
|
||||||
)
|
)
|
||||||
)) {
|
)) && !request->awaitingIntegrityCheck) {
|
||||||
if (!forceThisRequest && request->connectionToken > 0) {
|
if (!forceThisRequest && request->connectionToken > 0) {
|
||||||
if ((request->connectionType & ConnectionTypeGeneric || request->connectionType & ConnectionTypeTemp) && request->connectionToken == connection->getConnectionToken()) {
|
if ((request->connectionType & ConnectionTypeGeneric || request->connectionType & ConnectionTypeTemp) && request->connectionToken == connection->getConnectionToken()) {
|
||||||
if (LOGS_ENABLED) DEBUG_D("request token is valid, not retrying %s (%p)", typeInfo.name(), request->rawRequest);
|
if (LOGS_ENABLED) DEBUG_D("request token is valid, not retrying %s (%p)", typeInfo.name(), request->rawRequest);
|
||||||
|
@ -3519,12 +3561,9 @@ void ConnectionsManager::applyDnsConfig(NativeByteBuffer *buffer, std::string ph
|
||||||
if (LOGS_ENABLED) DEBUG_D("can't decrypt dns config");
|
if (LOGS_ENABLED) DEBUG_D("can't decrypt dns config");
|
||||||
} else {
|
} else {
|
||||||
delete config;
|
delete config;
|
||||||
if (LOGS_ENABLED) DEBUG_D("dns config not valid due to date or expire");
|
if (LOGS_ENABLED) DEBUG_D("dns config not valid due to date or expire, current date = %d, config date = %d, config expired = %d", currentDate, config->date, config->expires);
|
||||||
}
|
}
|
||||||
if (requestingSecondAddress == 2) {
|
if (requestingSecondAddress == 1) {
|
||||||
requestingSecondAddress = 3;
|
|
||||||
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
|
||||||
} else if (requestingSecondAddress == 1) {
|
|
||||||
requestingSecondAddress = 2;
|
requestingSecondAddress = 2;
|
||||||
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
||||||
} else if (requestingSecondAddress == 0) {
|
} else if (requestingSecondAddress == 0) {
|
||||||
|
|
|
@ -82,6 +82,7 @@ public:
|
||||||
|
|
||||||
void reconnect(int32_t datacentrId, int32_t connectionType);
|
void reconnect(int32_t datacentrId, int32_t connectionType);
|
||||||
void failNotRunningRequest(int32_t token);
|
void failNotRunningRequest(int32_t token);
|
||||||
|
void receivedIntegrityCheckClassic(int32_t requestToken, std::string nonce, std::string token);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void *ThreadProc(void *data);
|
static void *ThreadProc(void *data);
|
||||||
|
|
|
@ -593,14 +593,26 @@ void Datacenter::serializeToStream(NativeByteBuffer *stream) {
|
||||||
}
|
}
|
||||||
stream->writeInt64(authKeyMediaTempId);
|
stream->writeInt64(authKeyMediaTempId);
|
||||||
stream->writeInt32(authorized ? 1 : 0);
|
stream->writeInt32(authorized ? 1 : 0);
|
||||||
stream->writeInt32((int32_t) (size = serverSalts.size()));
|
|
||||||
for (uint32_t a = 0; a < size; a++) {
|
size = 0;
|
||||||
|
for (uint32_t a = 0; a < serverSalts.size(); a++) {
|
||||||
|
if (serverSalts[a] != nullptr) size++;
|
||||||
|
}
|
||||||
|
stream->writeInt32((int32_t) size);
|
||||||
|
for (uint32_t a = 0; a < serverSalts.size(); a++) {
|
||||||
|
if (serverSalts[a] == nullptr) continue;
|
||||||
stream->writeInt32(serverSalts[a]->valid_since);
|
stream->writeInt32(serverSalts[a]->valid_since);
|
||||||
stream->writeInt32(serverSalts[a]->valid_until);
|
stream->writeInt32(serverSalts[a]->valid_until);
|
||||||
stream->writeInt64(serverSalts[a]->salt);
|
stream->writeInt64(serverSalts[a]->salt);
|
||||||
}
|
}
|
||||||
stream->writeInt32((int32_t) (size = mediaServerSalts.size()));
|
|
||||||
for (uint32_t a = 0; a < size; a++) {
|
size = 0;
|
||||||
|
for (uint32_t a = 0; a < mediaServerSalts.size(); a++) {
|
||||||
|
if (mediaServerSalts[a] != nullptr) size++;
|
||||||
|
}
|
||||||
|
stream->writeInt32((int32_t) size);
|
||||||
|
for (uint32_t a = 0; a < mediaServerSalts.size(); a++) {
|
||||||
|
if (mediaServerSalts[a] == nullptr) continue;
|
||||||
stream->writeInt32(mediaServerSalts[a]->valid_since);
|
stream->writeInt32(mediaServerSalts[a]->valid_since);
|
||||||
stream->writeInt32(mediaServerSalts[a]->valid_until);
|
stream->writeInt32(mediaServerSalts[a]->valid_until);
|
||||||
stream->writeInt64(mediaServerSalts[a]->salt);
|
stream->writeInt64(mediaServerSalts[a]->salt);
|
||||||
|
|
|
@ -154,6 +154,7 @@ typedef struct ConnectiosManagerDelegate {
|
||||||
virtual void getHostByName(std::string domain, int32_t instanceNum, ConnectionSocket *socket) = 0;
|
virtual void getHostByName(std::string domain, int32_t instanceNum, ConnectionSocket *socket) = 0;
|
||||||
virtual int32_t getInitFlags(int32_t instanceNum) = 0;
|
virtual int32_t getInitFlags(int32_t instanceNum) = 0;
|
||||||
virtual void onPremiumFloodWait(int32_t instanceNum, int32_t requestToken, bool isUpload) = 0;
|
virtual void onPremiumFloodWait(int32_t instanceNum, int32_t requestToken, bool isUpload) = 0;
|
||||||
|
virtual void onIntegrityCheckClassic(int32_t instanceNum, int32_t requestToken, std::string nonce) = 0;
|
||||||
} ConnectiosManagerDelegate;
|
} ConnectiosManagerDelegate;
|
||||||
|
|
||||||
typedef struct HandshakeDelegate {
|
typedef struct HandshakeDelegate {
|
||||||
|
@ -175,7 +176,8 @@ enum RequestFlag {
|
||||||
RequestFlagResendAfter = 512,
|
RequestFlagResendAfter = 512,
|
||||||
RequestFlagIgnoreFloodWait = 1024,
|
RequestFlagIgnoreFloodWait = 1024,
|
||||||
RequestFlagListenAfterCancel = 2048,
|
RequestFlagListenAfterCancel = 2048,
|
||||||
RequestFlagIsCancel = 32768
|
RequestFlagIsCancel = 32768,
|
||||||
|
RequestFlagFailOnServerErrorsExceptFloodWait = 65536
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::string to_string_int32(int32_t value) {
|
inline std::string to_string_int32(int32_t value) {
|
||||||
|
|
|
@ -206,10 +206,13 @@ inline bool check_prime(BIGNUM *p) {
|
||||||
return result != 0;
|
return result != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isGoodPrime(BIGNUM *p, uint32_t g) {
|
bool Handshake::isGoodPrime(BIGNUM *p, uint32_t g) {
|
||||||
if (g < 2 || g > 7 || BN_num_bits(p) != 2048) {
|
if (g < 2 || g > 7 || BN_num_bits(p) != 2048) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (bnContext == nullptr) {
|
||||||
|
bnContext = BN_CTX_new();
|
||||||
|
}
|
||||||
|
|
||||||
BIGNUM *t = BN_new();
|
BIGNUM *t = BN_new();
|
||||||
BIGNUM *dh_g = BN_new();
|
BIGNUM *dh_g = BN_new();
|
||||||
|
@ -657,7 +660,7 @@ void Handshake::processHandshakeResponse_serverDHParams(TLObject *message, int64
|
||||||
if (LOGS_ENABLED) DEBUG_E("can't allocate BIGNUM p");
|
if (LOGS_ENABLED) DEBUG_E("can't allocate BIGNUM p");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (!isGoodPrime(p, dhInnerData->g)) {
|
if (!Handshake::isGoodPrime(p, dhInnerData->g)) {
|
||||||
if (LOGS_ENABLED) DEBUG_E("account%u dc%u handshake: bad prime, type = %d", currentDatacenter->instanceNum, currentDatacenter->datacenterId, handshakeType);
|
if (LOGS_ENABLED) DEBUG_E("account%u dc%u handshake: bad prime, type = %d", currentDatacenter->instanceNum, currentDatacenter->datacenterId, handshakeType);
|
||||||
beginHandshake(false);
|
beginHandshake(false);
|
||||||
BN_free(p);
|
BN_free(p);
|
||||||
|
@ -826,9 +829,11 @@ void Handshake::processHandshakeResponse_serverDHParamsAnswer(TLObject *message,
|
||||||
handshakeRequest = nullptr;
|
handshakeRequest = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<TL_future_salt> salt = std::unique_ptr<TL_future_salt>(handshakeServerSalt);
|
|
||||||
currentDatacenter->clearServerSalts(handshakeType == HandshakeTypeMediaTemp);
|
currentDatacenter->clearServerSalts(handshakeType == HandshakeTypeMediaTemp);
|
||||||
currentDatacenter->addServerSalt(salt, handshakeType == HandshakeTypeMediaTemp);
|
if (handshakeServerSalt != nullptr) {
|
||||||
|
std::unique_ptr<TL_future_salt> salt = std::unique_ptr<TL_future_salt>(handshakeServerSalt);
|
||||||
|
currentDatacenter->addServerSalt(salt, handshakeType == HandshakeTypeMediaTemp);
|
||||||
|
}
|
||||||
handshakeServerSalt = nullptr;
|
handshakeServerSalt = nullptr;
|
||||||
|
|
||||||
if (handshakeType == HandshakeTypePerm) {
|
if (handshakeType == HandshakeTypePerm) {
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "Defines.h"
|
#include "Defines.h"
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
|
||||||
class Datacenter;
|
class Datacenter;
|
||||||
class ByteArray;
|
class ByteArray;
|
||||||
|
@ -37,6 +38,7 @@ public:
|
||||||
ByteArray *getPendingAuthKey();
|
ByteArray *getPendingAuthKey();
|
||||||
int64_t getPendingAuthKeyId();
|
int64_t getPendingAuthKeyId();
|
||||||
TLObject *getCurrentHandshakeRequest();
|
TLObject *getCurrentHandshakeRequest();
|
||||||
|
static bool isGoodPrime(BIGNUM *p, uint32_t g);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -941,6 +941,13 @@ void invokeWithLayer::serializeToStream(NativeByteBuffer *stream) {
|
||||||
query->serializeToStream(stream);
|
query->serializeToStream(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void invokeWithGooglePlayIntegrity::serializeToStream(NativeByteBuffer *stream) {
|
||||||
|
stream->writeInt32(constructor);
|
||||||
|
stream->writeString(nonce);
|
||||||
|
stream->writeString(token);
|
||||||
|
query->serializeToStream(stream);
|
||||||
|
}
|
||||||
|
|
||||||
void TL_inputClientProxy::serializeToStream(NativeByteBuffer *stream) {
|
void TL_inputClientProxy::serializeToStream(NativeByteBuffer *stream) {
|
||||||
stream->writeInt32(constructor);
|
stream->writeInt32(constructor);
|
||||||
stream->writeString(address);
|
stream->writeString(address);
|
||||||
|
|
|
@ -730,6 +730,18 @@ public:
|
||||||
void serializeToStream(NativeByteBuffer *stream);
|
void serializeToStream(NativeByteBuffer *stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class invokeWithGooglePlayIntegrity : public TLObject {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const uint32_t constructor = 0x1df92984;
|
||||||
|
|
||||||
|
std::string nonce;
|
||||||
|
std::string token;
|
||||||
|
std::unique_ptr<TLObject> query;
|
||||||
|
|
||||||
|
void serializeToStream(NativeByteBuffer *stream);
|
||||||
|
};
|
||||||
|
|
||||||
class TL_inputClientProxy : public TLObject {
|
class TL_inputClientProxy : public TLObject {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -35,6 +35,7 @@ public:
|
||||||
uint32_t retryCount = 0;
|
uint32_t retryCount = 0;
|
||||||
bool failedBySalt = false;
|
bool failedBySalt = false;
|
||||||
int32_t failedByFloodWait = 0;
|
int32_t failedByFloodWait = 0;
|
||||||
|
bool awaitingIntegrityCheck = false;
|
||||||
bool premiumFloodWait = false;
|
bool premiumFloodWait = false;
|
||||||
ConnectionType connectionType;
|
ConnectionType connectionType;
|
||||||
uint32_t requestFlags;
|
uint32_t requestFlags;
|
||||||
|
|
|
@ -803,7 +803,7 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setBuffer
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setNetworkType(JNIEnv *env, jobject obj, jint networkType) {
|
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setNetworkType(JNIEnv *env, jobject obj, jint networkType) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
instance->nativeInstance->setNetworkType(parseNetworkType(networkType));
|
instance->nativeInstance->setNetworkType(parseNetworkType(networkType));
|
||||||
|
@ -830,7 +830,7 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setVolume
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setAudioOutputGainControlEnabled(JNIEnv *env, jobject obj, jboolean enabled) {
|
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setAudioOutputGainControlEnabled(JNIEnv *env, jobject obj, jboolean enabled) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
instance->nativeInstance->setAudioOutputGainControlEnabled(enabled);
|
instance->nativeInstance->setAudioOutputGainControlEnabled(enabled);
|
||||||
|
@ -839,7 +839,7 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setAudioO
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setEchoCancellationStrength(JNIEnv *env, jobject obj, jint strength) {
|
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setEchoCancellationStrength(JNIEnv *env, jobject obj, jint strength) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
instance->nativeInstance->setEchoCancellationStrength(strength);
|
instance->nativeInstance->setEchoCancellationStrength(strength);
|
||||||
|
@ -848,7 +848,7 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setEchoCa
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jstring JNICALL Java_org_telegram_messenger_voip_NativeInstance_getLastError(JNIEnv *env, jobject obj) {
|
JNIEXPORT jstring JNICALL Java_org_telegram_messenger_voip_NativeInstance_getLastError(JNIEnv *env, jobject obj) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return env->NewStringUTF(instance->nativeInstance->getLastError().c_str());
|
return env->NewStringUTF(instance->nativeInstance->getLastError().c_str());
|
||||||
|
@ -857,7 +857,7 @@ JNIEXPORT jstring JNICALL Java_org_telegram_messenger_voip_NativeInstance_getLas
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jstring JNICALL Java_org_telegram_messenger_voip_NativeInstance_getDebugInfo(JNIEnv *env, jobject obj) {
|
JNIEXPORT jstring JNICALL Java_org_telegram_messenger_voip_NativeInstance_getDebugInfo(JNIEnv *env, jobject obj) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return env->NewStringUTF(instance->nativeInstance->getDebugInfo().c_str());
|
return env->NewStringUTF(instance->nativeInstance->getDebugInfo().c_str());
|
||||||
|
@ -866,7 +866,7 @@ JNIEXPORT jstring JNICALL Java_org_telegram_messenger_voip_NativeInstance_getDeb
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_getPreferredRelayId(JNIEnv *env, jobject obj) {
|
JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_getPreferredRelayId(JNIEnv *env, jobject obj) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return instance->nativeInstance->getPreferredRelayId();
|
return instance->nativeInstance->getPreferredRelayId();
|
||||||
|
@ -875,7 +875,7 @@ JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_getPrefe
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jobject JNICALL Java_org_telegram_messenger_voip_NativeInstance_getTrafficStats(JNIEnv *env, jobject obj) {
|
JNIEXPORT jobject JNICALL Java_org_telegram_messenger_voip_NativeInstance_getTrafficStats(JNIEnv *env, jobject obj) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return asJavaTrafficStats(env, instance->nativeInstance->getTrafficStats());
|
return asJavaTrafficStats(env, instance->nativeInstance->getTrafficStats());
|
||||||
|
@ -884,7 +884,7 @@ JNIEXPORT jobject JNICALL Java_org_telegram_messenger_voip_NativeInstance_getTra
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jbyteArray JNICALL Java_org_telegram_messenger_voip_NativeInstance_getPersistentState(JNIEnv *env, jobject obj) {
|
JNIEXPORT jbyteArray JNICALL Java_org_telegram_messenger_voip_NativeInstance_getPersistentState(JNIEnv *env, jobject obj) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return copyVectorToJavaByteArray(env, instance->nativeInstance->getPersistentState().value);
|
return copyVectorToJavaByteArray(env, instance->nativeInstance->getPersistentState().value);
|
||||||
|
@ -893,7 +893,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_telegram_messenger_voip_NativeInstance_get
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_stopNative(JNIEnv *env, jobject obj) {
|
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_stopNative(JNIEnv *env, jobject obj) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
instance->nativeInstance->stop([instance](const FinalState& finalState) {
|
instance->nativeInstance->stop([instance](const FinalState& finalState) {
|
||||||
|
@ -920,7 +920,7 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_stopGroup
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_onStreamPartAvailable(JNIEnv *env, jobject obj, jlong ts, jobject byteBuffer, jint size, jlong responseTs, jint videoChannel, jint quality) {
|
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_onStreamPartAvailable(JNIEnv *env, jobject obj, jlong ts, jobject byteBuffer, jint size, jlong responseTs, jint videoChannel, jint quality) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->groupNativeInstance == nullptr) {
|
if (instance == nullptr || instance->groupNativeInstance == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto context = (AndroidContext *) instance->_platformContext.get();
|
auto context = (AndroidContext *) instance->_platformContext.get();
|
||||||
|
@ -1099,7 +1099,7 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setupOutg
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_onSignalingDataReceive(JNIEnv *env, jobject obj, jbyteArray value) {
|
JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_onSignalingDataReceive(JNIEnv *env, jobject obj, jbyteArray value) {
|
||||||
InstanceHolder *instance = getInstanceHolder(env, obj);
|
InstanceHolder *instance = getInstanceHolder(env, obj);
|
||||||
if (instance->nativeInstance == nullptr) {
|
if (instance == nullptr || instance->nativeInstance == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
chat_BlurAlpha=-1056964608
|
chat_BlurAlpha=-872415232
|
||||||
|
chat_BlurAlphaSlow=-1056964608
|
||||||
chat_unreadMessagesStartText=-14512671
|
chat_unreadMessagesStartText=-14512671
|
||||||
chat_inFileBackgroundSelected=-2823172
|
chat_inFileBackgroundSelected=-2823172
|
||||||
radioBackgroundChecked=-14638337
|
radioBackgroundChecked=-14638337
|
||||||
|
|
|
@ -182,3 +182,5 @@ chat_outReplyMediaMessageSelectedText=-8674357
|
||||||
chats_attachMessage=-14843710
|
chats_attachMessage=-14843710
|
||||||
chat_outSentClock=-594761027
|
chat_outSentClock=-594761027
|
||||||
chat_searchPanelText=-12609056
|
chat_searchPanelText=-12609056
|
||||||
|
table_background=-526345
|
||||||
|
table_border=-2039584
|
||||||
|
|
|
@ -398,7 +398,8 @@ windowBackgroundWhiteGrayText4=-931296359
|
||||||
chat_inTimeText=-645885536
|
chat_inTimeText=-645885536
|
||||||
dialogRadioBackground=-11245959
|
dialogRadioBackground=-11245959
|
||||||
statisticChartRipple=748994002
|
statisticChartRipple=748994002
|
||||||
chat_BlurAlpha=-520093696
|
chat_BlurAlpha=-1308622848
|
||||||
|
chat_BlurAlphaSlow=-872415232
|
||||||
chat_outReplyMessageText=-1
|
chat_outReplyMessageText=-1
|
||||||
chat_recordedVoiceDot=-1221292
|
chat_recordedVoiceDot=-1221292
|
||||||
chat_messagePanelBackground=-14602949
|
chat_messagePanelBackground=-14602949
|
||||||
|
@ -440,3 +441,5 @@ code_string=-7806088
|
||||||
code_operator=2147483647
|
code_operator=2147483647
|
||||||
code_number=-10887465
|
code_number=-10887465
|
||||||
code_comment=2147483647
|
code_comment=2147483647
|
||||||
|
table_background=177390847
|
||||||
|
table_border=436207615
|
||||||
|
|
|
@ -48,6 +48,8 @@ chat_outSentCheckRead=-167772161
|
||||||
chat_unreadMessagesStartArrowIcon=-3741702
|
chat_unreadMessagesStartArrowIcon=-3741702
|
||||||
chat_stickerReplyLine=-13527843
|
chat_stickerReplyLine=-13527843
|
||||||
windowBackgroundWhiteBlackText=-13421773
|
windowBackgroundWhiteBlackText=-13421773
|
||||||
|
table_background=-526345
|
||||||
|
table_border=-2039584
|
||||||
avatar_backgroundActionBarBlue=-1
|
avatar_backgroundActionBarBlue=-1
|
||||||
dialogTextLink=-14317077
|
dialogTextLink=-14317077
|
||||||
chat_status=-16284199
|
chat_status=-16284199
|
||||||
|
|
|
@ -421,7 +421,8 @@ windowBackgroundWhiteGrayText4=-9803158
|
||||||
chat_inTimeText=-8552575
|
chat_inTimeText=-8552575
|
||||||
dialogRadioBackground=-10855846
|
dialogRadioBackground=-10855846
|
||||||
statisticChartRipple=748994002
|
statisticChartRipple=748994002
|
||||||
chat_BlurAlpha=-1056964608
|
chat_BlurAlpha=-1308622848
|
||||||
|
chat_BlurAlphaSlow=-1056964608
|
||||||
chat_outBubbleGradient=-12874567
|
chat_outBubbleGradient=-12874567
|
||||||
chat_outReplyMessageText=-1
|
chat_outReplyMessageText=-1
|
||||||
chat_recordedVoiceDot=-1221292
|
chat_recordedVoiceDot=-1221292
|
||||||
|
@ -465,3 +466,5 @@ code_string=-7806088
|
||||||
code_operator=2147483647
|
code_operator=2147483647
|
||||||
code_number=-10887465
|
code_number=-10887465
|
||||||
code_comment=2147483647
|
code_comment=2147483647
|
||||||
|
table_background=177390847
|
||||||
|
table_border=436207615
|
||||||
|
|
|
@ -6,10 +6,10 @@ uniform sampler2D u_BackgroundTexture;
|
||||||
uniform float f_xOffset;
|
uniform float f_xOffset;
|
||||||
uniform float f_alpha;
|
uniform float f_alpha;
|
||||||
uniform mat4 world;
|
uniform mat4 world;
|
||||||
uniform vec3 modelViewVertex;
|
|
||||||
|
|
||||||
varying vec3 vNormal;
|
varying vec3 vNormal;
|
||||||
varying vec2 vUV;
|
varying vec2 vUV;
|
||||||
|
varying vec3 modelViewVertex;
|
||||||
|
|
||||||
vec3 cameraPosition = vec3(0, 0, 100);
|
vec3 cameraPosition = vec3(0, 0, 100);
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ void main() {
|
||||||
vec3 finalNormal = normalize(vNormalW + vTextureNormal);
|
vec3 finalNormal = normalize(vNormalW + vTextureNormal);
|
||||||
|
|
||||||
vec3 color = texture2D(u_Texture, vUV ).xyz;
|
vec3 color = texture2D(u_Texture, vUV ).xyz;
|
||||||
vec3 viewDirectionW = normalize(cameraPosition - modelViewVertex);
|
vec3 viewDirectionW = normalize(cameraPosition);
|
||||||
|
|
||||||
vec3 angleW = normalize(viewDirectionW + vLightPosition2);
|
vec3 angleW = normalize(viewDirectionW + vLightPosition2);
|
||||||
float specComp2 = max(0., dot(vNormalW, angleW));
|
float specComp2 = max(0., dot(vNormalW, angleW));
|
||||||
|
|
93
TMessagesProj/src/main/assets/shaders/fragment4.glsl
Normal file
93
TMessagesProj/src/main/assets/shaders/fragment4.glsl
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
uniform sampler2D u_Texture;
|
||||||
|
uniform sampler2D u_NormalMap;
|
||||||
|
uniform sampler2D u_BackgroundTexture;
|
||||||
|
uniform float f_xOffset;
|
||||||
|
uniform float f_alpha;
|
||||||
|
uniform mat4 world;
|
||||||
|
|
||||||
|
varying vec3 vNormal;
|
||||||
|
varying vec2 vUV;
|
||||||
|
varying vec3 modelViewVertex;
|
||||||
|
|
||||||
|
uniform float spec1;
|
||||||
|
uniform float spec2;
|
||||||
|
uniform float u_diffuse;
|
||||||
|
uniform float normalSpec;
|
||||||
|
uniform vec3 gradientColor1;
|
||||||
|
uniform vec3 gradientColor2;
|
||||||
|
uniform vec3 normalSpecColor;
|
||||||
|
uniform vec3 specColor;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform vec4 gradientPosition;
|
||||||
|
uniform int modelIndex;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
|
||||||
|
vec3 pos = modelViewVertex / 100.0 + .5;
|
||||||
|
float specTexture = texture2D(u_Texture, vUV).y * clamp(vNormal.z, 0.0, 1.0);
|
||||||
|
|
||||||
|
float gradientMix = distance(pos.xy, vec2(1, 1));
|
||||||
|
gradientMix -= .05 * specTexture;
|
||||||
|
gradientMix = clamp(gradientMix, 0.0, 1.0);
|
||||||
|
vec4 color = vec4(mix(gradientColor1, gradientColor2, gradientMix), 1.0);
|
||||||
|
|
||||||
|
vec3 norm = normalize(vec3(world * vec4(vNormal, 0.0)));
|
||||||
|
|
||||||
|
// vec3 flecksLightPos = vec3(.5, .5, 0.0);
|
||||||
|
// vec3 flecksLightDir = normalize(flecksLightPos - pos);
|
||||||
|
// vec3 flecksReflectDir = reflect(-flecksLightDir, norm);
|
||||||
|
// float flecksSpec = pow(max(dot(normalize(vec3(0.0) - pos), flecksReflectDir), 0.0), 8.0);
|
||||||
|
vec3 flecksNormal = normalize(1.0 - texture2D(u_NormalMap, vUV + .7 * vec2(-f_xOffset, f_xOffset)).xyz);
|
||||||
|
float flecks = clamp(flecksNormal.x, 0.0, 1.0);
|
||||||
|
// norm = normalize(norm + flecksSpec * abs(vNormal.z) * flecksNormal);
|
||||||
|
|
||||||
|
vec3 lightPos = vec3(-3., -3., 20.);
|
||||||
|
vec3 lightDir = normalize(lightPos - pos);
|
||||||
|
float diffuse = max(dot(norm, lightDir), 0.0);
|
||||||
|
|
||||||
|
float spec = 0.0;
|
||||||
|
|
||||||
|
lightPos = vec3(-1., .7, .2);
|
||||||
|
spec += specTexture * clamp(2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0) / 6.0;
|
||||||
|
lightPos = vec3(8., .7, .5);
|
||||||
|
spec += specTexture * clamp(2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0) / 6.0;
|
||||||
|
|
||||||
|
float notSpecTexture = mix(1.0, 0.3, specTexture);
|
||||||
|
lightPos = vec3(-3., -3., .5);
|
||||||
|
spec += clamp(2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0) / 4.0;
|
||||||
|
|
||||||
|
lightPos = vec3(4., 3., 2.5);
|
||||||
|
spec += clamp(1.5 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0) / 6.0;
|
||||||
|
|
||||||
|
lightPos = vec3(-33., .5, 30.);
|
||||||
|
spec += clamp(2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0) / 12.0;
|
||||||
|
|
||||||
|
spec = clamp(spec, 0.0, 0.7);
|
||||||
|
|
||||||
|
lightPos = vec3(10., .5, 3.3);
|
||||||
|
spec += mix(0.8, 1.0, specTexture) * clamp(2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0) / 8.0;
|
||||||
|
|
||||||
|
lightPos = vec3(-10., .5, 3.7);
|
||||||
|
spec += mix(0.8, 1.0, specTexture) * clamp(2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0) / 8.0;
|
||||||
|
|
||||||
|
lightPos = vec3(.5, 12., 1.5);
|
||||||
|
spec += mix(0.8, 1.0, specTexture) * clamp(2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0) / 8.0;
|
||||||
|
|
||||||
|
spec = clamp(spec, 0.0, 0.9);
|
||||||
|
|
||||||
|
color = mix(vec4(vec3(0.0), 1.0), color, .8 + .3 * diffuse);
|
||||||
|
vec4 specColor = vec4(mix(1.8, 2.0, specTexture) * gradientColor1, 1.0);
|
||||||
|
color = mix(color, specColor, spec);
|
||||||
|
|
||||||
|
float flecksSpec = 0.0;
|
||||||
|
lightPos = vec3(1.2, -.2, .5);
|
||||||
|
flecksSpec += clamp(2.0 * pow(max(dot(normalize(vec3(0.0) - pos), reflect(-normalize(lightPos - pos), norm)), 0.0), 2.0), 0.0, 1.0);
|
||||||
|
|
||||||
|
color = mix(color, specColor,
|
||||||
|
clamp(flecksSpec * abs(vNormal.z) * (flecksNormal.z), 0.2, 0.3) - .2
|
||||||
|
);
|
||||||
|
|
||||||
|
gl_FragColor = color * f_alpha;
|
||||||
|
}
|
|
@ -2,15 +2,15 @@ uniform mat4 uMVPMatrix;
|
||||||
|
|
||||||
attribute vec2 a_TexCoordinate;
|
attribute vec2 a_TexCoordinate;
|
||||||
attribute vec3 a_Normal;
|
attribute vec3 a_Normal;
|
||||||
attribute vec4 vPosition;
|
attribute vec3 vPosition;
|
||||||
|
|
||||||
varying vec3 vNormal;
|
varying vec3 vNormal;
|
||||||
varying vec2 vUV;
|
varying vec2 vUV;
|
||||||
varying vec3 modelViewVertex;
|
varying vec3 modelViewVertex;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
modelViewVertex = vec3(uMVPMatrix * vPosition);
|
|
||||||
vUV = a_TexCoordinate;
|
vUV = a_TexCoordinate;
|
||||||
vNormal = a_Normal;
|
vNormal = a_Normal;
|
||||||
gl_Position = uMVPMatrix * vPosition;
|
gl_Position = uMVPMatrix * vec4(vPosition, 1.0);
|
||||||
|
modelViewVertex = vec3(gl_Position);
|
||||||
}
|
}
|
|
@ -45,6 +45,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator {
|
||||||
public static final long DEFAULT_DURATION = 250;
|
public static final long DEFAULT_DURATION = 250;
|
||||||
public static final Interpolator DEFAULT_INTERPOLATOR = new CubicBezierInterpolator(0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625);
|
public static final Interpolator DEFAULT_INTERPOLATOR = new CubicBezierInterpolator(0.19919472913616398, 0.010644531250000006, 0.27920937042459737, 0.91025390625);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private final ChatActivity activity;
|
private final ChatActivity activity;
|
||||||
private final RecyclerListView recyclerListView;
|
private final RecyclerListView recyclerListView;
|
||||||
|
|
||||||
|
@ -347,7 +348,7 @@ public class ChatListItemAnimator extends DefaultItemAnimator {
|
||||||
if (!(chatMessageCell != null && chatMessageCell.getTransitionParams().ignoreAlpha)) {
|
if (!(chatMessageCell != null && chatMessageCell.getTransitionParams().ignoreAlpha)) {
|
||||||
holder.itemView.setAlpha(1);
|
holder.itemView.setAlpha(1);
|
||||||
}
|
}
|
||||||
if (chatMessageCell != null && activity.animatingMessageObjects.contains(chatMessageCell.getMessageObject())) {
|
if (activity != null && chatMessageCell != null && activity.animatingMessageObjects.contains(chatMessageCell.getMessageObject())) {
|
||||||
activity.animatingMessageObjects.remove(chatMessageCell.getMessageObject());
|
activity.animatingMessageObjects.remove(chatMessageCell.getMessageObject());
|
||||||
if (activity.getChatActivityEnterView().canShowMessageTransition()) {
|
if (activity.getChatActivityEnterView().canShowMessageTransition()) {
|
||||||
if (chatMessageCell.getMessageObject().isVoice()) {
|
if (chatMessageCell.getMessageObject().isVoice()) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.Signature;
|
import android.content.pm.Signature;
|
||||||
import android.content.res.AssetFileDescriptor;
|
import android.content.res.AssetFileDescriptor;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
@ -43,6 +44,9 @@ import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.fonts.Font;
|
||||||
|
import android.graphics.fonts.FontFamily;
|
||||||
|
import android.graphics.fonts.SystemFonts;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -50,7 +54,6 @@ import android.os.Environment;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.Vibrator;
|
import android.os.Vibrator;
|
||||||
import android.os.VibratorManager;
|
|
||||||
import android.provider.CallLog;
|
import android.provider.CallLog;
|
||||||
import android.provider.DocumentsContract;
|
import android.provider.DocumentsContract;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
|
@ -90,7 +93,6 @@ import android.view.TextureView;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewParent;
|
|
||||||
import android.view.ViewPropertyAnimator;
|
import android.view.ViewPropertyAnimator;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
|
@ -117,7 +119,9 @@ import androidx.annotation.RequiresApi;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
|
import androidx.core.graphics.TypefaceCompatUtil;
|
||||||
import androidx.core.math.MathUtils;
|
import androidx.core.math.MathUtils;
|
||||||
|
import androidx.core.provider.FontRequest;
|
||||||
import androidx.core.widget.NestedScrollView;
|
import androidx.core.widget.NestedScrollView;
|
||||||
import androidx.dynamicanimation.animation.DynamicAnimation;
|
import androidx.dynamicanimation.animation.DynamicAnimation;
|
||||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||||
|
@ -160,8 +164,6 @@ import org.telegram.ui.Components.LayoutHelper;
|
||||||
import org.telegram.ui.Components.MotionBackgroundDrawable;
|
import org.telegram.ui.Components.MotionBackgroundDrawable;
|
||||||
import org.telegram.ui.Components.PickerBottomLayout;
|
import org.telegram.ui.Components.PickerBottomLayout;
|
||||||
import org.telegram.ui.Components.PipRoundVideoView;
|
import org.telegram.ui.Components.PipRoundVideoView;
|
||||||
import org.telegram.ui.Components.PipVideoOverlay;
|
|
||||||
import org.telegram.ui.Components.RLottieImageView;
|
|
||||||
import org.telegram.ui.Components.RecyclerListView;
|
import org.telegram.ui.Components.RecyclerListView;
|
||||||
import org.telegram.ui.Components.ShareAlert;
|
import org.telegram.ui.Components.ShareAlert;
|
||||||
import org.telegram.ui.Components.TypefaceSpan;
|
import org.telegram.ui.Components.TypefaceSpan;
|
||||||
|
@ -233,6 +235,30 @@ public class AndroidUtilities {
|
||||||
public final static String TYPEFACE_MERRIWEATHER_BOLD = "fonts/mw_bold.ttf";
|
public final static String TYPEFACE_MERRIWEATHER_BOLD = "fonts/mw_bold.ttf";
|
||||||
public final static String TYPEFACE_COURIER_NEW_BOLD = "fonts/courier_new_bold.ttf";
|
public final static String TYPEFACE_COURIER_NEW_BOLD = "fonts/courier_new_bold.ttf";
|
||||||
|
|
||||||
|
private static Typeface mediumTypeface;
|
||||||
|
public static Typeface bold() {
|
||||||
|
if (mediumTypeface == null) {
|
||||||
|
// so system Roboto with 500 weight doesn't support Hebrew (but 700 Roboto does)
|
||||||
|
// there must be a way to take system font 500 and fallback it with system font 700
|
||||||
|
// I haven't found the way, even through private API :(
|
||||||
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
// mediumTypeface = Typeface.create(null, 500, false);
|
||||||
|
//
|
||||||
|
// final String text = "Sample text";
|
||||||
|
// final TextPaint normalPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
// final TextPaint mediumPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
// mediumPaint.setTypeface(mediumTypeface);
|
||||||
|
// if (Math.abs(normalPaint.measureText(text) - mediumPaint.measureText(text)) < 0.1f) {
|
||||||
|
// mediumTypeface = Typeface.create(null, 700, false);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (mediumTypeface == null) {
|
||||||
|
mediumTypeface = getTypeface(TYPEFACE_ROBOTO_MEDIUM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mediumTypeface;
|
||||||
|
}
|
||||||
|
|
||||||
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>();
|
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>();
|
||||||
public static float touchSlop;
|
public static float touchSlop;
|
||||||
private static int prevOrientation = -10;
|
private static int prevOrientation = -10;
|
||||||
|
@ -512,7 +538,7 @@ public class AndroidUtilities {
|
||||||
ds.setColor(Theme.getColor(colorKey, resourcesProvider));
|
ds.setColor(Theme.getColor(colorKey, resourcesProvider));
|
||||||
}
|
}
|
||||||
if (type == REPLACING_TAG_TYPE_LINKBOLD) {
|
if (type == REPLACING_TAG_TYPE_LINKBOLD) {
|
||||||
ds.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
ds.setTypeface(AndroidUtilities.bold());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,7 +553,7 @@ public class AndroidUtilities {
|
||||||
spannableStringBuilder.setSpan(new CharacterStyle() {
|
spannableStringBuilder.setSpan(new CharacterStyle() {
|
||||||
@Override
|
@Override
|
||||||
public void updateDrawState(TextPaint textPaint) {
|
public void updateDrawState(TextPaint textPaint) {
|
||||||
textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textPaint.setTypeface(AndroidUtilities.bold());
|
||||||
int wasAlpha = textPaint.getAlpha();
|
int wasAlpha = textPaint.getAlpha();
|
||||||
textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText, resourcesProvider));
|
textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText, resourcesProvider));
|
||||||
textPaint.setAlpha(wasAlpha);
|
textPaint.setAlpha(wasAlpha);
|
||||||
|
@ -979,11 +1005,32 @@ public class AndroidUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean addLinksSafe(Spannable text, int mask, boolean internalOnly, boolean removeOldReplacements) {
|
public static boolean addLinksSafe(Spannable text, int mask, boolean internalOnly, boolean removeOldReplacements) {
|
||||||
|
if (text == null)
|
||||||
|
return false;
|
||||||
SpannableStringBuilder newText = new SpannableStringBuilder(text);
|
SpannableStringBuilder newText = new SpannableStringBuilder(text);
|
||||||
|
boolean success = doSafe(() -> addLinks(newText, mask, internalOnly, removeOldReplacements));
|
||||||
|
if (success) {
|
||||||
|
URLSpan[] oldSpans = text.getSpans(0, text.length(), URLSpan.class);
|
||||||
|
for (int i = 0; i < oldSpans.length; ++i) {
|
||||||
|
text.removeSpan(oldSpans[i]);
|
||||||
|
}
|
||||||
|
URLSpan[] newSpans = newText.getSpans(0, newText.length(), URLSpan.class);
|
||||||
|
for (int i = 0; i < newSpans.length; ++i) {
|
||||||
|
text.setSpan(newSpans[i], newText.getSpanStart(newSpans[i]), newText.getSpanEnd(newSpans[i]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean doSafe(Utilities.Callback0Return<Boolean> runnable) {
|
||||||
|
return doSafe(runnable, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean doSafe(Utilities.Callback0Return<Boolean> runnable, int timeout) {
|
||||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
Callable<Boolean> task = () -> {
|
Callable<Boolean> task = () -> {
|
||||||
try {
|
try {
|
||||||
return addLinks(newText, mask, internalOnly, removeOldReplacements);
|
return runnable.run();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
return false;
|
return false;
|
||||||
|
@ -993,7 +1040,7 @@ public class AndroidUtilities {
|
||||||
Future<Boolean> future = null;
|
Future<Boolean> future = null;
|
||||||
try {
|
try {
|
||||||
future = executor.submit(task);
|
future = executor.submit(task);
|
||||||
success = future.get(200, TimeUnit.MILLISECONDS);
|
success = future.get(timeout, TimeUnit.MILLISECONDS);
|
||||||
} catch (TimeoutException ex) {
|
} catch (TimeoutException ex) {
|
||||||
if (future != null) {
|
if (future != null) {
|
||||||
future.cancel(true);
|
future.cancel(true);
|
||||||
|
@ -1003,18 +1050,7 @@ public class AndroidUtilities {
|
||||||
} finally {
|
} finally {
|
||||||
executor.shutdownNow();
|
executor.shutdownNow();
|
||||||
}
|
}
|
||||||
if (success && text != null) {
|
return success;
|
||||||
URLSpan[] oldSpans = text.getSpans(0, text.length(), URLSpan.class);
|
|
||||||
for (int i = 0; i < oldSpans.length; ++i) {
|
|
||||||
text.removeSpan(oldSpans[i]);
|
|
||||||
}
|
|
||||||
URLSpan[] newSpans = newText.getSpans(0, newText.length(), URLSpan.class);
|
|
||||||
for (int i = 0; i < newSpans.length; ++i) {
|
|
||||||
text.setSpan(newSpans[i], newText.getSpanStart(newSpans[i]), newText.getSpanEnd(newSpans[i]), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated // use addLinksSafe
|
@Deprecated // use addLinksSafe
|
||||||
|
@ -2967,7 +3003,7 @@ public class AndroidUtilities {
|
||||||
}
|
}
|
||||||
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(stringBuilder);
|
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(stringBuilder);
|
||||||
for (int a = 0; a < bolds.size() / 2; a++) {
|
for (int a = 0; a < bolds.size() / 2; a++) {
|
||||||
spannableStringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
spannableStringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
return spannableStringBuilder;
|
return spannableStringBuilder;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -3164,7 +3200,7 @@ public class AndroidUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean shouldShowClipboardToast() {
|
public static boolean shouldShowClipboardToast() {
|
||||||
return (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || !OneUIUtilities.hasBuiltInClipboardToasts()) && Build.VERSION.SDK_INT < 32 /* TODO: Update to TIRAMISU when compileSdkVersion would be 32 */;
|
return (Build.VERSION.SDK_INT < Build.VERSION_CODES.S || !OneUIUtilities.hasBuiltInClipboardToasts()) && Build.VERSION.SDK_INT < 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean addToClipboard(CharSequence str) {
|
public static boolean addToClipboard(CharSequence str) {
|
||||||
|
@ -4638,8 +4674,18 @@ public class AndroidUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void lerp(int[] a, int[] b, float f, int[] to) {
|
||||||
|
if (to == null) return;
|
||||||
|
for (int i = 0; i < to.length; ++i) {
|
||||||
|
int av = a == null || i >= a.length ? 0 : a[i];
|
||||||
|
int bv = b == null || i >= b.length ? 0 : b[i];
|
||||||
|
to[i] = lerp(av, bv, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static float cascade(float fullAnimationT, float position, float count, float waveLength) {
|
public static float cascade(float fullAnimationT, float position, float count, float waveLength) {
|
||||||
final float waveDuration = 1f / count * waveLength;
|
if (count <= 0) return fullAnimationT;
|
||||||
|
final float waveDuration = 1f / count * Math.min(waveLength, count);
|
||||||
final float waveOffset = position / count * (1f - waveDuration);
|
final float waveOffset = position / count * (1f - waveDuration);
|
||||||
return MathUtils.clamp((fullAnimationT - waveOffset) / waveDuration, 0, 1);
|
return MathUtils.clamp((fullAnimationT - waveOffset) / waveDuration, 0, 1);
|
||||||
}
|
}
|
||||||
|
@ -5308,7 +5354,30 @@ public class AndroidUtilities {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean hasDialogOnTop(BaseFragment fragment) {
|
||||||
|
if (fragment == null) return false;
|
||||||
|
if (fragment.visibleDialog != null) return true;
|
||||||
|
if (fragment.getParentLayout() == null) return false;
|
||||||
|
List<View> globalViews = allGlobalViews();
|
||||||
|
if (globalViews == null || globalViews.isEmpty()) return false;
|
||||||
|
View lastGlobalView = globalViews.get(globalViews.size() - 1);
|
||||||
|
return lastGlobalView != getRootView(fragment.getParentLayout().getView());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static View getRootView(View v) {
|
||||||
|
View view = v;
|
||||||
|
while (view != null && view.getParent() instanceof View) {
|
||||||
|
view = ((View) view.getParent());
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean makingGlobalBlurBitmap;
|
||||||
public static void makeGlobalBlurBitmap(Utilities.Callback<Bitmap> onBitmapDone, float amount) {
|
public static void makeGlobalBlurBitmap(Utilities.Callback<Bitmap> onBitmapDone, float amount) {
|
||||||
|
makeGlobalBlurBitmap(onBitmapDone, amount, (int) amount, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void makeGlobalBlurBitmap(Utilities.Callback<Bitmap> onBitmapDone, float downscale, int amount, View forView, List<View> exclude) {
|
||||||
if (onBitmapDone == null) {
|
if (onBitmapDone == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5319,20 +5388,32 @@ public class AndroidUtilities {
|
||||||
onBitmapDone.run(null);
|
onBitmapDone.run(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
makingGlobalBlurBitmap = true;
|
||||||
|
|
||||||
final List<View> finalViews = views;
|
final List<View> finalViews = views;
|
||||||
//Utilities.themeQueue.postRunnable(() -> {
|
//Utilities.themeQueue.postRunnable(() -> {
|
||||||
try {
|
try {
|
||||||
int w = (int) (AndroidUtilities.displaySize.x / amount);
|
int w;
|
||||||
int h = (int) ((AndroidUtilities.displaySize.y + AndroidUtilities.statusBarHeight) / amount);
|
int h;
|
||||||
|
if (forView == null) {
|
||||||
|
w = (int) (AndroidUtilities.displaySize.x / downscale);
|
||||||
|
h = (int) ((AndroidUtilities.displaySize.y + AndroidUtilities.statusBarHeight) / downscale);
|
||||||
|
} else {
|
||||||
|
w = (int) (forView.getWidth() / downscale);
|
||||||
|
h = (int) (forView.getHeight() / downscale);
|
||||||
|
}
|
||||||
|
int[] location = new int[2];
|
||||||
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
Canvas canvas = new Canvas(bitmap);
|
||||||
canvas.scale(1.0f / amount, 1.0f / amount);
|
if (forView != null) {
|
||||||
|
forView.getLocationOnScreen(location);
|
||||||
|
canvas.translate(-location[0] / downscale, -location[1] / downscale);
|
||||||
|
}
|
||||||
|
canvas.scale(1.0f / downscale, 1.0f / downscale);
|
||||||
canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundWhite));
|
||||||
int[] location = new int[2];
|
|
||||||
for (int i = 0; i < finalViews.size(); ++i) {
|
for (int i = 0; i < finalViews.size(); ++i) {
|
||||||
View view = finalViews.get(i);
|
View view = finalViews.get(i);
|
||||||
if (view instanceof PipRoundVideoView.PipFrameLayout || view instanceof PipRoundVideoView.PipFrameLayout) {
|
if (view instanceof PipRoundVideoView.PipFrameLayout || view instanceof PipRoundVideoView.PipFrameLayout || (exclude != null && exclude.contains(view))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5346,7 +5427,7 @@ public class AndroidUtilities {
|
||||||
|
|
||||||
canvas.save();
|
canvas.save();
|
||||||
view.getLocationOnScreen(location);
|
view.getLocationOnScreen(location);
|
||||||
canvas.translate(location[0] / amount, location[1] / amount);
|
canvas.translate(location[0] / downscale, location[1] / downscale);
|
||||||
try {
|
try {
|
||||||
view.draw(canvas);
|
view.draw(canvas);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -5354,7 +5435,7 @@ public class AndroidUtilities {
|
||||||
}
|
}
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
Utilities.stackBlurBitmap(bitmap, Math.max((int) amount, Math.max(w, h) / 180));
|
Utilities.stackBlurBitmap(bitmap, Math.max(amount, Math.max(w, h) / 180));
|
||||||
// AndroidUtilities.runOnUIThread(() -> {
|
// AndroidUtilities.runOnUIThread(() -> {
|
||||||
onBitmapDone.run(bitmap);
|
onBitmapDone.run(bitmap);
|
||||||
// });
|
// });
|
||||||
|
@ -5363,6 +5444,8 @@ public class AndroidUtilities {
|
||||||
// AndroidUtilities.runOnUIThread(() -> {
|
// AndroidUtilities.runOnUIThread(() -> {
|
||||||
onBitmapDone.run(null);
|
onBitmapDone.run(null);
|
||||||
// });
|
// });
|
||||||
|
} finally {
|
||||||
|
makingGlobalBlurBitmap = false;
|
||||||
}
|
}
|
||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
@ -5507,6 +5590,12 @@ public class AndroidUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isSafeToShow(Context context) {
|
||||||
|
Activity activity = findActivity(context);
|
||||||
|
if (activity == null) return true;
|
||||||
|
return isActivityRunning(activity);
|
||||||
|
}
|
||||||
|
|
||||||
public static Pair<Integer, Integer> getImageOrientation(InputStream is) {
|
public static Pair<Integer, Integer> getImageOrientation(InputStream is) {
|
||||||
try {
|
try {
|
||||||
return getImageOrientation(new ExifInterface(is));
|
return getImageOrientation(new ExifInterface(is));
|
||||||
|
|
|
@ -6,6 +6,8 @@ public class AnimationNotificationsLocker {
|
||||||
int notificationsIndex = -1;
|
int notificationsIndex = -1;
|
||||||
int globalNotificationsIndex = -1;
|
int globalNotificationsIndex = -1;
|
||||||
|
|
||||||
|
boolean disabled;
|
||||||
|
|
||||||
final int[] allowedNotifications;
|
final int[] allowedNotifications;
|
||||||
|
|
||||||
public AnimationNotificationsLocker() {
|
public AnimationNotificationsLocker() {
|
||||||
|
@ -17,6 +19,9 @@ public class AnimationNotificationsLocker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lock() {
|
public void lock() {
|
||||||
|
if (disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int currentAccount = UserConfig.selectedAccount;
|
int currentAccount = UserConfig.selectedAccount;
|
||||||
if (this.currentAccount != currentAccount) {
|
if (this.currentAccount != currentAccount) {
|
||||||
NotificationCenter.getInstance(currentAccount).onAnimationFinish(notificationsIndex);
|
NotificationCenter.getInstance(currentAccount).onAnimationFinish(notificationsIndex);
|
||||||
|
@ -28,8 +33,15 @@ public class AnimationNotificationsLocker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unlock() {
|
public void unlock() {
|
||||||
|
if (disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
NotificationCenter.getInstance(currentAccount).onAnimationFinish(notificationsIndex);
|
NotificationCenter.getInstance(currentAccount).onAnimationFinish(notificationsIndex);
|
||||||
NotificationCenter.getGlobalInstance().onAnimationFinish(globalNotificationsIndex);
|
NotificationCenter.getGlobalInstance().onAnimationFinish(globalNotificationsIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void disable() {
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import com.android.billingclient.api.QueryPurchasesParams;
|
||||||
import org.telegram.messenger.utils.BillingUtilities;
|
import org.telegram.messenger.utils.BillingUtilities;
|
||||||
import org.telegram.tgnet.ConnectionsManager;
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
|
import org.telegram.ui.ActionBar.AlertDialog;
|
||||||
import org.telegram.ui.PremiumPreviewFragment;
|
import org.telegram.ui.PremiumPreviewFragment;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
import java.text.NumberFormat;
|
||||||
|
@ -96,6 +97,7 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
return formatCurrency(amount, currency, exp, false);
|
return formatCurrency(amount, currency, exp, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static NumberFormat currencyInstance;
|
||||||
public String formatCurrency(long amount, String currency, int exp, boolean rounded) {
|
public String formatCurrency(long amount, String currency, int exp, boolean rounded) {
|
||||||
if (currency == null || currency.isEmpty()) {
|
if (currency == null || currency.isEmpty()) {
|
||||||
return String.valueOf(amount);
|
return String.valueOf(amount);
|
||||||
|
@ -105,12 +107,14 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
}
|
}
|
||||||
Currency cur = Currency.getInstance(currency);
|
Currency cur = Currency.getInstance(currency);
|
||||||
if (cur != null) {
|
if (cur != null) {
|
||||||
NumberFormat numberFormat = NumberFormat.getCurrencyInstance();
|
if (currencyInstance == null) {
|
||||||
numberFormat.setCurrency(cur);
|
currencyInstance = NumberFormat.getCurrencyInstance();
|
||||||
if (rounded) {
|
|
||||||
return numberFormat.format(Math.round(amount / Math.pow(10, exp)));
|
|
||||||
}
|
}
|
||||||
return numberFormat.format(amount / Math.pow(10, exp));
|
currencyInstance.setCurrency(cur);
|
||||||
|
if (rounded) {
|
||||||
|
return currencyInstance.format(Math.round(amount / Math.pow(10, exp)));
|
||||||
|
}
|
||||||
|
return currencyInstance.format(amount / Math.pow(10, exp));
|
||||||
}
|
}
|
||||||
return amount + " " + currency;
|
return amount + " " + currency;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +191,7 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paymentPurpose instanceof TLRPC.TL_inputStorePaymentGiftPremium && !checkedConsume) {
|
if ((paymentPurpose instanceof TLRPC.TL_inputStorePaymentGiftPremium || paymentPurpose instanceof TLRPC.TL_inputStorePaymentStars) && !checkedConsume) {
|
||||||
queryPurchases(BillingClient.ProductType.INAPP, (billingResult, list) -> {
|
queryPurchases(BillingClient.ProductType.INAPP, (billingResult, list) -> {
|
||||||
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
|
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
|
||||||
Runnable callback = () -> launchBillingFlow(activity, accountInstance, paymentPurpose, productDetails, subscriptionUpdateParams, true);
|
Runnable callback = () -> launchBillingFlow(activity, accountInstance, paymentPurpose, productDetails, subscriptionUpdateParams, true);
|
||||||
|
@ -281,8 +285,13 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
req.receipt.data = purchase.getOriginalJson();
|
req.receipt.data = purchase.getOriginalJson();
|
||||||
req.purpose = payload.second;
|
req.purpose = payload.second;
|
||||||
|
|
||||||
|
final AlertDialog progressDialog = new AlertDialog(ApplicationLoader.applicationContext, AlertDialog.ALERT_TYPE_SPINNER);
|
||||||
|
AndroidUtilities.runOnUIThread(() -> progressDialog.showDelayed(500));
|
||||||
|
|
||||||
AccountInstance acc = payload.first;
|
AccountInstance acc = payload.first;
|
||||||
acc.getConnectionsManager().sendRequest(req, (response, error) -> {
|
acc.getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||||
|
AndroidUtilities.runOnUIThread(progressDialog::dismiss);
|
||||||
|
|
||||||
requestingTokens.remove(purchase.getPurchaseToken());
|
requestingTokens.remove(purchase.getPurchaseToken());
|
||||||
|
|
||||||
if (response instanceof TLRPC.Updates) {
|
if (response instanceof TLRPC.Updates) {
|
||||||
|
@ -303,7 +312,7 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
}
|
}
|
||||||
NotificationCenter.getGlobalInstance().postNotificationNameOnUIThread(NotificationCenter.billingConfirmPurchaseError, req, error);
|
NotificationCenter.getGlobalInstance().postNotificationNameOnUIThread(NotificationCenter.billingConfirmPurchaseError, req, error);
|
||||||
}
|
}
|
||||||
}, ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagInvokeAfter);
|
}, ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagFailOnServerErrorsExceptFloodWait | ConnectionsManager.RequestFlagInvokeAfter);
|
||||||
} else {
|
} else {
|
||||||
consumeGiftPurchase(purchase, payload.second);
|
consumeGiftPurchase(purchase, payload.second);
|
||||||
}
|
}
|
||||||
|
@ -318,6 +327,7 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
private void consumeGiftPurchase(Purchase purchase, TLRPC.InputStorePaymentPurpose purpose) {
|
private void consumeGiftPurchase(Purchase purchase, TLRPC.InputStorePaymentPurpose purpose) {
|
||||||
if (purpose instanceof TLRPC.TL_inputStorePaymentGiftPremium
|
if (purpose instanceof TLRPC.TL_inputStorePaymentGiftPremium
|
||||||
|| purpose instanceof TLRPC.TL_inputStorePaymentPremiumGiftCode
|
|| purpose instanceof TLRPC.TL_inputStorePaymentPremiumGiftCode
|
||||||
|
|| purpose instanceof TLRPC.TL_inputStorePaymentStars
|
||||||
|| purpose instanceof TLRPC.TL_inputStorePaymentPremiumGiveaway) {
|
|| purpose instanceof TLRPC.TL_inputStorePaymentPremiumGiveaway) {
|
||||||
billingClient.consumeAsync(
|
billingClient.consumeAsync(
|
||||||
ConsumeParams.newBuilder()
|
ConsumeParams.newBuilder()
|
||||||
|
@ -340,6 +350,11 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
AndroidUtilities.runOnUIThread(() -> startConnection(), delay);
|
AndroidUtilities.runOnUIThread(() -> startConnection(), delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<Runnable> setupListeners = new ArrayList<>();
|
||||||
|
public void whenSetuped(Runnable listener) {
|
||||||
|
setupListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
private int triesLeft = 0;
|
private int triesLeft = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -355,6 +370,12 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
}
|
}
|
||||||
queryPurchases(BillingClient.ProductType.INAPP, this::onPurchasesUpdated);
|
queryPurchases(BillingClient.ProductType.INAPP, this::onPurchasesUpdated);
|
||||||
queryPurchases(BillingClient.ProductType.SUBS, this::onPurchasesUpdated);
|
queryPurchases(BillingClient.ProductType.SUBS, this::onPurchasesUpdated);
|
||||||
|
if (!setupListeners.isEmpty()) {
|
||||||
|
for (int i = 0; i < setupListeners.size(); ++i) {
|
||||||
|
AndroidUtilities.runOnUIThread(setupListeners.get(i));
|
||||||
|
}
|
||||||
|
setupListeners.clear();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!isDisconnected) {
|
if (!isDisconnected) {
|
||||||
switchToInvoice();
|
switchToInvoice();
|
||||||
|
@ -396,4 +417,22 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getResponseCodeString(int code) {
|
||||||
|
switch (code) {
|
||||||
|
case -3: return "SERVICE_TIMEOUT";
|
||||||
|
case -2: return "FEATURE_NOT_SUPPORTED";
|
||||||
|
case -1: return "SERVICE_DISCONNECTED";
|
||||||
|
case 0: return "OK";
|
||||||
|
case 1: return "USER_CANCELED";
|
||||||
|
case 2: return "SERVICE_UNAVAILABLE";
|
||||||
|
case 3: return "BILLING_UNAVAILABLE";
|
||||||
|
case 4: return "ITEM_UNAVAILABLE";
|
||||||
|
case 5: return "DEVELOPER_ERROR";
|
||||||
|
case 6: return "ERROR";
|
||||||
|
case 7: return "ITEM_ALREADY_OWNED";
|
||||||
|
case 8: return "ITEM_NOT_OWNED";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.telegram.messenger;
|
package org.telegram.messenger;
|
||||||
|
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Looper;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -21,11 +23,31 @@ public abstract class CacheFetcher<Args, R> {
|
||||||
// Implement this function
|
// Implement this function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CacheFetcher() {
|
||||||
|
this(4 * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CacheFetcher(int timeout) {
|
||||||
|
requestRemotelyTimeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean useCache(Args arguments) {
|
protected boolean useCache(Args arguments) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final long requestRemotelyTimeout = 4 * 60 * 1000;
|
protected boolean emitLocal(Args arguments) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean saveLastTimeRequested() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getSavedLastTimeRequested(int hashCode) { return 0; }
|
||||||
|
|
||||||
|
protected void setSavedLastTimeRequested(int hashCode, long time) {}
|
||||||
|
|
||||||
|
private final long requestRemotelyTimeout;
|
||||||
|
|
||||||
private HashMap<Pair<Integer, Args>, R> cachedResults;
|
private HashMap<Pair<Integer, Args>, R> cachedResults;
|
||||||
private HashMap<Pair<Integer, Args>, ArrayList<Utilities.Callback<R>>> loadingCallbacks;
|
private HashMap<Pair<Integer, Args>, ArrayList<Utilities.Callback<R>>> loadingCallbacks;
|
||||||
|
@ -50,24 +72,28 @@ public abstract class CacheFetcher<Args, R> {
|
||||||
saveCallback(key, onResult);
|
saveCallback(key, onResult);
|
||||||
getLocal(currentAccount, arguments, (hash, data) -> {
|
getLocal(currentAccount, arguments, (hash, data) -> {
|
||||||
if (shouldRequest(key)) {
|
if (shouldRequest(key)) {
|
||||||
|
if (data != null && emitLocal(arguments)) {
|
||||||
|
cacheResult(key, data);
|
||||||
|
callCallbacks(key, data, false);
|
||||||
|
}
|
||||||
getRemote(currentAccount, arguments, hash, (notModified, remoteData, newHash, requestSuccess) -> {
|
getRemote(currentAccount, arguments, hash, (notModified, remoteData, newHash, requestSuccess) -> {
|
||||||
if (requestSuccess) {
|
if (requestSuccess) {
|
||||||
saveLastRequested(key);
|
saveLastRequested(key);
|
||||||
}
|
}
|
||||||
if (notModified) {
|
if (notModified) {
|
||||||
cacheResult(key, data);
|
cacheResult(key, data);
|
||||||
callCallbacks(key, data);
|
callCallbacks(key, data, true);
|
||||||
} else {
|
} else {
|
||||||
if (remoteData != null) {
|
if (remoteData != null) {
|
||||||
setLocal(currentAccount, arguments, remoteData, newHash);
|
setLocal(currentAccount, arguments, remoteData, newHash);
|
||||||
cacheResult(key, remoteData);
|
cacheResult(key, remoteData);
|
||||||
}
|
}
|
||||||
callCallbacks(key, remoteData);
|
callCallbacks(key, remoteData, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cacheResult(key, data);
|
cacheResult(key, data);
|
||||||
callCallbacks(key, data);
|
callCallbacks(key, data, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -93,11 +119,18 @@ public abstract class CacheFetcher<Args, R> {
|
||||||
if (lastRequestedRemotely == null) {
|
if (lastRequestedRemotely == null) {
|
||||||
lastRequestedRemotely = new HashMap<>();
|
lastRequestedRemotely = new HashMap<>();
|
||||||
}
|
}
|
||||||
lastRequestedRemotely.put(key, System.currentTimeMillis());
|
final long now = System.currentTimeMillis();
|
||||||
|
lastRequestedRemotely.put(key, now);
|
||||||
|
if (saveLastTimeRequested()) {
|
||||||
|
setSavedLastTimeRequested(key.hashCode(), now);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldRequest(Pair<Integer, Args> key) {
|
private boolean shouldRequest(Pair<Integer, Args> key) {
|
||||||
Long lastRequested = lastRequestedRemotely != null ? lastRequestedRemotely.get(key) : null;
|
Long lastRequested = lastRequestedRemotely != null ? lastRequestedRemotely.get(key) : null;
|
||||||
|
if (saveLastTimeRequested() && lastRequested == null) {
|
||||||
|
lastRequested = getSavedLastTimeRequested(key.hashCode());
|
||||||
|
}
|
||||||
return lastRequested == null || System.currentTimeMillis() - lastRequested >= requestRemotelyTimeout;
|
return lastRequested == null || System.currentTimeMillis() - lastRequested >= requestRemotelyTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +138,11 @@ public abstract class CacheFetcher<Args, R> {
|
||||||
if (lastRequestedRemotely == null) {
|
if (lastRequestedRemotely == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastRequestedRemotely.remove(new Pair<>(currentAccount, args));
|
Pair<Integer, Args> key = new Pair<>(currentAccount, args);
|
||||||
|
lastRequestedRemotely.remove(key);
|
||||||
|
if (saveLastTimeRequested()) {
|
||||||
|
setSavedLastTimeRequested(key.hashCode(), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLoading(Pair<Integer, Args> key) {
|
private boolean isLoading(Pair<Integer, Args> key) {
|
||||||
|
@ -116,33 +153,38 @@ public abstract class CacheFetcher<Args, R> {
|
||||||
if (callback == null) {
|
if (callback == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (loadingCallbacks == null) {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
loadingCallbacks = new HashMap<>();
|
if (loadingCallbacks == null) {
|
||||||
}
|
loadingCallbacks = new HashMap<>();
|
||||||
ArrayList<Utilities.Callback<R>> callbacks = loadingCallbacks.get(key);
|
}
|
||||||
if (callbacks == null) {
|
ArrayList<Utilities.Callback<R>> callbacks = loadingCallbacks.get(key);
|
||||||
loadingCallbacks.put(key, callbacks = new ArrayList<>());
|
if (callbacks == null) {
|
||||||
}
|
loadingCallbacks.put(key, callbacks = new ArrayList<>());
|
||||||
callbacks.add(callback);
|
}
|
||||||
|
callbacks.add(callback);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void callCallbacks(Pair<Integer, Args> key, R result) {
|
private void callCallbacks(Pair<Integer, Args> key, R result, boolean remove) {
|
||||||
if (loadingCallbacks == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final ArrayList<Utilities.Callback<R>> callbacks = loadingCallbacks.get(key);
|
|
||||||
if (callbacks == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
if (loadingCallbacks == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ArrayList<Utilities.Callback<R>> callbacks = loadingCallbacks.get(key);
|
||||||
|
if (callbacks == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (Utilities.Callback<R> callback: callbacks) {
|
for (Utilities.Callback<R> callback: callbacks) {
|
||||||
callback.run(result);
|
callback.run(result);
|
||||||
}
|
}
|
||||||
callbacks.clear();
|
if (remove) {
|
||||||
});
|
callbacks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
loadingCallbacks.remove(key);
|
if (remove) {
|
||||||
|
loadingCallbacks.remove(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -43,17 +43,19 @@ public class ChannelBoostsController {
|
||||||
} else {
|
} else {
|
||||||
BaseFragment fragment = LaunchActivity.getLastFragment();
|
BaseFragment fragment = LaunchActivity.getLastFragment();
|
||||||
if (error != null && fragment != null && "CHANNEL_PRIVATE".equals(error.text)) {
|
if (error != null && fragment != null && "CHANNEL_PRIVATE".equals(error.text)) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getContext(), fragment.getResourceProvider());
|
if (!(LaunchActivity.instance != null && LaunchActivity.instance.isFinishing())) {
|
||||||
builder.setTitle(LocaleController.getString(R.string.AppName));
|
AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getContext(), fragment.getResourceProvider());
|
||||||
Map<String, Integer> colorsReplacement = new HashMap<>();
|
builder.setTitle(LocaleController.getString(R.string.AppName));
|
||||||
colorsReplacement.put("info1.**", Theme.getColor(Theme.key_dialogTopBackground));
|
Map<String, Integer> colorsReplacement = new HashMap<>();
|
||||||
colorsReplacement.put("info2.**", Theme.getColor(Theme.key_dialogTopBackground));
|
colorsReplacement.put("info1.**", Theme.getColor(Theme.key_dialogTopBackground));
|
||||||
builder.setTopAnimation(R.raw.not_available, AlertsCreator.NEW_DENY_DIALOG_TOP_ICON_SIZE, false, Theme.getColor(Theme.key_dialogTopBackground), colorsReplacement);
|
colorsReplacement.put("info2.**", Theme.getColor(Theme.key_dialogTopBackground));
|
||||||
builder.setTopAnimationIsNew(true);
|
builder.setTopAnimation(R.raw.not_available, AlertsCreator.NEW_DENY_DIALOG_TOP_ICON_SIZE, false, Theme.getColor(Theme.key_dialogTopBackground), colorsReplacement);
|
||||||
builder.setTitle(LocaleController.getString(R.string.ChannelPrivate));
|
builder.setTopAnimationIsNew(true);
|
||||||
builder.setMessage(LocaleController.getString("ChannelCantOpenPrivate2", R.string.ChannelCantOpenPrivate2));
|
builder.setTitle(LocaleController.getString(R.string.ChannelPrivate));
|
||||||
builder.setPositiveButton(LocaleController.getString(R.string.Close), null);
|
builder.setMessage(LocaleController.getString("ChannelCantOpenPrivate2", R.string.ChannelCantOpenPrivate2));
|
||||||
builder.show();
|
builder.setPositiveButton(LocaleController.getString(R.string.Close), null);
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
BulletinFactory.global().showForError(error);
|
BulletinFactory.global().showForError(error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2975,7 +2975,7 @@ public class ContactsController extends BaseController {
|
||||||
TLRPC.Chat chat = (TLRPC.Chat) object;
|
TLRPC.Chat chat = (TLRPC.Chat) object;
|
||||||
return chat.title;
|
return chat.title;
|
||||||
} else {
|
} else {
|
||||||
return "DELETED";
|
return LocaleController.getString(R.string.HiddenName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1504,6 +1504,18 @@ public class DatabaseMigrationHelper {
|
||||||
version = 153;
|
version = 153;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version == 153) {
|
||||||
|
database.executeFast("CREATE TABLE effects(data BLOB)").stepThis().dispose();
|
||||||
|
database.executeFast("PRAGMA user_version = 154").stepThis().dispose();
|
||||||
|
version = 154;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version == 154) {
|
||||||
|
database.executeFast("CREATE TABLE fact_checks(hash INTEGER PRIMARY KEY, data BLOB, expires INTEGER);").stepThis().dispose();
|
||||||
|
database.executeFast("PRAGMA user_version = 155").stepThis().dispose();
|
||||||
|
version = 155;
|
||||||
|
}
|
||||||
|
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.checkerframework.checker.units.qual.A;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.Components.AnimatedEmojiDrawable;
|
import org.telegram.ui.Components.AnimatedEmojiDrawable;
|
||||||
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
||||||
|
import org.telegram.ui.Components.ColoredImageSpan;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -586,13 +587,14 @@ public class Emoji {
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimatedEmojiSpan[] animatedEmojiSpans = s.getSpans(0, s.length(), AnimatedEmojiSpan.class);
|
AnimatedEmojiSpan[] animatedEmojiSpans = s.getSpans(0, s.length(), AnimatedEmojiSpan.class);
|
||||||
|
ColoredImageSpan[] imageSpans = s.getSpans(0, s.length(), ColoredImageSpan.class);
|
||||||
EmojiSpan span;
|
EmojiSpan span;
|
||||||
Drawable drawable;
|
Drawable drawable;
|
||||||
int limitCount = SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_HIGH ? 100 : 50;
|
int limitCount = SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_HIGH ? 100 : 50;
|
||||||
for (int i = 0; i < emojis.size(); ++i) {
|
for (int i = 0; i < emojis.size(); ++i) {
|
||||||
try {
|
try {
|
||||||
EmojiSpanRange emojiRange = emojis.get(i);
|
EmojiSpanRange emojiRange = emojis.get(i);
|
||||||
if (animatedEmojiSpans != null) {
|
if (animatedEmojiSpans != null && animatedEmojiSpans.length > 0) {
|
||||||
boolean hasAnimated = false;
|
boolean hasAnimated = false;
|
||||||
for (int j = 0; j < animatedEmojiSpans.length; ++j) {
|
for (int j = 0; j < animatedEmojiSpans.length; ++j) {
|
||||||
AnimatedEmojiSpan animatedSpan = animatedEmojiSpans[j];
|
AnimatedEmojiSpan animatedSpan = animatedEmojiSpans[j];
|
||||||
|
@ -605,6 +607,19 @@ public class Emoji {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (imageSpans != null && imageSpans.length > 0) {
|
||||||
|
boolean hasImage = false;
|
||||||
|
for (int j = 0; j < imageSpans.length; ++j) {
|
||||||
|
ColoredImageSpan imageSpan = imageSpans[j];
|
||||||
|
if (imageSpan != null && s.getSpanStart(imageSpan) == emojiRange.start && s.getSpanEnd(imageSpan) == emojiRange.end) {
|
||||||
|
hasImage = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasImage) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
drawable = Emoji.getEmojiDrawable(emojiRange.code);
|
drawable = Emoji.getEmojiDrawable(emojiRange.code);
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
span = new EmojiSpan(drawable, alignment, fontMetrics);
|
span = new EmojiSpan(drawable, alignment, fontMetrics);
|
||||||
|
|
|
@ -0,0 +1,590 @@
|
||||||
|
package org.telegram.messenger;
|
||||||
|
|
||||||
|
import static org.telegram.messenger.AndroidUtilities.dp;
|
||||||
|
import static org.telegram.messenger.LocaleController.getString;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.util.LongSparseArray;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.ActionMode;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.HapticFeedbackConstants;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.telegram.SQLite.SQLiteCursor;
|
||||||
|
import org.telegram.SQLite.SQLiteDatabase;
|
||||||
|
import org.telegram.SQLite.SQLitePreparedStatement;
|
||||||
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
|
import org.telegram.tgnet.NativeByteBuffer;
|
||||||
|
import org.telegram.tgnet.TLObject;
|
||||||
|
import org.telegram.tgnet.TLRPC;
|
||||||
|
import org.telegram.ui.ActionBar.AlertDialog;
|
||||||
|
import org.telegram.ui.ActionBar.AlertDialogDecor;
|
||||||
|
import org.telegram.ui.ActionBar.BaseFragment;
|
||||||
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
|
import org.telegram.ui.Components.AnimatedColor;
|
||||||
|
import org.telegram.ui.Components.AnimatedTextView;
|
||||||
|
import org.telegram.ui.Components.BulletinFactory;
|
||||||
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||||
|
import org.telegram.ui.Components.EditTextCaption;
|
||||||
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
|
import org.telegram.ui.Components.SizeNotifierFrameLayout;
|
||||||
|
import org.telegram.ui.Components.TypefaceSpan;
|
||||||
|
import org.telegram.ui.LaunchActivity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class FactCheckController {
|
||||||
|
|
||||||
|
private static volatile FactCheckController[] Instance = new FactCheckController[UserConfig.MAX_ACCOUNT_COUNT];
|
||||||
|
private static final Object[] lockObjects = new Object[UserConfig.MAX_ACCOUNT_COUNT];
|
||||||
|
static {
|
||||||
|
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++) {
|
||||||
|
lockObjects[i] = new Object();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FactCheckController getInstance(int num) {
|
||||||
|
FactCheckController localInstance = Instance[num];
|
||||||
|
if (localInstance == null) {
|
||||||
|
synchronized (lockObjects[num]) {
|
||||||
|
localInstance = Instance[num];
|
||||||
|
if (localInstance == null) {
|
||||||
|
Instance[num] = localInstance = new FactCheckController(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return localInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int currentAccount;
|
||||||
|
|
||||||
|
private FactCheckController(int account) {
|
||||||
|
currentAccount = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final LongSparseArray<TLRPC.TL_factCheck> localCache = new LongSparseArray<>();
|
||||||
|
private final LongSparseArray<HashMap<Key, Utilities.Callback<TLRPC.TL_factCheck>>> toload = new LongSparseArray<>();
|
||||||
|
private final ArrayList<Key> loading = new ArrayList<>();
|
||||||
|
|
||||||
|
public TLRPC.TL_factCheck getFactCheck(MessageObject messageObject) {
|
||||||
|
if (messageObject == null || messageObject.messageOwner == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (messageObject.messageOwner.factcheck == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!messageObject.messageOwner.factcheck.need_check) {
|
||||||
|
if (localCache.get(messageObject.messageOwner.factcheck.hash) == null) {
|
||||||
|
localCache.put(messageObject.messageOwner.factcheck.hash, messageObject.messageOwner.factcheck);
|
||||||
|
saveToDatabase(messageObject.messageOwner.factcheck);
|
||||||
|
}
|
||||||
|
return messageObject.messageOwner.factcheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Key key = Key.of(messageObject);
|
||||||
|
if (key == null) return null;
|
||||||
|
if (key.messageId < 0) return null;
|
||||||
|
|
||||||
|
TLRPC.TL_factCheck cached = localCache.get(key.hash);
|
||||||
|
if (cached != null) {
|
||||||
|
return messageObject.messageOwner.factcheck = cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loading.contains(key)) {
|
||||||
|
return messageObject.messageOwner.factcheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<Key, Utilities.Callback<TLRPC.TL_factCheck>> msgs = toload.get(key.dialogId);
|
||||||
|
if (msgs == null) {
|
||||||
|
toload.put(key.dialogId, msgs = new HashMap<>());
|
||||||
|
}
|
||||||
|
if (!msgs.containsKey(key)) {
|
||||||
|
msgs.put(key, factCheck -> {
|
||||||
|
localCache.put(key.hash, factCheck);
|
||||||
|
messageObject.messageOwner.factcheck = factCheck;
|
||||||
|
});
|
||||||
|
scheduleLoadMissing();
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageObject.messageOwner.factcheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleLoadMissing() {
|
||||||
|
AndroidUtilities.cancelRunOnUIThread(loadMissingRunnable);
|
||||||
|
AndroidUtilities.runOnUIThread(loadMissingRunnable, 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Runnable loadMissingRunnable = this::loadMissing;
|
||||||
|
|
||||||
|
private void loadMissing() {
|
||||||
|
for (int i = 0; i < this.toload.size(); ++i) {
|
||||||
|
long dialogId = this.toload.keyAt(i);
|
||||||
|
|
||||||
|
HashMap<Key, Utilities.Callback<TLRPC.TL_factCheck>> msgs = this.toload.valueAt(i);
|
||||||
|
this.toload.removeAt(i);
|
||||||
|
i--;
|
||||||
|
|
||||||
|
ArrayList<Key> keys = new ArrayList<>(msgs.keySet());
|
||||||
|
loading.addAll(keys);
|
||||||
|
getFromDatabase(keys, results -> {
|
||||||
|
TLRPC.TL_getFactCheck req = new TLRPC.TL_getFactCheck();
|
||||||
|
req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId);
|
||||||
|
|
||||||
|
ArrayList<Key> reqKeys = new ArrayList<>();
|
||||||
|
|
||||||
|
int processed = 0;
|
||||||
|
for (int k = 0; k < results.size(); ++k) {
|
||||||
|
final Key key = keys.get(k);
|
||||||
|
final TLRPC.TL_factCheck factCheck = results.get(k);
|
||||||
|
if (factCheck == null) {
|
||||||
|
reqKeys.add(key);
|
||||||
|
req.msg_id.add(key.messageId);
|
||||||
|
} else {
|
||||||
|
loading.remove(key);
|
||||||
|
final Utilities.Callback<TLRPC.TL_factCheck> callback = msgs.get(key);
|
||||||
|
if (callback != null) {
|
||||||
|
callback.run(factCheck);
|
||||||
|
processed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (processed > 0) {
|
||||||
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.factCheckLoaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!req.msg_id.isEmpty()) {
|
||||||
|
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
ArrayList<TLRPC.TL_factCheck> factChecks = new ArrayList<>();
|
||||||
|
if (res instanceof TLRPC.Vector) {
|
||||||
|
ArrayList<Object> objects = ((TLRPC.Vector) res).objects;
|
||||||
|
for (int k = 0; k < objects.size(); ++k) {
|
||||||
|
if (objects.get(k) instanceof TLRPC.TL_factCheck) {
|
||||||
|
factChecks.add((TLRPC.TL_factCheck) objects.get(k));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<Integer, TLRPC.TL_factCheck> map = new HashMap<>();
|
||||||
|
for (int k = 0; k < Math.min(req.msg_id.size(), factChecks.size()); ++k) {
|
||||||
|
final int messageId = req.msg_id.get(k);
|
||||||
|
final TLRPC.TL_factCheck factCheck = factChecks.get(k);
|
||||||
|
map.put(messageId, factCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
int processed2 = 0;
|
||||||
|
for (int k = 0; k < req.msg_id.size(); ++k) {
|
||||||
|
final Key key = reqKeys.get(k);
|
||||||
|
final int messageId = req.msg_id.get(k);
|
||||||
|
final TLRPC.TL_factCheck factCheck = map.get(messageId);
|
||||||
|
final Utilities.Callback<TLRPC.TL_factCheck> callback = msgs.get(key);
|
||||||
|
if (factCheck != null && !factCheck.need_check && callback != null) {
|
||||||
|
callback.run(factCheck);
|
||||||
|
processed2++;
|
||||||
|
loading.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed2 > 0) {
|
||||||
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.factCheckLoaded);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.toload.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Key {
|
||||||
|
public final long dialogId;
|
||||||
|
public final int messageId;
|
||||||
|
public final long hash;
|
||||||
|
|
||||||
|
private Key(long did, int mid, long hash) {
|
||||||
|
dialogId = did;
|
||||||
|
messageId = mid;
|
||||||
|
this.hash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Long.hashCode(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Key of(MessageObject msg) {
|
||||||
|
if (msg == null) return null;
|
||||||
|
if (msg.messageOwner == null) return null;
|
||||||
|
if (msg.messageOwner.factcheck == null) return null;
|
||||||
|
return new Key(msg.getDialogId(), msg.getId(), msg.messageOwner.factcheck.hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getFromDatabase(ArrayList<Key> keys, Utilities.Callback<ArrayList<TLRPC.TL_factCheck>> whenGot) {
|
||||||
|
if (whenGot == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (keys == null || keys.isEmpty()) {
|
||||||
|
whenGot.run(new ArrayList<>());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final MessagesStorage storage = MessagesStorage.getInstance(currentAccount);
|
||||||
|
storage.getStorageQueue().postRunnable(() -> {
|
||||||
|
ArrayList<TLRPC.TL_factCheck> result = new ArrayList<>();
|
||||||
|
SQLiteCursor cursor = null;
|
||||||
|
try {
|
||||||
|
SQLiteDatabase db = storage.getDatabase();
|
||||||
|
|
||||||
|
ArrayList<Long> hashes = new ArrayList<>();
|
||||||
|
for (Key key : keys) {
|
||||||
|
hashes.add(key.hash);
|
||||||
|
result.add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = db.queryFinalized("SELECT data FROM fact_checks WHERE hash IN (" + TextUtils.join(", ", hashes) + ")");
|
||||||
|
while (cursor.next()) {
|
||||||
|
NativeByteBuffer data = cursor.byteBufferValue(0);
|
||||||
|
TLRPC.TL_factCheck factCheck = TLRPC.TL_factCheck.TLdeserialize(data, data.readInt32(false), false);
|
||||||
|
if (factCheck == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
for (int i = 0; i < keys.size(); ++i) {
|
||||||
|
final Key key = keys.get(i);
|
||||||
|
if (factCheck.hash == key.hash) {
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index >= 0 && index < result.size()) {
|
||||||
|
result.set(index, factCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cursor.dispose();
|
||||||
|
cursor = null;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
} finally {
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
whenGot.run(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveToDatabase(TLRPC.TL_factCheck factCheck) {
|
||||||
|
if (factCheck == null) return;
|
||||||
|
final MessagesStorage storage = MessagesStorage.getInstance(currentAccount);
|
||||||
|
storage.getStorageQueue().postRunnable(() -> {
|
||||||
|
SQLitePreparedStatement state = null;
|
||||||
|
try {
|
||||||
|
SQLiteDatabase db = storage.getDatabase();
|
||||||
|
|
||||||
|
state = db.executeFast("REPLACE INTO fact_checks VALUES(?, ?, ?)");
|
||||||
|
state.requery();
|
||||||
|
state.bindLong(1, factCheck.hash);
|
||||||
|
NativeByteBuffer buffer = new NativeByteBuffer(factCheck.getObjectSize());
|
||||||
|
factCheck.serializeToStream(buffer);
|
||||||
|
state.bindByteBuffer(2, buffer);
|
||||||
|
state.bindLong(3, System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 60);
|
||||||
|
state.step();
|
||||||
|
state.dispose();
|
||||||
|
state = null;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
} finally {
|
||||||
|
if (state != null) {
|
||||||
|
state.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
clearExpiredInDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean clearedExpiredInDatabase;
|
||||||
|
private void clearExpiredInDatabase() {
|
||||||
|
if (clearedExpiredInDatabase) return;
|
||||||
|
clearedExpiredInDatabase = true;
|
||||||
|
|
||||||
|
final MessagesStorage storage = MessagesStorage.getInstance(currentAccount);
|
||||||
|
storage.getStorageQueue().postRunnable(() -> {
|
||||||
|
try {
|
||||||
|
SQLiteDatabase db = storage.getDatabase();
|
||||||
|
db.executeFast("DELETE FROM fact_checks WHERE expires > " + System.currentTimeMillis()).stepThis().dispose();
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AlertDialog currentDialog;
|
||||||
|
public void openFactCheckEditor(Context context, Theme.ResourcesProvider resourcesProvider, MessageObject messageObject, boolean forceNotAdaptive) {
|
||||||
|
BaseFragment fragment = LaunchActivity.getLastFragment();
|
||||||
|
Activity activity = AndroidUtilities.findActivity(context);
|
||||||
|
View currentFocus = activity != null ? activity.getCurrentFocus() : null;
|
||||||
|
final boolean isKeyboardVisible = fragment != null && fragment.getFragmentView() instanceof SizeNotifierFrameLayout && ((SizeNotifierFrameLayout) fragment.getFragmentView()).measureKeyboardHeight() > dp(20);
|
||||||
|
final boolean adaptive = isKeyboardVisible && !forceNotAdaptive;
|
||||||
|
AlertDialog[] dialog = new AlertDialog[1];
|
||||||
|
AlertDialog.Builder builder;
|
||||||
|
if (adaptive) {
|
||||||
|
builder = new AlertDialogDecor.Builder(context, resourcesProvider);
|
||||||
|
} else {
|
||||||
|
builder = new AlertDialog.Builder(context, resourcesProvider);
|
||||||
|
}
|
||||||
|
TextView[] positiveButton = new TextView[1];
|
||||||
|
|
||||||
|
final boolean creating = messageObject == null || messageObject.messageOwner == null || messageObject.messageOwner.factcheck == null;
|
||||||
|
builder.setTitle(getString(R.string.FactCheckDialog));
|
||||||
|
final int MAX_LENGTH = MessagesController.getInstance(currentAccount).factcheckLengthLimit;
|
||||||
|
EditTextCaption editText = new EditTextCaption(context, resourcesProvider) {
|
||||||
|
AnimatedColor limitColor = new AnimatedColor(this);
|
||||||
|
private int limitCount;
|
||||||
|
AnimatedTextView.AnimatedTextDrawable limit = new AnimatedTextView.AnimatedTextDrawable(false, true, true); {
|
||||||
|
limit.setAnimationProperties(.2f, 0, 160, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||||
|
limit.setTextSize(dp(15.33f));
|
||||||
|
limit.setCallback(this);
|
||||||
|
limit.setGravity(Gravity.RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean verifyDrawable(@NonNull Drawable who) {
|
||||||
|
return who == limit || super.verifyDrawable(who);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
|
||||||
|
super.onTextChanged(text, start, lengthBefore, lengthAfter);
|
||||||
|
|
||||||
|
if (limit != null) {
|
||||||
|
limitCount = MAX_LENGTH - text.length();
|
||||||
|
limit.cancelAnimation();
|
||||||
|
limit.setText(limitCount > 4 ? "" : "" + limitCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void extendActionMode(ActionMode actionMode, Menu menu) {
|
||||||
|
if (menu.findItem(R.id.menu_bold) != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
menu.removeItem(android.R.id.shareText);
|
||||||
|
}
|
||||||
|
int order = 6;
|
||||||
|
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(getString("Bold", R.string.Bold));
|
||||||
|
stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
menu.add(R.id.menu_groupbolditalic, R.id.menu_bold, order++, stringBuilder);
|
||||||
|
stringBuilder = new SpannableStringBuilder(getString("Italic", R.string.Italic));
|
||||||
|
stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
menu.add(R.id.menu_groupbolditalic, R.id.menu_italic, order++, stringBuilder);
|
||||||
|
menu.add(R.id.menu_groupbolditalic, R.id.menu_link, order++, getString("CreateLink", R.string.CreateLink));
|
||||||
|
menu.add(R.id.menu_groupbolditalic, R.id.menu_regular, order++, getString("Regular", R.string.Regular));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void dispatchDraw(Canvas canvas) {
|
||||||
|
super.dispatchDraw(canvas);
|
||||||
|
|
||||||
|
limit.setTextColor(limitColor.set(Theme.getColor(limitCount < 0 ? Theme.key_text_RedRegular : Theme.key_dialogSearchHint, resourcesProvider)));
|
||||||
|
limit.setBounds(getScrollX(), 0, getScrollX() + getWidth(), getHeight());
|
||||||
|
limit.draw(canvas);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
editText.lineYFix = true;
|
||||||
|
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||||
|
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||||
|
String text = editText.getText().toString();
|
||||||
|
if (text.length() > MAX_LENGTH) {
|
||||||
|
AndroidUtilities.shakeView(editText);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TLRPC.TL_textWithEntities textObj = new TLRPC.TL_textWithEntities();
|
||||||
|
CharSequence[] message = new CharSequence[] { editText.getText() };
|
||||||
|
textObj.entities = MediaDataController.getInstance(currentAccount).getEntities(message, true);
|
||||||
|
textObj.text = message[0] == null ? "" : message[0].toString();
|
||||||
|
applyFactCheck(messageObject, textObj, creating);
|
||||||
|
|
||||||
|
if (dialog[0] != null) {
|
||||||
|
dialog[0].dismiss();
|
||||||
|
}
|
||||||
|
if (dialog[0] == currentDialog) {
|
||||||
|
currentDialog = null;
|
||||||
|
}
|
||||||
|
if (currentFocus != null) {
|
||||||
|
currentFocus.requestFocus();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
MediaDataController.getInstance(currentAccount).fetchNewEmojiKeywords(AndroidUtilities.getCurrentKeyboardLanguage(), true);
|
||||||
|
editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
|
||||||
|
editText.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider));
|
||||||
|
editText.setHintColor(Theme.getColor(Theme.key_groupcreate_hintText, resourcesProvider));
|
||||||
|
editText.setHintText(getString(R.string.FactCheckPlaceholder));
|
||||||
|
editText.setFocusable(true);
|
||||||
|
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
|
||||||
|
editText.setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField, resourcesProvider), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated, resourcesProvider), Theme.getColor(Theme.key_text_RedRegular, resourcesProvider));
|
||||||
|
editText.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||||
|
editText.setBackgroundDrawable(null);
|
||||||
|
editText.setPadding(0, dp(6), 0, dp(6));
|
||||||
|
|
||||||
|
TLRPC.TL_factCheck factCheck = messageObject.getFactCheck();
|
||||||
|
if (factCheck != null && factCheck.text != null) {
|
||||||
|
CharSequence text = SpannableStringBuilder.valueOf(factCheck.text.text);
|
||||||
|
MessageObject.addEntitiesToText(text, factCheck.text.entities, false, true, false, false);
|
||||||
|
editText.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
editText.addTextChangedListener(new TextWatcher() {
|
||||||
|
boolean ignoreTextChange;
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
if (ignoreTextChange) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (s.length() > MAX_LENGTH) {
|
||||||
|
ignoreTextChange = true;
|
||||||
|
s.delete(MAX_LENGTH, s.length());
|
||||||
|
AndroidUtilities.shakeView(editText);
|
||||||
|
editText.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
|
||||||
|
ignoreTextChange = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (positiveButton[0] != null) {
|
||||||
|
final boolean showDone = s.length() > 0 || factCheck == null;
|
||||||
|
positiveButton[0].setText(getString(showDone ? R.string.Done : R.string.Remove));
|
||||||
|
positiveButton[0].setTextColor(Theme.getColor(showDone ? Theme.key_dialogButton : Theme.key_text_RedBold));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
LinearLayout container = new LinearLayout(context);
|
||||||
|
container.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
|
||||||
|
container.addView(editText, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 0, 24, 10));
|
||||||
|
builder.makeCustomMaxHeight();
|
||||||
|
builder.setView(container);
|
||||||
|
builder.setWidth(dp(292));
|
||||||
|
|
||||||
|
builder.setPositiveButton(getString(R.string.Done), (dialogInterface, i) -> {
|
||||||
|
String text = editText.getText().toString();
|
||||||
|
if (text.length() > MAX_LENGTH) {
|
||||||
|
AndroidUtilities.shakeView(editText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TLRPC.TL_textWithEntities textObj = new TLRPC.TL_textWithEntities();
|
||||||
|
CharSequence[] message = new CharSequence[] { editText.getText() };
|
||||||
|
textObj.entities = MediaDataController.getInstance(currentAccount).getEntities(message, true);
|
||||||
|
textObj.text = message[0] == null ? "" : message[0].toString();
|
||||||
|
applyFactCheck(messageObject, textObj, creating);
|
||||||
|
|
||||||
|
dialogInterface.dismiss();
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(getString("Cancel", R.string.Cancel), (dialogInterface, i) -> {
|
||||||
|
dialogInterface.dismiss();
|
||||||
|
});
|
||||||
|
if (adaptive) {
|
||||||
|
dialog[0] = currentDialog = builder.create();
|
||||||
|
currentDialog.setOnDismissListener(d -> {
|
||||||
|
currentDialog = null;
|
||||||
|
currentFocus.requestFocus();
|
||||||
|
});
|
||||||
|
currentDialog.setOnShowListener(d -> {
|
||||||
|
editText.requestFocus();
|
||||||
|
AndroidUtilities.showKeyboard(editText);
|
||||||
|
});
|
||||||
|
currentDialog.showDelayed(250);
|
||||||
|
} else {
|
||||||
|
dialog[0] = builder.create();
|
||||||
|
dialog[0].setOnDismissListener(d -> {
|
||||||
|
AndroidUtilities.hideKeyboard(editText);
|
||||||
|
});
|
||||||
|
dialog[0].setOnShowListener(d -> {
|
||||||
|
editText.requestFocus();
|
||||||
|
AndroidUtilities.showKeyboard(editText);
|
||||||
|
});
|
||||||
|
dialog[0].show();
|
||||||
|
}
|
||||||
|
dialog[0].setDismissDialogByButtons(false);
|
||||||
|
View button = dialog[0].getButton(DialogInterface.BUTTON_POSITIVE);
|
||||||
|
if (button instanceof TextView) {
|
||||||
|
positiveButton[0] = (TextView) button;
|
||||||
|
}
|
||||||
|
editText.setSelection(editText.getText().length());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyFactCheck(MessageObject messageObject, TLRPC.TL_textWithEntities text, boolean created) {
|
||||||
|
TLObject req;
|
||||||
|
|
||||||
|
if (text == null || TextUtils.isEmpty(text.text)) {
|
||||||
|
if (created) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TLRPC.TL_deleteFactCheck r = new TLRPC.TL_deleteFactCheck();
|
||||||
|
r.peer = MessagesController.getInstance(currentAccount).getInputPeer(messageObject.getDialogId());
|
||||||
|
r.msg_id = messageObject.getId();
|
||||||
|
req = r;
|
||||||
|
} else {
|
||||||
|
TLRPC.TL_editFactCheck r = new TLRPC.TL_editFactCheck();
|
||||||
|
r.peer = MessagesController.getInstance(currentAccount).getInputPeer(messageObject.getDialogId());
|
||||||
|
r.msg_id = messageObject.getId();
|
||||||
|
r.text = text;
|
||||||
|
req = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Context context = LaunchActivity.instance != null ? LaunchActivity.instance : ApplicationLoader.applicationContext;
|
||||||
|
final AlertDialog progressDialog = new AlertDialog(context, AlertDialog.ALERT_TYPE_SPINNER);
|
||||||
|
progressDialog.showDelayed(320);
|
||||||
|
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
if (res instanceof TLRPC.Updates) {
|
||||||
|
MessagesController.getInstance(currentAccount).processUpdates((TLRPC.Updates) res, false);
|
||||||
|
|
||||||
|
BaseFragment fragment = LaunchActivity.getSafeLastFragment();
|
||||||
|
if (fragment != null) {
|
||||||
|
final boolean deleted = text == null || TextUtils.isEmpty(text.text);
|
||||||
|
if (deleted || !created) {
|
||||||
|
BulletinFactory.of(fragment).createSimpleBulletin(deleted ? R.raw.ic_delete : R.raw.contact_check, getString(deleted ? R.string.FactCheckDeleted : R.string.FactCheckEdited)).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
progressDialog.dismiss();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -880,6 +880,9 @@ public class FileLoadOperation {
|
||||||
return wasPaused;
|
return wasPaused;
|
||||||
}
|
}
|
||||||
if (location == null && webLocation == null) {
|
if (location == null && webLocation == null) {
|
||||||
|
if (BuildVars.DEBUG_VERSION) {
|
||||||
|
FileLog.d("loadOperation: no location, failing");
|
||||||
|
}
|
||||||
onFail(true, 0);
|
onFail(true, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,6 +312,7 @@ public class FileLoader extends BaseController {
|
||||||
String key = getAttachFileName(document);
|
String key = getAttachFileName(document);
|
||||||
if (loadingVideos.containsKey(key + (player ? "" : "p"))) {
|
if (loadingVideos.containsKey(key + (player ? "" : "p"))) {
|
||||||
loadingVideos.put(key + (player ? "p" : ""), true);
|
loadingVideos.put(key + (player ? "p" : ""), true);
|
||||||
|
getNotificationCenter().postNotificationName(NotificationCenter.videoLoadingStateChanged, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
public class FilePathDatabase {
|
public class FilePathDatabase {
|
||||||
|
@ -26,6 +27,8 @@ public class FilePathDatabase {
|
||||||
private File cacheFile;
|
private File cacheFile;
|
||||||
private File shmCacheFile;
|
private File shmCacheFile;
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<String, String> cache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final static int LAST_DB_VERSION = 7;
|
private final static int LAST_DB_VERSION = 7;
|
||||||
|
|
||||||
private final static String DATABASE_NAME = "file_to_path";
|
private final static String DATABASE_NAME = "file_to_path";
|
||||||
|
@ -159,6 +162,15 @@ public class FilePathDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPath(long documentId, int dc, int type, boolean useQueue) {
|
public String getPath(long documentId, int dc, int type, boolean useQueue) {
|
||||||
|
final long start = System.currentTimeMillis();
|
||||||
|
final String key = documentId + "_" + dc + "_" + type;
|
||||||
|
String path = cache.get(key);
|
||||||
|
if (path != null) {
|
||||||
|
if (BuildVars.DEBUG_VERSION) {
|
||||||
|
FileLog.d("get file path cached id=" + documentId + " dc=" + dc + " type=" + type + " path=" + path + " in " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
if (useQueue) {
|
if (useQueue) {
|
||||||
if (BuildVars.DEBUG_PRIVATE_VERSION) {
|
if (BuildVars.DEBUG_PRIVATE_VERSION) {
|
||||||
if (dispatchQueue != null && dispatchQueue.getHandler() != null && Thread.currentThread() == dispatchQueue.getHandler().getLooper().getThread()) {
|
if (dispatchQueue != null && dispatchQueue.getHandler() != null && Thread.currentThread() == dispatchQueue.getHandler().getLooper().getThread()) {
|
||||||
|
@ -178,7 +190,7 @@ public class FilePathDatabase {
|
||||||
if (cursor.next()) {
|
if (cursor.next()) {
|
||||||
res[0] = cursor.stringValue(0);
|
res[0] = cursor.stringValue(0);
|
||||||
if (BuildVars.DEBUG_VERSION) {
|
if (BuildVars.DEBUG_VERSION) {
|
||||||
FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res[0]);
|
FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res[0] + " in " + (System.currentTimeMillis() - start) + "ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -195,6 +207,9 @@ public class FilePathDatabase {
|
||||||
syncLatch.await();
|
syncLatch.await();
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
}
|
}
|
||||||
|
if (res[0] != null) {
|
||||||
|
cache.put(key, res[0]);
|
||||||
|
}
|
||||||
return res[0];
|
return res[0];
|
||||||
} else {
|
} else {
|
||||||
if (database == null) {
|
if (database == null) {
|
||||||
|
@ -207,7 +222,7 @@ public class FilePathDatabase {
|
||||||
if (cursor.next()) {
|
if (cursor.next()) {
|
||||||
res = cursor.stringValue(0);
|
res = cursor.stringValue(0);
|
||||||
if (BuildVars.DEBUG_VERSION) {
|
if (BuildVars.DEBUG_VERSION) {
|
||||||
FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res);
|
FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res + " in " + (System.currentTimeMillis() - start) + "ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLiteException e) {
|
} catch (SQLiteException e) {
|
||||||
|
@ -217,6 +232,9 @@ public class FilePathDatabase {
|
||||||
cursor.dispose();
|
cursor.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (res != null) {
|
||||||
|
cache.put(key, res);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,8 +286,10 @@ public class FilePathDatabase {
|
||||||
state.bindInteger(5, flags);
|
state.bindInteger(5, flags);
|
||||||
state.step();
|
state.step();
|
||||||
state.dispose();
|
state.dispose();
|
||||||
|
cache.put(id + "_" + dc + "_" + type, path);
|
||||||
} else {
|
} else {
|
||||||
database.executeFast("DELETE FROM paths WHERE document_id = " + id + " AND dc_id = " + dc + " AND type = " + type).stepThis().dispose();
|
database.executeFast("DELETE FROM paths WHERE document_id = " + id + " AND dc_id = " + dc + " AND type = " + type).stepThis().dispose();
|
||||||
|
cache.remove(id + "_" + dc + "_" + type);
|
||||||
}
|
}
|
||||||
} catch (SQLiteException e) {
|
} catch (SQLiteException e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
|
@ -326,6 +346,7 @@ public class FilePathDatabase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
cache.clear();
|
||||||
postRunnable(() -> {
|
postRunnable(() -> {
|
||||||
ensureDatabaseCreated();
|
ensureDatabaseCreated();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -248,7 +248,7 @@ public class FilesMigrationService extends Service {
|
||||||
title.setGravity(Gravity.START);
|
title.setGravity(Gravity.START);
|
||||||
title.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
title.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
||||||
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
|
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
|
||||||
title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
title.setTypeface(AndroidUtilities.bold());
|
||||||
title.setText(LocaleController.getString("MigrateOldFolderTitle", R.string.MigrateOldFolderTitle));
|
title.setText(LocaleController.getString("MigrateOldFolderTitle", R.string.MigrateOldFolderTitle));
|
||||||
linearLayout.addView(title, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 21, 30, 21, 0));
|
linearLayout.addView(title, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 21, 30, 21, 0));
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ public class FilesMigrationService extends Service {
|
||||||
buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0);
|
buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0);
|
||||||
buttonTextView.setGravity(Gravity.CENTER);
|
buttonTextView.setGravity(Gravity.CENTER);
|
||||||
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
buttonTextView.setTypeface(AndroidUtilities.bold());
|
||||||
buttonTextView.setText(LocaleController.getString("MigrateOldFolderButton", R.string.MigrateOldFolderButton));
|
buttonTextView.setText(LocaleController.getString("MigrateOldFolderButton", R.string.MigrateOldFolderButton));
|
||||||
|
|
||||||
buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
||||||
|
|
|
@ -0,0 +1,308 @@
|
||||||
|
package org.telegram.messenger;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
|
import org.telegram.tgnet.TLObject;
|
||||||
|
import org.telegram.tgnet.TLRPC;
|
||||||
|
import org.telegram.ui.ChatActivity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class HashtagSearchController {
|
||||||
|
private static volatile HashtagSearchController[] Instance = new HashtagSearchController[UserConfig.MAX_ACCOUNT_COUNT];
|
||||||
|
private static final Object[] lockObjects = new Object[UserConfig.MAX_ACCOUNT_COUNT];
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++) {
|
||||||
|
lockObjects[i] = new Object();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HashtagSearchController getInstance(int num) {
|
||||||
|
HashtagSearchController localInstance = Instance[num];
|
||||||
|
if (localInstance == null) {
|
||||||
|
synchronized (lockObjects[num]) {
|
||||||
|
localInstance = Instance[num];
|
||||||
|
if (localInstance == null) {
|
||||||
|
Instance[num] = localInstance = new HashtagSearchController(num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return localInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int currentAccount;
|
||||||
|
|
||||||
|
private final SearchResult myMessagesSearch = new SearchResult();
|
||||||
|
private final SearchResult channelPostsSearch = new SearchResult();
|
||||||
|
private final SharedPreferences historyPreferences;
|
||||||
|
|
||||||
|
public final ArrayList<String> history = new ArrayList<>();
|
||||||
|
public final static int HISTORY_LIMIT = 100;
|
||||||
|
|
||||||
|
private HashtagSearchController(int currentAccount) {
|
||||||
|
this.currentAccount = currentAccount;
|
||||||
|
|
||||||
|
historyPreferences = ApplicationLoader.applicationContext.getSharedPreferences("hashtag_search_history" + currentAccount, Activity.MODE_PRIVATE);
|
||||||
|
loadHistoryFromPref();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadHistoryFromPref() {
|
||||||
|
int count = historyPreferences.getInt("count", 0);
|
||||||
|
history.clear();
|
||||||
|
history.ensureCapacity(count);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
String value = historyPreferences.getString("e_" + i, "");
|
||||||
|
if (!value.startsWith("#") && !value.startsWith("$")) {
|
||||||
|
value = "#" + value;
|
||||||
|
}
|
||||||
|
history.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveHistoryToPref() {
|
||||||
|
SharedPreferences.Editor editor = historyPreferences.edit();
|
||||||
|
editor.clear();
|
||||||
|
editor.putInt("count", history.size());
|
||||||
|
for (int i = 0; i < history.size(); ++i) {
|
||||||
|
editor.putString("e_" + i, history.get(i));
|
||||||
|
}
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putToHistory(String hashtag) {
|
||||||
|
if (!hashtag.startsWith("#") && !hashtag.startsWith("$")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int index = history.indexOf(hashtag);
|
||||||
|
if (index != -1) {
|
||||||
|
if (index == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
history.remove(index);
|
||||||
|
}
|
||||||
|
history.add(0, hashtag);
|
||||||
|
|
||||||
|
if (history.size() >= HISTORY_LIMIT) {
|
||||||
|
history.subList(HISTORY_LIMIT - 1, history.size()).clear();
|
||||||
|
}
|
||||||
|
saveHistoryToPref();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearHistory() {
|
||||||
|
history.clear();
|
||||||
|
saveHistoryToPref();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeHashtagFromHistory(String hashtag) {
|
||||||
|
int index = history.indexOf(hashtag);
|
||||||
|
if (index != -1) {
|
||||||
|
history.remove(index);
|
||||||
|
saveHistoryToPref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private SearchResult getSearchResult(int searchType) {
|
||||||
|
if (searchType == ChatActivity.SEARCH_MY_MESSAGES) {
|
||||||
|
return myMessagesSearch;
|
||||||
|
} else if (searchType == ChatActivity.SEARCH_PUBLIC_POSTS) {
|
||||||
|
return channelPostsSearch;
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Unknown search type");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<MessageObject> getMessages(int searchType) {
|
||||||
|
return getSearchResult(searchType).messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount(int searchType) {
|
||||||
|
return getSearchResult(searchType).count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEndReached(int searchType) {
|
||||||
|
return getSearchResult(searchType).endReached;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void searchHashtag(String hashtag, int guid, int searchType, int loadIndex) {
|
||||||
|
SearchResult search = getSearchResult(searchType);
|
||||||
|
if (search.lastHashtag == null && hashtag == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashtag != null && hashtag.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashtag == null) {
|
||||||
|
hashtag = search.lastHashtag;
|
||||||
|
} else if (!TextUtils.equals(hashtag, search.lastHashtag)) {
|
||||||
|
search.clear();
|
||||||
|
}
|
||||||
|
search.lastHashtag = hashtag;
|
||||||
|
|
||||||
|
final String query = hashtag;
|
||||||
|
int limit = 30;
|
||||||
|
TLObject request;
|
||||||
|
if (searchType == ChatActivity.SEARCH_MY_MESSAGES) {
|
||||||
|
TLRPC.TL_messages_searchGlobal req = new TLRPC.TL_messages_searchGlobal();
|
||||||
|
req.limit = limit;
|
||||||
|
req.q = query;
|
||||||
|
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
|
||||||
|
req.offset_peer = new TLRPC.TL_inputPeerEmpty();
|
||||||
|
if (search.lastOffsetPeer != null) {
|
||||||
|
req.offset_rate = search.lastOffsetRate;
|
||||||
|
req.offset_id = search.lastOffsetId;
|
||||||
|
req.offset_peer = MessagesController.getInstance(currentAccount).getInputPeer(search.lastOffsetPeer);
|
||||||
|
}
|
||||||
|
request = req;
|
||||||
|
} else {
|
||||||
|
TLRPC.TL_channels_searchPosts req = new TLRPC.TL_channels_searchPosts();
|
||||||
|
req.limit = limit;
|
||||||
|
req.hashtag = query;
|
||||||
|
req.offset_peer = new TLRPC.TL_inputPeerEmpty();
|
||||||
|
if (search.lastOffsetPeer != null) {
|
||||||
|
req.offset_rate = search.lastOffsetRate;
|
||||||
|
req.offset_id = search.lastOffsetId;
|
||||||
|
req.offset_peer = MessagesController.getInstance(currentAccount).getInputPeer(search.lastOffsetPeer);
|
||||||
|
}
|
||||||
|
request = req;
|
||||||
|
}
|
||||||
|
ConnectionsManager.getInstance(currentAccount).sendRequest(request, (res, err) -> {
|
||||||
|
if (res instanceof TLRPC.messages_Messages) {
|
||||||
|
TLRPC.messages_Messages messages = (TLRPC.messages_Messages) res;
|
||||||
|
ArrayList<MessageObject> messageObjects = new ArrayList<>();
|
||||||
|
for (TLRPC.Message msg : messages.messages) {
|
||||||
|
MessageObject obj = new MessageObject(currentAccount, msg, null, null, null, null, null, true, true, 0, false, false, false, searchType);
|
||||||
|
if (obj.hasValidGroupId()) {
|
||||||
|
obj.isPrimaryGroupMessage = true;
|
||||||
|
}
|
||||||
|
obj.setQuery(query);
|
||||||
|
messageObjects.add(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
search.lastOffsetRate = messages.next_rate;
|
||||||
|
|
||||||
|
for (MessageObject msg : messageObjects) {
|
||||||
|
MessageCompositeID compositeId = new MessageCompositeID(msg.messageOwner);
|
||||||
|
Integer id = search.generatedIds.get(compositeId);
|
||||||
|
if (id == null) {
|
||||||
|
id = search.lastGeneratedId--;
|
||||||
|
search.generatedIds.put(compositeId, id);
|
||||||
|
search.messages.add(msg);
|
||||||
|
}
|
||||||
|
msg.messageOwner.realId = msg.messageOwner.id;
|
||||||
|
msg.messageOwner.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!messages.messages.isEmpty()) {
|
||||||
|
TLRPC.Message lastMsg = messages.messages.get(messages.messages.size() - 1);
|
||||||
|
search.lastOffsetId = lastMsg.id;
|
||||||
|
search.lastOffsetPeer = lastMsg.peer_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessagesStorage.getInstance(currentAccount).putUsersAndChats(messages.users, messages.chats, true, true);
|
||||||
|
MessagesController.getInstance(currentAccount).putUsers(messages.users, false);
|
||||||
|
MessagesController.getInstance(currentAccount).putChats(messages.chats, false);
|
||||||
|
|
||||||
|
search.endReached = messages.messages.size() < limit;
|
||||||
|
search.count = Math.max(messages.count, messages.messages.size());
|
||||||
|
|
||||||
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.messagesDidLoad, 0L, messageObjects.size(), messageObjects, false, 0, 0, 0, 0, 2, true, guid, loadIndex, 0, 0, ChatActivity.MODE_SEARCH);
|
||||||
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.hashtagSearchUpdated, guid, search.count, search.endReached, search.getMask(), search.selectedIndex, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void jumpToMessage(int guid, int index, int searchType) {
|
||||||
|
SearchResult search = getSearchResult(searchType);
|
||||||
|
if (index < 0 || index >= search.messages.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
search.selectedIndex = index;
|
||||||
|
NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.hashtagSearchUpdated, guid, search.count, search.endReached, search.getMask(), search.selectedIndex, search.messages.get(index).messageOwner.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearSearchResults() {
|
||||||
|
myMessagesSearch.clear();
|
||||||
|
channelPostsSearch.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearSearchResults(int searchType) {
|
||||||
|
getSearchResult(searchType).clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static class MessageCompositeID {
|
||||||
|
final long dialog_id;
|
||||||
|
final int id;
|
||||||
|
|
||||||
|
MessageCompositeID(TLRPC.Message msg) {
|
||||||
|
this(MessageObject.getDialogId(msg), msg.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageCompositeID(long dialogId, int id) {
|
||||||
|
dialog_id = dialogId;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
MessageCompositeID that = (MessageCompositeID) o;
|
||||||
|
return dialog_id == that.dialog_id && id == that.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(dialog_id, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SearchResult {
|
||||||
|
ArrayList<MessageObject> messages = new ArrayList<>();
|
||||||
|
HashMap<MessageCompositeID, Integer> generatedIds = new HashMap<>();
|
||||||
|
|
||||||
|
int lastOffsetRate;
|
||||||
|
int lastOffsetId;
|
||||||
|
TLRPC.Peer lastOffsetPeer;
|
||||||
|
int lastGeneratedId = Integer.MAX_VALUE;
|
||||||
|
String lastHashtag;
|
||||||
|
int selectedIndex;
|
||||||
|
int count;
|
||||||
|
boolean endReached;
|
||||||
|
|
||||||
|
int getMask() {
|
||||||
|
int mask = 0;
|
||||||
|
if (selectedIndex < messages.size() - 1) {
|
||||||
|
mask |= 1;
|
||||||
|
}
|
||||||
|
if (selectedIndex > 0) {
|
||||||
|
mask |= 2;
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
messages.clear();
|
||||||
|
generatedIds.clear();
|
||||||
|
lastOffsetRate = 0;
|
||||||
|
lastOffsetId = 0;
|
||||||
|
lastOffsetPeer = null;
|
||||||
|
lastGeneratedId = Integer.MAX_VALUE - 10;
|
||||||
|
lastHashtag = null;
|
||||||
|
selectedIndex = 0;
|
||||||
|
count = 0;
|
||||||
|
endReached = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -79,6 +79,7 @@ import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -100,6 +101,7 @@ import java.util.zip.GZIPInputStream;
|
||||||
* firstframe - return firstframe for Lottie or Video animation
|
* firstframe - return firstframe for Lottie or Video animation
|
||||||
* ignoreOrientation - do not extract EXIF orientation and do not apply it to an imagereceiver
|
* ignoreOrientation - do not extract EXIF orientation and do not apply it to an imagereceiver
|
||||||
* exif — check exif contents of invert/orientation
|
* exif — check exif contents of invert/orientation
|
||||||
|
* bnb — airbnb canvas lottie impl
|
||||||
*/
|
*/
|
||||||
public class ImageLoader {
|
public class ImageLoader {
|
||||||
|
|
||||||
|
@ -117,7 +119,8 @@ public class ImageLoader {
|
||||||
ArrayList<AnimatedFileDrawable> cachedAnimatedFileDrawables = new ArrayList<>();
|
ArrayList<AnimatedFileDrawable> cachedAnimatedFileDrawables = new ArrayList<>();
|
||||||
private HashMap<String, CacheImage> imageLoadingByUrl = new HashMap<>();
|
private HashMap<String, CacheImage> imageLoadingByUrl = new HashMap<>();
|
||||||
private HashMap<String, CacheImage> imageLoadingByUrlPframe = new HashMap<>();
|
private HashMap<String, CacheImage> imageLoadingByUrlPframe = new HashMap<>();
|
||||||
private HashMap<String, CacheImage> imageLoadingByKeys = new HashMap<>();
|
public ConcurrentHashMap<String, CacheImage> imageLoadingByKeys = new ConcurrentHashMap<>();
|
||||||
|
public HashSet<String> imageLoadingKeys = new HashSet<>();
|
||||||
private SparseArray<CacheImage> imageLoadingByTag = new SparseArray<>();
|
private SparseArray<CacheImage> imageLoadingByTag = new SparseArray<>();
|
||||||
private HashMap<String, ThumbGenerateInfo> waitingForQualityThumb = new HashMap<>();
|
private HashMap<String, ThumbGenerateInfo> waitingForQualityThumb = new HashMap<>();
|
||||||
private SparseArray<String> waitingForQualityThumbByTag = new SparseArray<>();
|
private SparseArray<String> waitingForQualityThumbByTag = new SparseArray<>();
|
||||||
|
@ -1019,10 +1022,11 @@ public class ImageLoader {
|
||||||
cacheOptions.firstFrame = true;
|
cacheOptions.firstFrame = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final boolean airbnb = cacheImage.filter != null && cacheImage.filter.contains("bnb");
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, decompressGzip(cacheImage.finalFilePath), w, h, cacheOptions, limitFps, null, fitzModifier);
|
lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, decompressGzip(cacheImage.finalFilePath), w, h, cacheOptions, limitFps, null, fitzModifier, airbnb);
|
||||||
} else {
|
} else {
|
||||||
lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, w, h, cacheOptions, limitFps, null, fitzModifier);
|
lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, w, h, cacheOptions, limitFps, null, fitzModifier, airbnb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lastFrameBitmap || firstFrameBitmap) {
|
if (lastFrameBitmap || firstFrameBitmap) {
|
||||||
|
@ -2004,6 +2008,7 @@ public class ImageLoader {
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
imageLoadingByKeys.remove(key);
|
imageLoadingByKeys.remove(key);
|
||||||
|
imageLoadingKeys.remove(cutFilter(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2078,6 +2083,7 @@ public class ImageLoader {
|
||||||
}
|
}
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
imageLoadingByKeys.remove(key);
|
imageLoadingByKeys.remove(key);
|
||||||
|
imageLoadingKeys.remove(cutFilter(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2315,6 +2321,7 @@ public class ImageLoader {
|
||||||
cacheImage.imageType = img.imageType;
|
cacheImage.imageType = img.imageType;
|
||||||
cacheImage.cacheType = img.cacheType;
|
cacheImage.cacheType = img.cacheType;
|
||||||
imageLoadingByKeys.put(key, cacheImage);
|
imageLoadingByKeys.put(key, cacheImage);
|
||||||
|
imageLoadingKeys.add(cutFilter(key));
|
||||||
tasks.add(cacheImage.cacheTask);
|
tasks.add(cacheImage.cacheTask);
|
||||||
}
|
}
|
||||||
cacheImage.addImageReceiver(imageReceiver, key, filter, type, guid);
|
cacheImage.addImageReceiver(imageReceiver, key, filter, type, guid);
|
||||||
|
@ -2948,6 +2955,14 @@ public class ImageLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String cutFilter(String key) {
|
||||||
|
if (key == null) return null;
|
||||||
|
int index = key.indexOf('@');
|
||||||
|
if (index >= 0)
|
||||||
|
return key.substring(0, index);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
public void replaceImageInCache(final String oldKey, final String newKey, final ImageLocation newLocation, boolean post) {
|
public void replaceImageInCache(final String oldKey, final String newKey, final ImageLocation newLocation, boolean post) {
|
||||||
if (post) {
|
if (post) {
|
||||||
AndroidUtilities.runOnUIThread(() -> replaceImageInCacheInternal(oldKey, newKey, newLocation));
|
AndroidUtilities.runOnUIThread(() -> replaceImageInCacheInternal(oldKey, newKey, newLocation));
|
||||||
|
@ -3272,6 +3287,7 @@ public class ImageLoader {
|
||||||
img.cacheTask = new CacheOutTask(img);
|
img.cacheTask = new CacheOutTask(img);
|
||||||
|
|
||||||
imageLoadingByKeys.put(key, img);
|
imageLoadingByKeys.put(key, img);
|
||||||
|
imageLoadingKeys.add(cutFilter(key));
|
||||||
if (thumb != 0) {
|
if (thumb != 0) {
|
||||||
cacheThumbOutQueue.postRunnable(img.cacheTask);
|
cacheThumbOutQueue.postRunnable(img.cacheTask);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3779,6 +3795,7 @@ public class ImageLoader {
|
||||||
cacheImage.filter = filter;
|
cacheImage.filter = filter;
|
||||||
cacheImage.imageType = img.imageType;
|
cacheImage.imageType = img.imageType;
|
||||||
imageLoadingByKeys.put(key, cacheImage);
|
imageLoadingByKeys.put(key, cacheImage);
|
||||||
|
imageLoadingKeys.add(cutFilter(key));
|
||||||
tasks.add(cacheImage.cacheTask);
|
tasks.add(cacheImage.cacheTask);
|
||||||
}
|
}
|
||||||
cacheImage.addImageReceiver(imageReceiver, key, filter, type, guid);
|
cacheImage.addImageReceiver(imageReceiver, key, filter, type, guid);
|
||||||
|
|
|
@ -315,7 +315,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
private boolean isAspectFit;
|
private boolean isAspectFit;
|
||||||
private boolean forcePreview;
|
private boolean forcePreview;
|
||||||
private boolean forceCrossfade;
|
private boolean forceCrossfade;
|
||||||
|
private boolean useRoundRadius = true;
|
||||||
private final int[] roundRadius = new int[4];
|
private final int[] roundRadius = new int[4];
|
||||||
|
private int[] emptyRoundRadius;
|
||||||
private boolean isRoundRect = true;
|
private boolean isRoundRect = true;
|
||||||
private Object mark;
|
private Object mark;
|
||||||
|
|
||||||
|
@ -1009,18 +1011,19 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
if (drawable == null) {
|
if (drawable == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int[] r = getRoundRadius(true);
|
||||||
if (drawable instanceof ClipRoundedDrawable) {
|
if (drawable instanceof ClipRoundedDrawable) {
|
||||||
((ClipRoundedDrawable) drawable).setRadii(roundRadius[0], roundRadius[1], roundRadius[2], roundRadius[3]);
|
((ClipRoundedDrawable) drawable).setRadii(r[0], r[1], r[2], r[3]);
|
||||||
} else if ((hasRoundRadius() || gradientShader != null) && (drawable instanceof BitmapDrawable || drawable instanceof AvatarDrawable)) {
|
} else if ((hasRoundRadius() || gradientShader != null) && (drawable instanceof BitmapDrawable || drawable instanceof AvatarDrawable)) {
|
||||||
if (drawable instanceof AvatarDrawable) {
|
if (drawable instanceof AvatarDrawable) {
|
||||||
((AvatarDrawable) drawable).setRoundRadius(roundRadius[0]);
|
((AvatarDrawable) drawable).setRoundRadius(r[0]);
|
||||||
} else {
|
} else {
|
||||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||||
if (bitmapDrawable instanceof RLottieDrawable) {
|
if (bitmapDrawable instanceof RLottieDrawable) {
|
||||||
|
|
||||||
} else if (bitmapDrawable instanceof AnimatedFileDrawable) {
|
} else if (bitmapDrawable instanceof AnimatedFileDrawable) {
|
||||||
AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable;
|
AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable;
|
||||||
animatedFileDrawable.setRoundRadius(roundRadius);
|
animatedFileDrawable.setRoundRadius(r);
|
||||||
} else if (bitmapDrawable.getBitmap() != null && !bitmapDrawable.getBitmap().isRecycled()) {
|
} else if (bitmapDrawable.getBitmap() != null && !bitmapDrawable.getBitmap().isRecycled()) {
|
||||||
setDrawableShader(drawable, new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
|
setDrawableShader(drawable, new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
|
||||||
}
|
}
|
||||||
|
@ -1209,6 +1212,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
colorFilter = this.colorFilter;
|
colorFilter = this.colorFilter;
|
||||||
roundRadius = this.roundRadius;
|
roundRadius = this.roundRadius;
|
||||||
}
|
}
|
||||||
|
if (!useRoundRadius) roundRadius = emptyRoundRadius;
|
||||||
if (drawable instanceof BitmapDrawable) {
|
if (drawable instanceof BitmapDrawable) {
|
||||||
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
|
||||||
if (drawable instanceof RLottieDrawable) {
|
if (drawable instanceof RLottieDrawable) {
|
||||||
|
@ -1323,7 +1327,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
roundPaint.setAlpha(alpha);
|
roundPaint.setAlpha(alpha);
|
||||||
roundRect.set(drawRegion);
|
roundRect.set(drawRegion);
|
||||||
|
|
||||||
if (isRoundRect) {
|
if (isRoundRect && useRoundRadius) {
|
||||||
try {
|
try {
|
||||||
if (canvas != null) {
|
if (canvas != null) {
|
||||||
if (roundRadius[0] == 0) {
|
if (roundRadius[0] == 0) {
|
||||||
|
@ -1433,7 +1437,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
|
|
||||||
roundPaint.setAlpha(alpha);
|
roundPaint.setAlpha(alpha);
|
||||||
|
|
||||||
if (isRoundRect) {
|
if (isRoundRect && useRoundRadius) {
|
||||||
try {
|
try {
|
||||||
if (canvas != null) {
|
if (canvas != null) {
|
||||||
if (roundRadius[0] == 0) {
|
if (roundRadius[0] == 0) {
|
||||||
|
@ -1874,6 +1878,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
animationNotReady = animation != null && !animation.hasBitmap() || lottieDrawable != null && !lottieDrawable.hasBitmap();
|
animationNotReady = animation != null && !animation.hasBitmap() || lottieDrawable != null && !lottieDrawable.hasBitmap();
|
||||||
colorFilter = this.colorFilter;
|
colorFilter = this.colorFilter;
|
||||||
}
|
}
|
||||||
|
if (!useRoundRadius) roundRadius = emptyRoundRadius;
|
||||||
|
|
||||||
if (animation != null) {
|
if (animation != null) {
|
||||||
animation.setRoundRadius(roundRadius);
|
animation.setRoundRadius(roundRadius);
|
||||||
|
@ -2483,6 +2488,28 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRoundRadiusEnabled(boolean enabled) {
|
||||||
|
if (useRoundRadius != enabled) {
|
||||||
|
useRoundRadius = enabled;
|
||||||
|
if (!useRoundRadius && emptyRoundRadius == null) {
|
||||||
|
emptyRoundRadius = new int[4];
|
||||||
|
emptyRoundRadius[0] = emptyRoundRadius[1] = emptyRoundRadius[2] = emptyRoundRadius[3] = 0;
|
||||||
|
}
|
||||||
|
if (currentImageDrawable != null && imageShader == null) {
|
||||||
|
updateDrawableRadius(currentImageDrawable);
|
||||||
|
}
|
||||||
|
if (currentMediaDrawable != null && mediaShader == null) {
|
||||||
|
updateDrawableRadius(currentMediaDrawable);
|
||||||
|
}
|
||||||
|
if (currentThumbDrawable != null) {
|
||||||
|
updateDrawableRadius(currentThumbDrawable);
|
||||||
|
}
|
||||||
|
if (staticThumbDrawable != null) {
|
||||||
|
updateDrawableRadius(staticThumbDrawable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setMark(Object mark) {
|
public void setMark(Object mark) {
|
||||||
this.mark = mark;
|
this.mark = mark;
|
||||||
}
|
}
|
||||||
|
@ -2499,6 +2526,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
return roundRadius;
|
return roundRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int[] getRoundRadius(boolean includingEmpty) {
|
||||||
|
return !useRoundRadius && includingEmpty ? emptyRoundRadius : roundRadius;
|
||||||
|
}
|
||||||
|
|
||||||
public Object getParentObject() {
|
public Object getParentObject() {
|
||||||
return currentParentObject;
|
return currentParentObject;
|
||||||
}
|
}
|
||||||
|
@ -2618,12 +2649,27 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
animation.stop();
|
animation.stop();
|
||||||
} else {
|
} else {
|
||||||
RLottieDrawable rLottieDrawable = getLottieAnimation();
|
RLottieDrawable rLottieDrawable = getLottieAnimation();
|
||||||
if (rLottieDrawable != null && !rLottieDrawable.isRunning()) {
|
if (rLottieDrawable != null) {
|
||||||
rLottieDrawable.stop();
|
rLottieDrawable.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean emojiPaused;
|
||||||
|
public void setEmojiPaused(boolean paused) {
|
||||||
|
if (emojiPaused == paused) return;
|
||||||
|
emojiPaused = paused;
|
||||||
|
RLottieDrawable rLottieDrawable = getLottieAnimation();
|
||||||
|
allowStartLottieAnimation = !paused;
|
||||||
|
if (rLottieDrawable != null) {
|
||||||
|
if (paused) {
|
||||||
|
rLottieDrawable.stop();
|
||||||
|
} else if (!rLottieDrawable.isRunning()) {
|
||||||
|
rLottieDrawable.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAnimationRunning() {
|
public boolean isAnimationRunning() {
|
||||||
AnimatedFileDrawable animation = getAnimation();
|
AnimatedFileDrawable animation = getAnimation();
|
||||||
return animation != null && animation.isRunning();
|
return animation != null && animation.isRunning();
|
||||||
|
|
|
@ -23,6 +23,8 @@ import android.util.Xml;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
import org.telegram.messenger.time.FastDateFormat;
|
import org.telegram.messenger.time.FastDateFormat;
|
||||||
|
import org.telegram.ui.Stars.StarsController;
|
||||||
|
import org.telegram.ui.Stars.StarsIntroActivity;
|
||||||
import org.telegram.tgnet.ConnectionsManager;
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
import org.telegram.tgnet.TLObject;
|
import org.telegram.tgnet.TLObject;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
|
@ -1168,7 +1170,17 @@ public class LocaleController {
|
||||||
return formatPluralStringComma(key, plural, ',');
|
return formatPluralStringComma(key, plural, ',');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatPluralStringComma(String key, int plural, Object... args) {
|
||||||
|
return formatPluralStringComma(key, plural, ',', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String formatPluralStringComma(String key, int plural, char symbol) {
|
public static String formatPluralStringComma(String key, int plural, char symbol) {
|
||||||
|
return formatPluralStringComma(key, plural, symbol, new Object[] {});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String formatPluralStringComma(String key, int plural, char symbol, Object... args) {
|
||||||
try {
|
try {
|
||||||
if (key == null || key.length() == 0 || getInstance().currentPluralRules == null) {
|
if (key == null || key.length() == 0 || getInstance().currentPluralRules == null) {
|
||||||
return "LOC_ERR:" + key;
|
return "LOC_ERR:" + key;
|
||||||
|
@ -1195,10 +1207,14 @@ public class LocaleController {
|
||||||
value = value.replace("%d", "%1$s");
|
value = value.replace("%d", "%1$s");
|
||||||
value = value.replace("%1$d", "%1$s");
|
value = value.replace("%1$d", "%1$s");
|
||||||
|
|
||||||
|
Object[] a = new Object[(args == null ? 0 : args.length) + 1];
|
||||||
|
for (int i = 0; i < a.length; ++i) {
|
||||||
|
a[i] = i == 0 ? stringBuilder : args[i - 1];
|
||||||
|
}
|
||||||
if (getInstance().currentLocale != null) {
|
if (getInstance().currentLocale != null) {
|
||||||
return String.format(getInstance().currentLocale, value, stringBuilder);
|
return String.format(getInstance().currentLocale, value, a);
|
||||||
} else {
|
} else {
|
||||||
return String.format(value, stringBuilder);
|
return String.format(value, a);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
|
@ -1206,6 +1222,14 @@ public class LocaleController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatNumber(long count, char symbol) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder(String.format("%d", count));
|
||||||
|
for (int a = stringBuilder.length() - 3; a > 0; a -= 3) {
|
||||||
|
stringBuilder.insert(a, symbol);
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public static String formatString(@StringRes int res, Object... args) {
|
public static String formatString(@StringRes int res, Object... args) {
|
||||||
String key = resourcesCacheMap.get(res);
|
String key = resourcesCacheMap.get(res);
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
|
@ -1324,6 +1348,11 @@ public class LocaleController {
|
||||||
amount = Math.abs(amount);
|
amount = Math.abs(amount);
|
||||||
Currency currency = Currency.getInstance(type);
|
Currency currency = Currency.getInstance(type);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case StarsController.currency:
|
||||||
|
customFormat = " %.0f";
|
||||||
|
doubleAmount = amount;
|
||||||
|
break;
|
||||||
|
|
||||||
case "CLF":
|
case "CLF":
|
||||||
customFormat = " %.4f";
|
customFormat = " %.4f";
|
||||||
doubleAmount = amount / 10000.0;
|
doubleAmount = amount / 10000.0;
|
||||||
|
|
|
@ -682,9 +682,7 @@ public class LocationController extends BaseController implements NotificationCe
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
getMessagesStorage().getUsersInternal(usersToLoad, users);
|
||||||
getMessagesStorage().getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.hardware.Sensor;
|
import android.hardware.Sensor;
|
||||||
import android.hardware.SensorEvent;
|
import android.hardware.SensorEvent;
|
||||||
import android.hardware.SensorEventListener;
|
import android.hardware.SensorEventListener;
|
||||||
|
@ -388,6 +389,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
public boolean isPainted;
|
public boolean isPainted;
|
||||||
public boolean isCropped;
|
public boolean isCropped;
|
||||||
public int ttl;
|
public int ttl;
|
||||||
|
public long effectId;
|
||||||
|
|
||||||
public CropState cropState;
|
public CropState cropState;
|
||||||
|
|
||||||
|
@ -457,12 +459,16 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
public boolean hasSpoiler;
|
public boolean hasSpoiler;
|
||||||
public String emoji;
|
public String emoji;
|
||||||
|
|
||||||
|
public int videoOrientation = -1;
|
||||||
|
|
||||||
public boolean isChatPreviewSpoilerRevealed;
|
public boolean isChatPreviewSpoilerRevealed;
|
||||||
public boolean isAttachSpoilerRevealed;
|
public boolean isAttachSpoilerRevealed;
|
||||||
public TLRPC.VideoSize emojiMarkup;
|
public TLRPC.VideoSize emojiMarkup;
|
||||||
|
|
||||||
public int gradientTopColor, gradientBottomColor;
|
public int gradientTopColor, gradientBottomColor;
|
||||||
|
|
||||||
|
public BitmapDrawable thumb;
|
||||||
|
|
||||||
public PhotoEntry(int bucketId, int imageId, long dateTaken, String path, int orientationOrDuration, boolean isVideo, int width, int height, long size) {
|
public PhotoEntry(int bucketId, int imageId, long dateTaken, String path, int orientationOrDuration, boolean isVideo, int width, int height, long size) {
|
||||||
this.bucketId = bucketId;
|
this.bucketId = bucketId;
|
||||||
this.imageId = imageId;
|
this.imageId = imageId;
|
||||||
|
@ -479,6 +485,19 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
this.isVideo = isVideo;
|
this.isVideo = isVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PhotoEntry(int bucketId, int imageId, long dateTaken, String path, int orientation, int duration, boolean isVideo, int width, int height, long size) {
|
||||||
|
this.bucketId = bucketId;
|
||||||
|
this.imageId = imageId;
|
||||||
|
this.dateTaken = dateTaken;
|
||||||
|
this.path = path;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.size = size;
|
||||||
|
this.duration = duration;
|
||||||
|
this.orientation = orientation;
|
||||||
|
this.isVideo = isVideo;
|
||||||
|
}
|
||||||
|
|
||||||
public PhotoEntry setOrientation(Pair<Integer, Integer> rotationAndInvert) {
|
public PhotoEntry setOrientation(Pair<Integer, Integer> rotationAndInvert) {
|
||||||
this.orientation = rotationAndInvert.first;
|
this.orientation = rotationAndInvert.first;
|
||||||
this.invert = rotationAndInvert.second;
|
this.invert = rotationAndInvert.second;
|
||||||
|
@ -498,7 +517,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
}
|
}
|
||||||
|
|
||||||
public PhotoEntry clone() {
|
public PhotoEntry clone() {
|
||||||
PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, isVideo ? duration : orientation, isVideo, width, height, size);
|
PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, orientation, duration, isVideo, width, height, size);
|
||||||
photoEntry.invert = invert;
|
photoEntry.invert = invert;
|
||||||
photoEntry.isMuted = isMuted;
|
photoEntry.isMuted = isMuted;
|
||||||
photoEntry.canDeleteAfter = canDeleteAfter;
|
photoEntry.canDeleteAfter = canDeleteAfter;
|
||||||
|
@ -5120,7 +5139,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
int height = cursor.getInt(heightColumn);
|
int height = cursor.getInt(heightColumn);
|
||||||
long size = cursor.getLong(sizeColumn);
|
long size = cursor.getLong(sizeColumn);
|
||||||
|
|
||||||
PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, orientation, false, width, height, size);
|
PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, orientation, 0, false, width, height, size);
|
||||||
|
|
||||||
if (allPhotosAlbum == null) {
|
if (allPhotosAlbum == null) {
|
||||||
allPhotosAlbum = new AlbumEntry(0, LocaleController.getString("AllPhotos", R.string.AllPhotos), photoEntry);
|
allPhotosAlbum = new AlbumEntry(0, LocaleController.getString("AllPhotos", R.string.AllPhotos), photoEntry);
|
||||||
|
@ -5196,6 +5215,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
int widthColumn = cursor.getColumnIndex(MediaStore.Video.Media.WIDTH);
|
int widthColumn = cursor.getColumnIndex(MediaStore.Video.Media.WIDTH);
|
||||||
int heightColumn = cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT);
|
int heightColumn = cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT);
|
||||||
int sizeColumn = cursor.getColumnIndex(MediaStore.Video.Media.SIZE);
|
int sizeColumn = cursor.getColumnIndex(MediaStore.Video.Media.SIZE);
|
||||||
|
int orientationColumn = cursor.getColumnIndex(MediaStore.Video.Media.ORIENTATION);
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor.moveToNext()) {
|
||||||
String path = cursor.getString(dataColumn);
|
String path = cursor.getString(dataColumn);
|
||||||
|
@ -5211,8 +5231,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
int width = cursor.getInt(widthColumn);
|
int width = cursor.getInt(widthColumn);
|
||||||
int height = cursor.getInt(heightColumn);
|
int height = cursor.getInt(heightColumn);
|
||||||
long size = cursor.getLong(sizeColumn);
|
long size = cursor.getLong(sizeColumn);
|
||||||
|
int orientation = 0;
|
||||||
|
|
||||||
PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, (int) (duration / 1000), true, width, height, size);
|
PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, orientation, (int) (duration / 1000), true, width, height, size);
|
||||||
|
|
||||||
if (allVideosAlbum == null) {
|
if (allVideosAlbum == null) {
|
||||||
allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideos", R.string.AllVideos), photoEntry);
|
allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideos", R.string.AllVideos), photoEntry);
|
||||||
|
|
|
@ -2049,7 +2049,7 @@ public class MediaDataController extends BaseController {
|
||||||
}
|
}
|
||||||
state.dispose();
|
state.dispose();
|
||||||
database.commitTransaction();
|
database.commitTransaction();
|
||||||
if (documents.size() >= maxCount) {
|
if (!replace && documents.size() >= maxCount) {
|
||||||
database.beginTransaction();
|
database.beginTransaction();
|
||||||
for (int a = maxCount; a < documents.size(); a++) {
|
for (int a = maxCount; a < documents.size(); a++) {
|
||||||
database.executeFast("DELETE FROM web_recent_v3 WHERE id = '" + documents.get(a).id + "' AND type = " + cacheType).stepThis().dispose();
|
database.executeFast("DELETE FROM web_recent_v3 WHERE id = '" + documents.get(a).id + "' AND type = " + cacheType).stepThis().dispose();
|
||||||
|
@ -2067,22 +2067,22 @@ public class MediaDataController extends BaseController {
|
||||||
if (gif) {
|
if (gif) {
|
||||||
loadingRecentGifs = false;
|
loadingRecentGifs = false;
|
||||||
recentGifsLoaded = true;
|
recentGifsLoaded = true;
|
||||||
editor.putLong("lastGifLoadTime", System.currentTimeMillis()).commit();
|
editor.putLong("lastGifLoadTime", System.currentTimeMillis()).apply();
|
||||||
} else {
|
} else {
|
||||||
loadingRecentStickers[type] = false;
|
loadingRecentStickers[type] = false;
|
||||||
recentStickersLoaded[type] = true;
|
recentStickersLoaded[type] = true;
|
||||||
if (type == TYPE_IMAGE) {
|
if (type == TYPE_IMAGE) {
|
||||||
editor.putLong("lastStickersLoadTime", System.currentTimeMillis()).commit();
|
editor.putLong("lastStickersLoadTime", System.currentTimeMillis()).apply();
|
||||||
} else if (type == TYPE_MASK) {
|
} else if (type == TYPE_MASK) {
|
||||||
editor.putLong("lastStickersLoadTimeMask", System.currentTimeMillis()).commit();
|
editor.putLong("lastStickersLoadTimeMask", System.currentTimeMillis()).apply();
|
||||||
} else if (type == TYPE_GREETINGS) {
|
} else if (type == TYPE_GREETINGS) {
|
||||||
editor.putLong("lastStickersLoadTimeGreet", System.currentTimeMillis()).commit();
|
editor.putLong("lastStickersLoadTimeGreet", System.currentTimeMillis()).apply();
|
||||||
} else if (type == TYPE_EMOJIPACKS) {
|
} else if (type == TYPE_EMOJIPACKS) {
|
||||||
editor.putLong("lastStickersLoadTimeEmojiPacks", System.currentTimeMillis()).commit();
|
editor.putLong("lastStickersLoadTimeEmojiPacks", System.currentTimeMillis()).apply();
|
||||||
} else if (type == TYPE_PREMIUM_STICKERS) {
|
} else if (type == TYPE_PREMIUM_STICKERS) {
|
||||||
editor.putLong("lastStickersLoadTimePremiumStickers", System.currentTimeMillis()).commit();
|
editor.putLong("lastStickersLoadTimePremiumStickers", System.currentTimeMillis()).apply();
|
||||||
} else {
|
} else {
|
||||||
editor.putLong("lastStickersLoadTimeFavs", System.currentTimeMillis()).commit();
|
editor.putLong("lastStickersLoadTimeFavs", System.currentTimeMillis()).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4689,7 +4689,7 @@ public class MediaDataController extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getMessagesStorage().getUsersInternal(TextUtils.join(",", usersToLoad), res.users);
|
getMessagesStorage().getUsersInternal(usersToLoad, res.users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), res.chats);
|
getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), res.chats);
|
||||||
|
@ -5062,7 +5062,7 @@ public class MediaDataController extends BaseController {
|
||||||
}
|
}
|
||||||
cursor.dispose();
|
cursor.dispose();
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getMessagesStorage().getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getMessagesStorage().getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
|
@ -5839,7 +5839,7 @@ public class MediaDataController extends BaseController {
|
||||||
}
|
}
|
||||||
if (!results.isEmpty()) {
|
if (!results.isEmpty()) {
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getMessagesStorage().getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getMessagesStorage().getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
|
@ -6249,7 +6249,7 @@ public class MediaDataController extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getMessagesStorage().getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getMessagesStorage().getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getMessagesStorage().getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
|
@ -7036,6 +7036,7 @@ public class MediaDataController extends BaseController {
|
||||||
TLRPC.TL_messageEntityBlockquote entity = new TLRPC.TL_messageEntityBlockquote();
|
TLRPC.TL_messageEntityBlockquote entity = new TLRPC.TL_messageEntityBlockquote();
|
||||||
entity.offset = spannable.getSpanStart(span);
|
entity.offset = spannable.getSpanStart(span);
|
||||||
entity.length = Math.min(spannable.getSpanEnd(span), message[0].length()) - entity.offset;
|
entity.length = Math.min(spannable.getSpanEnd(span), message[0].length()) - entity.offset;
|
||||||
|
entity.collapsed = span.isCollapsing;
|
||||||
entities.add(entity);
|
entities.add(entity);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
|
@ -7045,8 +7046,9 @@ public class MediaDataController extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spannable instanceof Spannable) {
|
if (spannable instanceof Spannable) {
|
||||||
AndroidUtilities.addLinksSafe((Spannable) spannable, Linkify.WEB_URLS, false, false);
|
Spannable s = (Spannable) spannable;
|
||||||
URLSpan[] spansUrl = spannable.getSpans(0, message[0].length(), URLSpan.class);
|
AndroidUtilities.addLinksSafe(s, Linkify.WEB_URLS, false, false);
|
||||||
|
URLSpan[] spansUrl = s.getSpans(0, message[0].length(), URLSpan.class);
|
||||||
if (spansUrl != null && spansUrl.length > 0) {
|
if (spansUrl != null && spansUrl.length > 0) {
|
||||||
if (entities == null) {
|
if (entities == null) {
|
||||||
entities = new ArrayList<>();
|
entities = new ArrayList<>();
|
||||||
|
@ -7060,8 +7062,28 @@ public class MediaDataController extends BaseController {
|
||||||
entity.length = Math.min(spannable.getSpanEnd(spansUrl[b]), message[0].length()) - entity.offset;
|
entity.length = Math.min(spannable.getSpanEnd(spansUrl[b]), message[0].length()) - entity.offset;
|
||||||
entity.url = spansUrl[b].getURL();
|
entity.url = spansUrl[b].getURL();
|
||||||
entities.add(entity);
|
entities.add(entity);
|
||||||
|
s.removeSpan(spansUrl[b]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// AndroidUtilities.doSafe(() -> Linkify.addLinks(s, Linkify.PHONE_NUMBERS));
|
||||||
|
// spansUrl = s.getSpans(0, message[0].length(), URLSpan.class);
|
||||||
|
// if (spansUrl != null && spansUrl.length > 0) {
|
||||||
|
// if (entities == null) {
|
||||||
|
// entities = new ArrayList<>();
|
||||||
|
// }
|
||||||
|
// for (int b = 0; b < spansUrl.length; b++) {
|
||||||
|
// if (spansUrl[b] instanceof URLSpanReplacement || spansUrl[b] instanceof URLSpanUserMention) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// TLRPC.TL_messageEntityTextUrl entity = new TLRPC.TL_messageEntityTextUrl();
|
||||||
|
// entity.offset = spannable.getSpanStart(spansUrl[b]);
|
||||||
|
// entity.length = Math.min(spannable.getSpanEnd(spansUrl[b]), message[0].length()) - entity.offset;
|
||||||
|
// entity.url = spansUrl[b].getURL();
|
||||||
|
// entities.add(entity);
|
||||||
|
// s.removeSpan(spansUrl[b]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7119,6 +7141,17 @@ public class MediaDataController extends BaseController {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean stringsEqual(CharSequence a, CharSequence b) {
|
||||||
|
if (a == null && b == null) return true;
|
||||||
|
if (a == null || b == null) return false;
|
||||||
|
if (!TextUtils.equals(a, b)) return false;
|
||||||
|
CharSequence[] A = new CharSequence[] { a };
|
||||||
|
CharSequence[] B = new CharSequence[] { b };
|
||||||
|
ArrayList<TLRPC.MessageEntity> ae = getInstance(UserConfig.selectedAccount).getEntities(A, true);
|
||||||
|
ArrayList<TLRPC.MessageEntity> be = getInstance(UserConfig.selectedAccount).getEntities(B, true);
|
||||||
|
return entitiesEqual(ae, be);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean entitiesEqual(ArrayList<TLRPC.MessageEntity> entities1, ArrayList<TLRPC.MessageEntity> entities2) {
|
public static boolean entitiesEqual(ArrayList<TLRPC.MessageEntity> entities1, ArrayList<TLRPC.MessageEntity> entities2) {
|
||||||
if (entities1.size() != entities2.size()) {
|
if (entities1.size() != entities2.size()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -8057,6 +8090,7 @@ public class MediaDataController extends BaseController {
|
||||||
checkPremiumPromo();
|
checkPremiumPromo();
|
||||||
checkPremiumGiftStickers();
|
checkPremiumGiftStickers();
|
||||||
checkGenericAnimations();
|
checkGenericAnimations();
|
||||||
|
getMessagesController().getAvailableEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveStickerSetToTop(long setId, boolean emojis, boolean masks) {
|
public void moveStickerSetToTop(long setId, boolean emojis, boolean masks) {
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.telegram.ui.ChatActivity;
|
||||||
import org.telegram.ui.Components.AnimatedEmojiDrawable;
|
import org.telegram.ui.Components.AnimatedEmojiDrawable;
|
||||||
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
||||||
import org.telegram.ui.Components.AvatarDrawable;
|
import org.telegram.ui.Components.AvatarDrawable;
|
||||||
|
import org.telegram.ui.Components.ButtonBounce;
|
||||||
import org.telegram.ui.Components.ColoredImageSpan;
|
import org.telegram.ui.Components.ColoredImageSpan;
|
||||||
import org.telegram.ui.Components.Forum.ForumBubbleDrawable;
|
import org.telegram.ui.Components.Forum.ForumBubbleDrawable;
|
||||||
import org.telegram.ui.Components.Forum.ForumUtilities;
|
import org.telegram.ui.Components.Forum.ForumUtilities;
|
||||||
|
@ -72,6 +73,8 @@ import org.telegram.ui.Components.URLSpanReplacement;
|
||||||
import org.telegram.ui.Components.URLSpanUserMention;
|
import org.telegram.ui.Components.URLSpanUserMention;
|
||||||
import org.telegram.ui.Components.spoilers.SpoilerEffect;
|
import org.telegram.ui.Components.spoilers.SpoilerEffect;
|
||||||
import org.telegram.ui.PeerColorActivity;
|
import org.telegram.ui.PeerColorActivity;
|
||||||
|
import org.telegram.ui.Stars.StarsController;
|
||||||
|
import org.telegram.ui.Stars.StarsIntroActivity;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -84,6 +87,7 @@ import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.GregorianCalendar;
|
import java.util.GregorianCalendar;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
@ -167,6 +171,7 @@ public class MessageObject {
|
||||||
private int isRoundVideoCached;
|
private int isRoundVideoCached;
|
||||||
public long eventId;
|
public long eventId;
|
||||||
public int contentType;
|
public int contentType;
|
||||||
|
public int realDate;
|
||||||
public String dateKey;
|
public String dateKey;
|
||||||
public int dateKeyInt;
|
public int dateKeyInt;
|
||||||
public String monthKey;
|
public String monthKey;
|
||||||
|
@ -193,6 +198,8 @@ public class MessageObject {
|
||||||
public int wantedBotKeyboardWidth;
|
public int wantedBotKeyboardWidth;
|
||||||
public boolean attachPathExists;
|
public boolean attachPathExists;
|
||||||
public boolean mediaExists;
|
public boolean mediaExists;
|
||||||
|
public MediaController.PhotoEntry sendPreviewEntry;
|
||||||
|
public boolean sendPreview;
|
||||||
public boolean resendAsIs;
|
public boolean resendAsIs;
|
||||||
public String customReplyName;
|
public String customReplyName;
|
||||||
public boolean useCustomPhoto;
|
public boolean useCustomPhoto;
|
||||||
|
@ -201,6 +208,7 @@ public class MessageObject {
|
||||||
public long loadedFileSize;
|
public long loadedFileSize;
|
||||||
public boolean forceExpired;
|
public boolean forceExpired;
|
||||||
public long actionDeleteGroupEventId = -1;
|
public long actionDeleteGroupEventId = -1;
|
||||||
|
public HashSet<Integer> expandedQuotes;
|
||||||
|
|
||||||
public boolean isSpoilersRevealed;
|
public boolean isSpoilersRevealed;
|
||||||
public boolean isMediaSpoilersRevealed;
|
public boolean isMediaSpoilersRevealed;
|
||||||
|
@ -242,6 +250,8 @@ public class MessageObject {
|
||||||
public boolean preview;
|
public boolean preview;
|
||||||
public boolean previewForward;
|
public boolean previewForward;
|
||||||
|
|
||||||
|
public boolean notime;
|
||||||
|
|
||||||
public int getChatMode() {
|
public int getChatMode() {
|
||||||
if (scheduled) {
|
if (scheduled) {
|
||||||
return ChatActivity.MODE_SCHEDULED;
|
return ChatActivity.MODE_SCHEDULED;
|
||||||
|
@ -327,6 +337,7 @@ public class MessageObject {
|
||||||
public boolean isSaved;
|
public boolean isSaved;
|
||||||
public boolean isSavedFiltered;
|
public boolean isSavedFiltered;
|
||||||
public String quick_reply_shortcut;
|
public String quick_reply_shortcut;
|
||||||
|
public int searchType;
|
||||||
|
|
||||||
private byte[] randomWaveform;
|
private byte[] randomWaveform;
|
||||||
public boolean drawServiceWithDefaultTypeface;
|
public boolean drawServiceWithDefaultTypeface;
|
||||||
|
@ -572,7 +583,7 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < messageOwner.reactions.results.size(); i++) {
|
for (int i = 0; i < messageOwner.reactions.results.size(); i++) {
|
||||||
if (messageOwner.reactions.results.get(i).chosen) {
|
if (messageOwner.reactions.results.get(i).chosen) {
|
||||||
choosenReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(messageOwner.reactions.results.get(i).reaction));
|
choosenReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromTL(messageOwner.reactions.results.get(i).reaction));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return choosenReactions;
|
return choosenReactions;
|
||||||
|
@ -600,6 +611,9 @@ public class MessageObject {
|
||||||
public float currentY;
|
public float currentY;
|
||||||
public float timeAlpha;
|
public float timeAlpha;
|
||||||
public float progress;
|
public float progress;
|
||||||
|
|
||||||
|
public boolean fromPreview;
|
||||||
|
public ChatMessageCell.TransitionParams fromParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class VCardData {
|
public static class VCardData {
|
||||||
|
@ -726,15 +740,23 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean expandedQuotesEquals(HashSet<Integer> a, HashSet<Integer> b) {
|
||||||
|
if (a == null && b == null)
|
||||||
|
return true;
|
||||||
|
if ((a == null ? 0 : a.size()) != (b == null ? 0 : b.size()))
|
||||||
|
return false;
|
||||||
|
return a != null && a.equals(b);
|
||||||
|
}
|
||||||
|
|
||||||
public static class TextLayoutBlock {
|
public static class TextLayoutBlock {
|
||||||
public final static int FLAG_RTL = 1, FLAG_NOT_RTL = 2;
|
public final static int FLAG_RTL = 1, FLAG_NOT_RTL = 2;
|
||||||
|
|
||||||
public boolean first, last;
|
public boolean first, last;
|
||||||
|
public int index;
|
||||||
|
|
||||||
public AtomicReference<Layout> spoilersPatchedTextLayout = new AtomicReference<>();
|
public AtomicReference<Layout> spoilersPatchedTextLayout = new AtomicReference<>();
|
||||||
public StaticLayout textLayout;
|
public StaticLayout textLayout;
|
||||||
public int padTop, padBottom;
|
public int padTop, padBottom;
|
||||||
public float textYOffset;
|
|
||||||
public int charactersOffset;
|
public int charactersOffset;
|
||||||
public int charactersEnd;
|
public int charactersEnd;
|
||||||
public int height;
|
public int height;
|
||||||
|
@ -743,8 +765,13 @@ public class MessageObject {
|
||||||
public List<SpoilerEffect> spoilers = new ArrayList<>();
|
public List<SpoilerEffect> spoilers = new ArrayList<>();
|
||||||
public float maxRight;
|
public float maxRight;
|
||||||
|
|
||||||
|
public MessageObject messageObject;
|
||||||
|
public int collapsedHeight;
|
||||||
|
public ButtonBounce collapsedBounce;
|
||||||
|
|
||||||
public boolean code;
|
public boolean code;
|
||||||
public boolean quote;
|
public boolean quote;
|
||||||
|
public boolean quoteCollapse;
|
||||||
|
|
||||||
public String language;
|
public String language;
|
||||||
public Text languageLayout;
|
public Text languageLayout;
|
||||||
|
@ -758,10 +785,51 @@ public class MessageObject {
|
||||||
public Drawable copySelector;
|
public Drawable copySelector;
|
||||||
public Paint copySeparator;
|
public Paint copySeparator;
|
||||||
|
|
||||||
|
public int height() {
|
||||||
|
return quoteCollapse && collapsed() ? collapsedHeight : height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int height(ChatMessageCell.TransitionParams tp) {
|
||||||
|
if (!quoteCollapse)
|
||||||
|
return height;
|
||||||
|
return AndroidUtilities.lerp(height, collapsedHeight, collapsed(tp));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float collapsed(ChatMessageCell.TransitionParams tp) {
|
||||||
|
final boolean pastCollapsed = tp.animateExpandedQuotes ? (tp.animateExpandedQuotesFrom == null ? true : !tp.animateExpandedQuotesFrom.contains(index)) : collapsed();
|
||||||
|
return AndroidUtilities.lerp(pastCollapsed ? 1f : 0f, collapsed() ? 1f : 0f, tp.animateChangeProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean collapsed() {
|
||||||
|
return messageObject == null || messageObject.expandedQuotes == null || !messageObject.expandedQuotes.contains(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float textYOffset(ArrayList<TextLayoutBlock> blocks) {
|
||||||
|
if (blocks == null) return 0;
|
||||||
|
int h = 0;
|
||||||
|
for (int i = 0; i < blocks.size(); ++i) {
|
||||||
|
TextLayoutBlock block = blocks.get(i);
|
||||||
|
if (block == this) break;
|
||||||
|
h += block.padTop + block.height() + block.padBottom;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float textYOffset(ArrayList<TextLayoutBlock> blocks, ChatMessageCell.TransitionParams tp) {
|
||||||
|
if (blocks == null) return 0;
|
||||||
|
int h = 0;
|
||||||
|
for (int i = 0; i < blocks.size(); ++i) {
|
||||||
|
TextLayoutBlock block = blocks.get(i);
|
||||||
|
if (block == this) break;
|
||||||
|
h += block.padTop + block.height(tp) + block.padBottom;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
public void layoutCode(String lng, int codeLength, boolean noforwards) {
|
public void layoutCode(String lng, int codeLength, boolean noforwards) {
|
||||||
hasCodeCopyButton = codeLength >= 75 && !noforwards;
|
hasCodeCopyButton = codeLength >= 75 && !noforwards;
|
||||||
if (hasCodeCopyButton) {
|
if (hasCodeCopyButton) {
|
||||||
copyText = new Text(LocaleController.getString(R.string.CopyCode).toUpperCase(), SharedConfig.fontSize - 3, AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
copyText = new Text(LocaleController.getString(R.string.CopyCode).toUpperCase(), SharedConfig.fontSize - 3, AndroidUtilities.bold());
|
||||||
copyIcon = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.msg_copy).mutate();
|
copyIcon = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.msg_copy).mutate();
|
||||||
copyIcon.setColorFilter(new PorterDuffColorFilter(copyIconColor, PorterDuff.Mode.SRC_IN));
|
copyIcon.setColorFilter(new PorterDuffColorFilter(copyIconColor, PorterDuff.Mode.SRC_IN));
|
||||||
copySelector = Theme.createRadSelectorDrawable(copySelectorColor, 0, 0, Math.min(5, SharedConfig.bubbleRadius), 0);
|
copySelector = Theme.createRadSelectorDrawable(copySelectorColor, 0, 0, Math.min(5, SharedConfig.bubbleRadius), 0);
|
||||||
|
@ -776,7 +844,7 @@ public class MessageObject {
|
||||||
languageLayout = new Text(
|
languageLayout = new Text(
|
||||||
capitalizeLanguage(lng),
|
capitalizeLanguage(lng),
|
||||||
SharedConfig.fontSize - 1 - CodeHighlighting.getTextSizeDecrement(codeLength) / 2,
|
SharedConfig.fontSize - 1 - CodeHighlighting.getTextSizeDecrement(codeLength) / 2,
|
||||||
AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)
|
AndroidUtilities.bold()
|
||||||
);
|
);
|
||||||
languageHeight = (int) (languageLayout.getTextSize() * 1.714f) + dp(4);
|
languageHeight = (int) (languageLayout.getTextSize() * 1.714f) + dp(4);
|
||||||
}
|
}
|
||||||
|
@ -792,7 +860,9 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
copySelector.setBounds((int) bounds.left + dp(3), (int) (bounds.bottom - dp(38)), (int) bounds.right, (int) bounds.bottom);
|
copySelector.setBounds((int) bounds.left + dp(3), (int) (bounds.bottom - dp(38)), (int) bounds.right, (int) bounds.bottom);
|
||||||
copySelector.setAlpha((int) (0xFF * alpha));
|
copySelector.setAlpha((int) (0xFF * alpha));
|
||||||
copySelector.draw(canvas);
|
if (copySelector.getCallback() != null) {
|
||||||
|
copySelector.draw(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
copySeparator.setColor(ColorUtils.setAlphaComponent(backgroundColor, 0x26));
|
copySeparator.setColor(ColorUtils.setAlphaComponent(backgroundColor, 0x26));
|
||||||
canvas.drawRect(bounds.left + dp(10), bounds.bottom - dp(38) - AndroidUtilities.getShadowHeight(), bounds.right - dp(6.66f), bounds.bottom - dp(38), copySeparator);
|
canvas.drawRect(bounds.left + dp(10), bounds.bottom - dp(38) - AndroidUtilities.getShadowHeight(), bounds.right - dp(6.66f), bounds.bottom - dp(38), copySeparator);
|
||||||
|
@ -949,6 +1019,7 @@ public class MessageObject {
|
||||||
public LongSparseArray<GroupedMessagePosition> positionsArray = new LongSparseArray<>();
|
public LongSparseArray<GroupedMessagePosition> positionsArray = new LongSparseArray<>();
|
||||||
public MessageObject captionMessage;
|
public MessageObject captionMessage;
|
||||||
public boolean isDocuments;
|
public boolean isDocuments;
|
||||||
|
public boolean captionAbove;
|
||||||
|
|
||||||
public GroupedMessagePosition getPosition(MessageObject msg) {
|
public GroupedMessagePosition getPosition(MessageObject msg) {
|
||||||
if (msg == null) {
|
if (msg == null) {
|
||||||
|
@ -1026,6 +1097,7 @@ public class MessageObject {
|
||||||
hasCaption = false;
|
hasCaption = false;
|
||||||
boolean checkCaption = true;
|
boolean checkCaption = true;
|
||||||
|
|
||||||
|
captionAbove = false;
|
||||||
for (int a = (reversed ? count - 1 : 0); (reversed ? a >= 0 : a < count);) {
|
for (int a = (reversed ? count - 1 : 0); (reversed ? a >= 0 : a < count);) {
|
||||||
MessageObject messageObject = messages.get(a);
|
MessageObject messageObject = messages.get(a);
|
||||||
if (a == (reversed ? count - 1 : 0)) {
|
if (a == (reversed ? count - 1 : 0)) {
|
||||||
|
@ -1040,6 +1112,9 @@ public class MessageObject {
|
||||||
isDocuments = true;
|
isDocuments = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (messageObject.messageOwner != null && messageObject.messageOwner.invert_media) {
|
||||||
|
captionAbove = true;
|
||||||
|
}
|
||||||
TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize());
|
TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize());
|
||||||
GroupedMessagePosition position = new GroupedMessagePosition();
|
GroupedMessagePosition position = new GroupedMessagePosition();
|
||||||
position.last = (reversed ? a == 0 : a == count - 1);
|
position.last = (reversed ? a == 0 : a == count - 1);
|
||||||
|
@ -1490,7 +1565,6 @@ public class MessageObject {
|
||||||
|
|
||||||
public int lastLineWidth;
|
public int lastLineWidth;
|
||||||
public int textWidth;
|
public int textWidth;
|
||||||
public int textHeight;
|
|
||||||
public boolean hasRtl;
|
public boolean hasRtl;
|
||||||
public float textXOffset;
|
public float textXOffset;
|
||||||
public ArrayList<TextLayoutBlock> textLayoutBlocks;
|
public ArrayList<TextLayoutBlock> textLayoutBlocks;
|
||||||
|
@ -1568,11 +1642,16 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyToMessage, AbstractMap<Long, TLRPC.User> users, AbstractMap<Long, TLRPC.Chat> chats, LongSparseArray<TLRPC.User> sUsers, LongSparseArray<TLRPC.Chat> sChats, boolean generateLayout, boolean checkMediaExists, long eid, boolean isRepostPreview, boolean isRepostVideoPreview, boolean isSavedMessages) {
|
public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyToMessage, AbstractMap<Long, TLRPC.User> users, AbstractMap<Long, TLRPC.Chat> chats, LongSparseArray<TLRPC.User> sUsers, LongSparseArray<TLRPC.Chat> sChats, boolean generateLayout, boolean checkMediaExists, long eid, boolean isRepostPreview, boolean isRepostVideoPreview, boolean isSavedMessages) {
|
||||||
|
this(accountNum, message, replyToMessage, users, chats, sUsers, sChats, generateLayout, checkMediaExists, eid, isRepostPreview, isRepostVideoPreview, isSavedMessages, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyToMessage, AbstractMap<Long, TLRPC.User> users, AbstractMap<Long, TLRPC.Chat> chats, LongSparseArray<TLRPC.User> sUsers, LongSparseArray<TLRPC.Chat> sChats, boolean generateLayout, boolean checkMediaExists, long eid, boolean isRepostPreview, boolean isRepostVideoPreview, boolean isSavedMessages, int searchType) {
|
||||||
Theme.createCommonMessageResources();
|
Theme.createCommonMessageResources();
|
||||||
|
|
||||||
this.isRepostPreview = isRepostPreview;
|
this.isRepostPreview = isRepostPreview;
|
||||||
this.isRepostVideoPreview = isRepostVideoPreview;
|
this.isRepostVideoPreview = isRepostVideoPreview;
|
||||||
this.isSaved = isSavedMessages || getDialogId(message) == UserConfig.getInstance(accountNum).getClientUserId();
|
this.isSaved = isSavedMessages || getDialogId(message) == UserConfig.getInstance(accountNum).getClientUserId();
|
||||||
|
this.searchType = searchType;
|
||||||
|
|
||||||
currentAccount = accountNum;
|
currentAccount = accountNum;
|
||||||
messageOwner = message;
|
messageOwner = message;
|
||||||
|
@ -1832,6 +1911,33 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TextPaint getTextPaint() {
|
||||||
|
if (emojiOnlyCount >= 1 && messageOwner != null && !hasNonEmojiEntities()) {
|
||||||
|
boolean large = emojiOnlyCount == animatedEmojiCount;
|
||||||
|
switch (Math.max(emojiOnlyCount, animatedEmojiCount)) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
return large ? Theme.chat_msgTextPaintEmoji[0] : Theme.chat_msgTextPaintEmoji[2];
|
||||||
|
case 3:
|
||||||
|
return large ? Theme.chat_msgTextPaintEmoji[1] : Theme.chat_msgTextPaintEmoji[3];
|
||||||
|
case 4:
|
||||||
|
return large ? Theme.chat_msgTextPaintEmoji[2] : Theme.chat_msgTextPaintEmoji[4];
|
||||||
|
case 5:
|
||||||
|
return large ? Theme.chat_msgTextPaintEmoji[3] : Theme.chat_msgTextPaintEmoji[5];
|
||||||
|
case 6:
|
||||||
|
return large ? Theme.chat_msgTextPaintEmoji[4] : Theme.chat_msgTextPaintEmoji[5];
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
default:
|
||||||
|
return Theme.chat_msgTextPaintEmoji[5];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Theme.chat_msgTextPaint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayList<MessageObject> messageObjects, HashMap<String, ArrayList<MessageObject>> messagesByDays, TLRPC.Chat chat, int[] mid, boolean addToEnd) {
|
public MessageObject(int accountNum, TLRPC.TL_channelAdminLogEvent event, ArrayList<MessageObject> messageObjects, HashMap<String, ArrayList<MessageObject>> messagesByDays, TLRPC.Chat chat, int[] mid, boolean addToEnd) {
|
||||||
currentEvent = event;
|
currentEvent = event;
|
||||||
currentAccount = accountNum;
|
currentAccount = accountNum;
|
||||||
|
@ -2426,6 +2532,13 @@ public class MessageObject {
|
||||||
message.date = event.date;
|
message.date = event.date;
|
||||||
TLRPC.Message newMessage = ((TLRPC.TL_channelAdminLogEventActionEditMessage) event.action).new_message;
|
TLRPC.Message newMessage = ((TLRPC.TL_channelAdminLogEventActionEditMessage) event.action).new_message;
|
||||||
TLRPC.Message oldMessage = ((TLRPC.TL_channelAdminLogEventActionEditMessage) event.action).prev_message;
|
TLRPC.Message oldMessage = ((TLRPC.TL_channelAdminLogEventActionEditMessage) event.action).prev_message;
|
||||||
|
if (oldMessage != null) {
|
||||||
|
message.reply_to = oldMessage.reply_to;
|
||||||
|
message.id = oldMessage.id;
|
||||||
|
} else if (newMessage != null) {
|
||||||
|
message.reply_to = newMessage.reply_to;
|
||||||
|
message.id = newMessage.id;
|
||||||
|
}
|
||||||
if (newMessage != null && newMessage.from_id != null) {
|
if (newMessage != null && newMessage.from_id != null) {
|
||||||
message.from_id = newMessage.from_id;
|
message.from_id = newMessage.from_id;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2994,7 +3107,13 @@ public class MessageObject {
|
||||||
message.id = mid[0]++;
|
message.id = mid[0]++;
|
||||||
message.flags = message.flags & ~TLRPC.MESSAGE_FLAG_EDITED;
|
message.flags = message.flags & ~TLRPC.MESSAGE_FLAG_EDITED;
|
||||||
message.dialog_id = -chat.id;
|
message.dialog_id = -chat.id;
|
||||||
|
int realDate = 0;
|
||||||
|
if (event.action instanceof TLRPC.TL_channelAdminLogEventActionDeleteMessage) {
|
||||||
|
realDate = message.date;
|
||||||
|
message.date = event.date;
|
||||||
|
}
|
||||||
MessageObject messageObject = new MessageObject(currentAccount, message, null, null, true, true, eventId);
|
MessageObject messageObject = new MessageObject(currentAccount, message, null, null, true, true, eventId);
|
||||||
|
messageObject.realDate = realDate;
|
||||||
messageObject.currentEvent = event;
|
messageObject.currentEvent = event;
|
||||||
if (messageObject.contentType >= 0) {
|
if (messageObject.contentType >= 0) {
|
||||||
if (mediaController.isPlayingMessage(messageObject)) {
|
if (mediaController.isPlayingMessage(messageObject)) {
|
||||||
|
@ -3282,7 +3401,11 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
String currency;
|
String currency;
|
||||||
try {
|
try {
|
||||||
currency = LocaleController.getInstance().formatCurrencyString(messageOwner.action.total_amount, messageOwner.action.currency);
|
if (StarsController.currency.equals(messageOwner.action.currency)) {
|
||||||
|
currency = StarsController.currency + " " + messageOwner.action.total_amount;
|
||||||
|
} else {
|
||||||
|
currency = LocaleController.getInstance().formatCurrencyString(messageOwner.action.total_amount, messageOwner.action.currency);
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
currency = "<error>";
|
currency = "<error>";
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
|
@ -3300,6 +3423,7 @@ public class MessageObject {
|
||||||
messageText = LocaleController.formatString("PaymentSuccessfullyPaidNoItem", R.string.PaymentSuccessfullyPaidNoItem, currency, name);
|
messageText = LocaleController.formatString("PaymentSuccessfullyPaidNoItem", R.string.PaymentSuccessfullyPaidNoItem, currency, name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
messageText = StarsIntroActivity.replaceStars(messageText);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generatePinMessageText(TLRPC.User fromUser, TLRPC.Chat chat) {
|
public void generatePinMessageText(TLRPC.User fromUser, TLRPC.Chat chat) {
|
||||||
|
@ -3844,14 +3968,14 @@ public class MessageObject {
|
||||||
} else if (wallPaper.for_both && partner != null) {
|
} else if (wallPaper.for_both && partner != null) {
|
||||||
messageText = LocaleController.getString(R.string.ActionSetWallpaperForThisChatSelfBoth);
|
messageText = LocaleController.getString(R.string.ActionSetWallpaperForThisChatSelfBoth);
|
||||||
CharSequence partnerName = new SpannableString(UserObject.getFirstName(partner));
|
CharSequence partnerName = new SpannableString(UserObject.getFirstName(partner));
|
||||||
((SpannableString) partnerName).setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, partnerName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
((SpannableString) partnerName).setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, partnerName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
messageText = AndroidUtilities.replaceCharSequence("%s", messageText, partnerName);
|
messageText = AndroidUtilities.replaceCharSequence("%s", messageText, partnerName);
|
||||||
} else {
|
} else {
|
||||||
messageText = LocaleController.getString(R.string.ActionSetWallpaperForThisChatSelf);
|
messageText = LocaleController.getString(R.string.ActionSetWallpaperForThisChatSelf);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CharSequence userName = new SpannableString(UserObject.getFirstName(user));
|
CharSequence userName = new SpannableString(UserObject.getFirstName(user));
|
||||||
((SpannableString) userName).setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, userName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
((SpannableString) userName).setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, userName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
if (wallPaper.same) {
|
if (wallPaper.same) {
|
||||||
type = TYPE_DATE;
|
type = TYPE_DATE;
|
||||||
messageText = LocaleController.getString(R.string.ActionSetSameWallpaperForThisChat);
|
messageText = LocaleController.getString(R.string.ActionSetSameWallpaperForThisChat);
|
||||||
|
@ -5901,7 +6025,7 @@ public class MessageObject {
|
||||||
// only set in searching with tags
|
// only set in searching with tags
|
||||||
public boolean isPrimaryGroupMessage;
|
public boolean isPrimaryGroupMessage;
|
||||||
public boolean hasValidGroupId() {
|
public boolean hasValidGroupId() {
|
||||||
return getGroupId() != 0 && (photoThumbs != null && !photoThumbs.isEmpty() || isMusic() || isDocument());
|
return getGroupId() != 0 && (photoThumbs != null && !photoThumbs.isEmpty() || sendPreview && (type == TYPE_VIDEO || type == TYPE_PHOTO) || isMusic() || isDocument());
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getGroupIdForUse() {
|
public long getGroupIdForUse() {
|
||||||
|
@ -5922,23 +6046,35 @@ public class MessageObject {
|
||||||
|
|
||||||
public static void addLinks(boolean isOut, CharSequence messageText, boolean botCommands, boolean check, boolean internalOnly) {
|
public static void addLinks(boolean isOut, CharSequence messageText, boolean botCommands, boolean check, boolean internalOnly) {
|
||||||
if (messageText instanceof Spannable && containsUrls(messageText)) {
|
if (messageText instanceof Spannable && containsUrls(messageText)) {
|
||||||
if (messageText.length() < 1000) {
|
try {
|
||||||
try {
|
AndroidUtilities.addLinksSafe((Spannable) messageText, Linkify.WEB_URLS, internalOnly, false);
|
||||||
AndroidUtilities.addLinksSafe((Spannable) messageText, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS, internalOnly, false);
|
} catch (Exception e) {
|
||||||
} catch (Exception e) {
|
FileLog.e(e);
|
||||||
FileLog.e(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
AndroidUtilities.addLinksSafe((Spannable) messageText, Linkify.WEB_URLS, internalOnly, false);
|
|
||||||
} catch (Exception e) {
|
|
||||||
FileLog.e(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
addPhoneLinks(messageText);
|
||||||
addUrlsByPattern(isOut, messageText, botCommands, 0, 0, check);
|
addUrlsByPattern(isOut, messageText, botCommands, 0, 0, check);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void addPhoneLinks(CharSequence messageText) {
|
||||||
|
// if (messageText == null || !(messageText instanceof Spannable))
|
||||||
|
// return;
|
||||||
|
// Spannable spannable = (Spannable) messageText;
|
||||||
|
// SpannableString otherText = new SpannableString(spannable);
|
||||||
|
// AndroidUtilities.doSafe(() -> Linkify.addLinks(otherText, Linkify.PHONE_NUMBERS));
|
||||||
|
// URLSpan[] spans = otherText.getSpans(0, otherText.length(), URLSpan.class);
|
||||||
|
// for (int i = 0; spans != null && i < spans.length; ++i) {
|
||||||
|
// if (spans[i].getURL().startsWith("tel:")) {
|
||||||
|
// spannable.setSpan(
|
||||||
|
// new URLSpanNoUnderline(spans[i].getURL()),
|
||||||
|
// otherText.getSpanStart(spans[i]),
|
||||||
|
// otherText.getSpanEnd(spans[i]),
|
||||||
|
// Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
public void resetPlayingProgress() {
|
public void resetPlayingProgress() {
|
||||||
audioProgress = 0.0f;
|
audioProgress = 0.0f;
|
||||||
audioProgressSec = 0;
|
audioProgressSec = 0;
|
||||||
|
@ -6281,7 +6417,7 @@ public class MessageObject {
|
||||||
if (url.startsWith("+")) {
|
if (url.startsWith("+")) {
|
||||||
tel = "+" + tel;
|
tel = "+" + tel;
|
||||||
}
|
}
|
||||||
spannable.setSpan(new URLSpanBrowser("tel:" + tel, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
spannable.setSpan(new URLSpanNoUnderline("tel:" + tel, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityTextUrl) {
|
} else if (run.urlEntity instanceof TLRPC.TL_messageEntityTextUrl) {
|
||||||
url = run.urlEntity.url;
|
url = run.urlEntity.url;
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
|
@ -6311,7 +6447,7 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity instanceof TLRPC.TL_messageEntityBlockquote) {
|
if (entity instanceof TLRPC.TL_messageEntityBlockquote) {
|
||||||
QuoteSpan.putQuote(spannable, entity.offset, entity.offset + entity.length);
|
QuoteSpan.putQuote(spannable, entity.offset, entity.offset + entity.length, entity.collapsed);
|
||||||
} else if (entity instanceof TLRPC.TL_messageEntityPre) {
|
} else if (entity instanceof TLRPC.TL_messageEntityPre) {
|
||||||
final int start = entity.offset;
|
final int start = entity.offset;
|
||||||
final int end = entity.offset + entity.length;
|
final int end = entity.offset + entity.length;
|
||||||
|
@ -6352,6 +6488,8 @@ public class MessageObject {
|
||||||
return false;
|
return false;
|
||||||
} else if (eventId != 0) {
|
} else if (eventId != 0) {
|
||||||
return false;
|
return false;
|
||||||
|
} else if (searchType == ChatActivity.SEARCH_PUBLIC_POSTS) {
|
||||||
|
return true;
|
||||||
} else if (messageOwner.noforwards) {
|
} else if (messageOwner.noforwards) {
|
||||||
return false;
|
return false;
|
||||||
} else if (messageOwner.fwd_from != null && !isOutOwner() && messageOwner.fwd_from.saved_from_peer != null && getDialogId() == UserConfig.getInstance(currentAccount).getClientUserId()) {
|
} else if (messageOwner.fwd_from != null && !isOutOwner() && messageOwner.fwd_from.saved_from_peer != null && getDialogId() == UserConfig.getInstance(currentAccount).getClientUserId()) {
|
||||||
|
@ -6429,7 +6567,7 @@ public class MessageObject {
|
||||||
maxWidth -= dp(52);
|
maxWidth -= dp(52);
|
||||||
}
|
}
|
||||||
if (needDrawShareButton() && (isSaved || !isOutOwner())) {
|
if (needDrawShareButton() && (isSaved || !isOutOwner())) {
|
||||||
maxWidth -= dp(isSaved && isOutOwner() ? 40 : 10);
|
maxWidth -= dp(isSaved && isOutOwner() ? 40 : 14);
|
||||||
}
|
}
|
||||||
if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) {
|
if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) {
|
||||||
maxWidth -= dp(10);
|
maxWidth -= dp(10);
|
||||||
|
@ -6490,13 +6628,7 @@ public class MessageObject {
|
||||||
if (useManualParse) {
|
if (useManualParse) {
|
||||||
addLinks(isOutOwner(), messageText, true, true);
|
addLinks(isOutOwner(), messageText, true, true);
|
||||||
} else {
|
} else {
|
||||||
// if (messageText instanceof Spannable && messageText.length() < 1000) {
|
addPhoneLinks(messageText);
|
||||||
// try {
|
|
||||||
// AndroidUtilities.addLinks((Spannable) messageText, Linkify.PHONE_NUMBERS);
|
|
||||||
// } catch (Throwable e) {
|
|
||||||
// FileLog.e(e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
if (isYouTubeVideo()) {
|
if (isYouTubeVideo()) {
|
||||||
addUrlsByPattern(isOutOwner(), messageText, false, 3, Integer.MAX_VALUE, false);
|
addUrlsByPattern(isOutOwner(), messageText, false, 3, Integer.MAX_VALUE, false);
|
||||||
|
@ -6664,7 +6796,7 @@ public class MessageObject {
|
||||||
maxWidth += AndroidUtilities.dp(15);
|
maxWidth += AndroidUtilities.dp(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
textHeight = 0;
|
// textHeight = 0;
|
||||||
int linesCount = textLayout.getLineCount();
|
int linesCount = textLayout.getLineCount();
|
||||||
int linesPreBlock = totalAnimatedEmojiCount >= 50 ? LINES_PER_BLOCK_WITH_EMOJI : LINES_PER_BLOCK;
|
int linesPreBlock = totalAnimatedEmojiCount >= 50 ? LINES_PER_BLOCK_WITH_EMOJI : LINES_PER_BLOCK;
|
||||||
|
|
||||||
|
@ -6711,7 +6843,6 @@ public class MessageObject {
|
||||||
hasQuoteAtBottom = false;
|
hasQuoteAtBottom = false;
|
||||||
hasSingleQuote = false;
|
hasSingleQuote = false;
|
||||||
hasSingleCode = false;
|
hasSingleCode = false;
|
||||||
float offset = 0;
|
|
||||||
for (int a = 0; a < textRanges.size(); a++) {
|
for (int a = 0; a < textRanges.size(); a++) {
|
||||||
TextLayoutBlock block = new TextLayoutBlock();
|
TextLayoutBlock block = new TextLayoutBlock();
|
||||||
|
|
||||||
|
@ -6719,7 +6850,12 @@ public class MessageObject {
|
||||||
|
|
||||||
block.code = range.code;
|
block.code = range.code;
|
||||||
block.quote = range.quote;
|
block.quote = range.quote;
|
||||||
|
block.quoteCollapse = range.collapse;
|
||||||
|
if (block.quoteCollapse) {
|
||||||
|
block.messageObject = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
block.index = a;
|
||||||
block.first = a == 0;
|
block.first = a == 0;
|
||||||
block.last = a == textRanges.size() - 1;
|
block.last = a == textRanges.size() - 1;
|
||||||
|
|
||||||
|
@ -6777,25 +6913,21 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
block.textLayout = textLayout;
|
block.textLayout = textLayout;
|
||||||
block.textYOffset = 0;
|
|
||||||
block.charactersOffset = 0;
|
block.charactersOffset = 0;
|
||||||
block.charactersEnd = textLayout.getText().length();
|
block.charactersEnd = textLayout.getText().length();
|
||||||
|
|
||||||
block.height = textLayout.getHeight();
|
block.height = textLayout.getHeight();
|
||||||
textHeight = block.padTop + block.height + block.padBottom;
|
block.collapsedHeight = (int) Math.min(paint.getTextSize() * 1.4f * 3, block.height);
|
||||||
if (emojiOnlyCount != 0) {
|
if (emojiOnlyCount != 0) {
|
||||||
switch (emojiOnlyCount) {
|
switch (emojiOnlyCount) {
|
||||||
case 1:
|
case 1:
|
||||||
textHeight -= dp(5.3f);
|
block.padTop -= dp(5.3f);
|
||||||
block.textYOffset -= dp(5.3f);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
textHeight -= dp(4.5f);
|
block.padTop -= dp(4.5f);
|
||||||
block.textYOffset -= dp(4.5f);
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
textHeight -= dp(4.2f);
|
block.padTop -= dp(4.2f);
|
||||||
block.textYOffset -= dp(4.2f);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6816,21 +6948,14 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
block.textLayout = makeStaticLayout(sb, layoutPaint, blockMaxWidth, 1f, totalAnimatedEmojiCount >= 4 ? -1 : 0, false);
|
block.textLayout = makeStaticLayout(sb, layoutPaint, blockMaxWidth, 1f, totalAnimatedEmojiCount >= 4 ? -1 : 0, false);
|
||||||
|
|
||||||
block.textYOffset = offset;
|
|
||||||
if (a != 0 && emojiOnlyCount <= 0) {
|
|
||||||
block.height = (int) (block.textYOffset - prevOffset);
|
|
||||||
}
|
|
||||||
block.height = block.textLayout.getHeight();//Math.max(block.height, block.textLayout.getLineBottom(block.textLayout.getLineCount() - 1));
|
block.height = block.textLayout.getHeight();//Math.max(block.height, block.textLayout.getLineBottom(block.textLayout.getLineCount() - 1));
|
||||||
textHeight += block.padTop + block.height + block.padBottom;
|
block.collapsedHeight = (int) Math.min(paint.getTextSize() * 1.4f * 3, block.height);
|
||||||
prevOffset = block.textYOffset;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += block.padTop + block.height + block.padBottom;
|
|
||||||
|
|
||||||
textLayoutBlocks.add(block);
|
textLayoutBlocks.add(block);
|
||||||
|
|
||||||
final int currentBlockLinesCount = block.textLayout.getLineCount();
|
final int currentBlockLinesCount = block.textLayout.getLineCount();
|
||||||
|
@ -6976,6 +7101,25 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasWideCode = hasCode && textWidth > generatedWithMinSize - dp(80 + (needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage ? 52 : 0));
|
hasWideCode = hasCode && textWidth > generatedWithMinSize - dp(80 + (needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage ? 52 : 0));
|
||||||
|
factCheckText = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int textHeight() {
|
||||||
|
if (textLayoutBlocks == null) return 0;
|
||||||
|
int h = 0;
|
||||||
|
for (int i = 0; i < textLayoutBlocks.size(); ++i) {
|
||||||
|
h += textLayoutBlocks.get(i).padTop + textLayoutBlocks.get(i).height() + textLayoutBlocks.get(i).padBottom;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int textHeight(ChatMessageCell.TransitionParams tp) {
|
||||||
|
if (textLayoutBlocks == null) return 0;
|
||||||
|
int h = 0;
|
||||||
|
for (int i = 0; i < textLayoutBlocks.size(); ++i) {
|
||||||
|
h += textLayoutBlocks.get(i).padTop + textLayoutBlocks.get(i).height(tp) + textLayoutBlocks.get(i).padBottom;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TextLayoutBlocks {
|
public static class TextLayoutBlocks {
|
||||||
|
@ -6983,13 +7127,35 @@ public class MessageObject {
|
||||||
public final CharSequence text;
|
public final CharSequence text;
|
||||||
public int lastLineWidth;
|
public int lastLineWidth;
|
||||||
public int textWidth;
|
public int textWidth;
|
||||||
public int textHeight;
|
|
||||||
public boolean hasRtl;
|
public boolean hasRtl;
|
||||||
public float textXOffset;
|
public float textXOffset;
|
||||||
public final ArrayList<TextLayoutBlock> textLayoutBlocks = new ArrayList<>();
|
public final ArrayList<TextLayoutBlock> textLayoutBlocks = new ArrayList<>();
|
||||||
public boolean hasCode, hasCodeAtTop, hasCodeAtBottom, hasSingleCode;
|
public boolean hasCode, hasCodeAtTop, hasCodeAtBottom, hasSingleCode;
|
||||||
public boolean hasQuote, hasQuoteAtBottom, hasSingleQuote;
|
public boolean hasQuote, hasQuoteAtBottom, hasSingleQuote;
|
||||||
|
|
||||||
|
public int textHeight() {
|
||||||
|
int h = 0;
|
||||||
|
for (int i = 0; i < textLayoutBlocks.size(); ++i) {
|
||||||
|
h += textLayoutBlocks.get(i).padTop + textLayoutBlocks.get(i).height() + textLayoutBlocks.get(i).padBottom;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int textHeight(ChatMessageCell.TransitionParams tp) {
|
||||||
|
int h = 0;
|
||||||
|
for (int i = 0; i < textLayoutBlocks.size(); ++i) {
|
||||||
|
h += textLayoutBlocks.get(i).padTop + textLayoutBlocks.get(i).height(tp) + textLayoutBlocks.get(i).padBottom;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bounceFrom(TextLayoutBlocks from) {
|
||||||
|
if (from == null) return;
|
||||||
|
for (int i = 0; i < Math.min(textLayoutBlocks.size(), from.textLayoutBlocks.size()); ++i) {
|
||||||
|
textLayoutBlocks.get(i).collapsedBounce = from.textLayoutBlocks.get(i).collapsedBounce;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public TextLayoutBlocks(MessageObject messageObject, @NonNull CharSequence text, TextPaint textPaint, int width) {
|
public TextLayoutBlocks(MessageObject messageObject, @NonNull CharSequence text, TextPaint textPaint, int width) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
textWidth = 0;
|
textWidth = 0;
|
||||||
|
@ -7086,7 +7252,6 @@ public class MessageObject {
|
||||||
width += AndroidUtilities.dp(15);
|
width += AndroidUtilities.dp(15);
|
||||||
}
|
}
|
||||||
|
|
||||||
textHeight = 0;
|
|
||||||
int linesCount = textLayout.getLineCount();
|
int linesCount = textLayout.getLineCount();
|
||||||
int linesPreBlock = LINES_PER_BLOCK;
|
int linesPreBlock = LINES_PER_BLOCK;
|
||||||
|
|
||||||
|
@ -7127,7 +7292,6 @@ public class MessageObject {
|
||||||
hasCodeAtBottom = false;
|
hasCodeAtBottom = false;
|
||||||
hasQuoteAtBottom = false;
|
hasQuoteAtBottom = false;
|
||||||
hasSingleQuote = false;
|
hasSingleQuote = false;
|
||||||
float offset = 0;
|
|
||||||
for (int a = 0; a < textRanges.size(); a++) {
|
for (int a = 0; a < textRanges.size(); a++) {
|
||||||
TextLayoutBlock block = new TextLayoutBlock();
|
TextLayoutBlock block = new TextLayoutBlock();
|
||||||
|
|
||||||
|
@ -7135,7 +7299,12 @@ public class MessageObject {
|
||||||
|
|
||||||
block.code = range.code;
|
block.code = range.code;
|
||||||
block.quote = range.quote;
|
block.quote = range.quote;
|
||||||
|
block.quoteCollapse = range.collapse;
|
||||||
|
if (block.quoteCollapse) {
|
||||||
|
block.messageObject = messageObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
block.index = a;
|
||||||
block.first = a == 0;
|
block.first = a == 0;
|
||||||
block.last = a == textRanges.size() - 1;
|
block.last = a == textRanges.size() - 1;
|
||||||
|
|
||||||
|
@ -7191,12 +7360,11 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
block.textLayout = textLayout;
|
block.textLayout = textLayout;
|
||||||
block.textYOffset = 0;
|
|
||||||
block.charactersOffset = 0;
|
block.charactersOffset = 0;
|
||||||
block.charactersEnd = textLayout.getText().length();
|
block.charactersEnd = textLayout.getText().length();
|
||||||
|
|
||||||
block.height = textLayout.getHeight();
|
block.height = textLayout.getHeight();
|
||||||
textHeight = block.padTop + block.height + block.padBottom;
|
block.collapsedHeight = (int) Math.min(textPaint.getTextSize() * 1.4f * 3, block.height);
|
||||||
} else {
|
} else {
|
||||||
int startCharacter = range.start;
|
int startCharacter = range.start;
|
||||||
int endCharacter = range.end;
|
int endCharacter = range.end;
|
||||||
|
@ -7214,13 +7382,8 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
block.textLayout = makeStaticLayout(sb, layoutPaint, blockMaxWidth, 1f, 0f, false);
|
block.textLayout = makeStaticLayout(sb, layoutPaint, blockMaxWidth, 1f, 0f, false);
|
||||||
|
|
||||||
block.textYOffset = offset;
|
block.height = block.textLayout.getHeight();
|
||||||
if (a != 0) {
|
block.collapsedHeight = (int) Math.min(textPaint.getTextSize() * 1.4f * 3, block.height);
|
||||||
block.height = (int) (block.textYOffset - prevOffset);
|
|
||||||
}
|
|
||||||
block.height = block.textLayout.getHeight(); // Math.max(block.height, block.textLayout.getLineBottom(block.textLayout.getLineCount() - 1));
|
|
||||||
textHeight += block.padTop + block.height + block.padBottom;
|
|
||||||
prevOffset = block.textYOffset;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
continue;
|
continue;
|
||||||
|
@ -7231,8 +7394,6 @@ public class MessageObject {
|
||||||
CodeHighlighting.highlight((Spannable) block.textLayout.getText(), 0, block.textLayout.getText().length(), range.language, 0, null, true);
|
CodeHighlighting.highlight((Spannable) block.textLayout.getText(), 0, block.textLayout.getText().length(), range.language, 0, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += block.padTop + block.height + block.padBottom;
|
|
||||||
|
|
||||||
textLayoutBlocks.add(block);
|
textLayoutBlocks.add(block);
|
||||||
|
|
||||||
final int currentBlockLinesCount = block.textLayout.getLineCount();
|
final int currentBlockLinesCount = block.textLayout.getLineCount();
|
||||||
|
@ -7417,6 +7578,9 @@ public class MessageObject {
|
||||||
if (forceAvatar || customAvatarDrawable != null) {
|
if (forceAvatar || customAvatarDrawable != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (searchType != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return !isSponsored() && (isFromUser() || isFromGroup() || eventId != 0 || messageOwner.fwd_from != null && messageOwner.fwd_from.saved_from_peer != null);
|
return !isSponsored() && (isFromUser() || isFromGroup() || eventId != 0 || messageOwner.fwd_from != null && messageOwner.fwd_from.saved_from_peer != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7430,6 +7594,9 @@ public class MessageObject {
|
||||||
if (forceAvatar || customAvatarDrawable != null) {
|
if (forceAvatar || customAvatarDrawable != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (searchType != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return !isSponsored() && (isFromChat() && isFromUser() || isFromGroup() || eventId != 0 || messageOwner.fwd_from != null && messageOwner.fwd_from.saved_from_peer != null);
|
return !isSponsored() && (isFromChat() && isFromUser() || isFromGroup() || eventId != 0 || messageOwner.fwd_from != null && messageOwner.fwd_from.saved_from_peer != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7585,6 +7752,26 @@ public class MessageObject {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TLObject getPeerObject() {
|
||||||
|
if (messageOwner != null) {
|
||||||
|
if (messageOwner.peer_id instanceof TLRPC.TL_peerChannel_layer131 ||
|
||||||
|
messageOwner.peer_id instanceof TLRPC.TL_peerChannel) {
|
||||||
|
return MessagesController.getInstance(currentAccount).getChat(messageOwner.peer_id.channel_id);
|
||||||
|
} else if (
|
||||||
|
messageOwner.peer_id instanceof TLRPC.TL_peerUser_layer131 ||
|
||||||
|
messageOwner.peer_id instanceof TLRPC.TL_peerUser
|
||||||
|
) {
|
||||||
|
return MessagesController.getInstance(currentAccount).getUser(messageOwner.peer_id.user_id);
|
||||||
|
} else if (
|
||||||
|
messageOwner.peer_id instanceof TLRPC.TL_peerChat_layer131 ||
|
||||||
|
messageOwner.peer_id instanceof TLRPC.TL_peerChat
|
||||||
|
) {
|
||||||
|
return MessagesController.getInstance(currentAccount).getChat(messageOwner.peer_id.chat_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static String getPeerObjectName(TLObject object) {
|
public static String getPeerObjectName(TLObject object) {
|
||||||
if (object instanceof TLRPC.User) {
|
if (object instanceof TLRPC.User) {
|
||||||
return UserObject.getUserName((TLRPC.User) object);
|
return UserObject.getUserName((TLRPC.User) object);
|
||||||
|
@ -8460,7 +8647,7 @@ public class MessageObject {
|
||||||
|
|
||||||
public int getApproximateHeight() {
|
public int getApproximateHeight() {
|
||||||
if (type == TYPE_TEXT) {
|
if (type == TYPE_TEXT) {
|
||||||
int height = textHeight + (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage ? dp(100) : 0);
|
int height = textHeight() + (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage ? dp(100) : 0);
|
||||||
if (isReply()) {
|
if (isReply()) {
|
||||||
height += dp(42);
|
height += dp(42);
|
||||||
}
|
}
|
||||||
|
@ -8484,7 +8671,7 @@ public class MessageObject {
|
||||||
} else if (type == TYPE_ROUND_VIDEO) {
|
} else if (type == TYPE_ROUND_VIDEO) {
|
||||||
return AndroidUtilities.roundMessageSize;
|
return AndroidUtilities.roundMessageSize;
|
||||||
} else if (type == TYPE_EMOJIS) {
|
} else if (type == TYPE_EMOJIS) {
|
||||||
return textHeight + dp(30);
|
return textHeight() + dp(30);
|
||||||
} else if (type == TYPE_STICKER || type == TYPE_ANIMATED_STICKER) {
|
} else if (type == TYPE_STICKER || type == TYPE_ANIMATED_STICKER) {
|
||||||
float maxHeight = AndroidUtilities.displaySize.y * 0.4f;
|
float maxHeight = AndroidUtilities.displaySize.y * 0.4f;
|
||||||
float maxWidth;
|
float maxWidth;
|
||||||
|
@ -9978,6 +10165,7 @@ public class MessageObject {
|
||||||
!"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2
|
!"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2
|
||||||
!"telegram_background".equals(webpageType) && // drawInstantViewType = 6
|
!"telegram_background".equals(webpageType) && // drawInstantViewType = 6
|
||||||
!"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9
|
!"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9
|
||||||
|
!"telegram_videochat".equals(webpageType) &&
|
||||||
!"telegram_livestream".equals(webpageType) && // drawInstantViewType = 11
|
!"telegram_livestream".equals(webpageType) && // drawInstantViewType = 11
|
||||||
!"telegram_user".equals(webpageType) && // drawInstantViewType = 13
|
!"telegram_user".equals(webpageType) && // drawInstantViewType = 13
|
||||||
!"telegram_story".equals(webpageType) && // drawInstantViewType = 17
|
!"telegram_story".equals(webpageType) && // drawInstantViewType = 17
|
||||||
|
@ -9995,7 +10183,7 @@ public class MessageObject {
|
||||||
"app".equals(webpageType) || "profile".equals(webpageType) ||
|
"app".equals(webpageType) || "profile".equals(webpageType) ||
|
||||||
"article".equals(webpageType) || "telegram_bot".equals(webpageType) ||
|
"article".equals(webpageType) || "telegram_bot".equals(webpageType) ||
|
||||||
"telegram_user".equals(webpageType) || "telegram_channel".equals(webpageType) ||
|
"telegram_user".equals(webpageType) || "telegram_channel".equals(webpageType) ||
|
||||||
"telegram_megagroup".equals(webpageType) || "telegram_voicechat".equals(webpageType) ||
|
"telegram_megagroup".equals(webpageType) || "telegram_voicechat".equals(webpageType) || "telegram_videochat".equals(webpageType) ||
|
||||||
"telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType) || "telegram_group_boost".equals(webpageType) ||
|
"telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType) || "telegram_group_boost".equals(webpageType) ||
|
||||||
"telegram_chat".equals(webpageType)
|
"telegram_chat".equals(webpageType)
|
||||||
);
|
);
|
||||||
|
@ -10007,17 +10195,19 @@ public class MessageObject {
|
||||||
|
|
||||||
public boolean quote;
|
public boolean quote;
|
||||||
public boolean code;
|
public boolean code;
|
||||||
|
public boolean collapse;
|
||||||
public String language;
|
public String language;
|
||||||
|
|
||||||
public TextRange(int start, int end) {
|
public TextRange(int start, int end) {
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
public TextRange(int start, int end, boolean quote, boolean code, String language) {
|
public TextRange(int start, int end, boolean quote, boolean code, boolean collapse, String language) {
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.quote = quote;
|
this.quote = quote;
|
||||||
this.code = code;
|
this.code = code;
|
||||||
|
this.collapse = quote && collapse;
|
||||||
this.language = language;
|
this.language = language;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10035,6 +10225,7 @@ public class MessageObject {
|
||||||
final int QUOTE_END = 2;
|
final int QUOTE_END = 2;
|
||||||
final int CODE_START = 4;
|
final int CODE_START = 4;
|
||||||
final int CODE_END = 8;
|
final int CODE_END = 8;
|
||||||
|
final int QUOTE_START_COLLAPSE = 16;
|
||||||
|
|
||||||
final TreeSet<Integer> cutIndexes = new TreeSet<>();
|
final TreeSet<Integer> cutIndexes = new TreeSet<>();
|
||||||
final HashMap<Integer, Integer> cutToType = new HashMap<>();
|
final HashMap<Integer, Integer> cutToType = new HashMap<>();
|
||||||
|
@ -10048,12 +10239,27 @@ public class MessageObject {
|
||||||
int end = spanned.getSpanEnd(quoteSpans[i]);
|
int end = spanned.getSpanEnd(quoteSpans[i]);
|
||||||
|
|
||||||
cutIndexes.add(start);
|
cutIndexes.add(start);
|
||||||
cutToType.put(start, (cutToType.containsKey(start) ? cutToType.get(start) : 0) | QUOTE_START);
|
cutToType.put(start, (cutToType.containsKey(start) ? cutToType.get(start) : 0) | (quoteSpans[i].span.isCollapsing ? QUOTE_START_COLLAPSE : QUOTE_START));
|
||||||
|
|
||||||
cutIndexes.add(end);
|
cutIndexes.add(end);
|
||||||
cutToType.put(end, (cutToType.containsKey(end) ? cutToType.get(end) : 0) | QUOTE_END);
|
cutToType.put(end, (cutToType.containsKey(end) ? cutToType.get(end) : 0) | QUOTE_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// join quotes: some clients cut their quotes when formatting is inside :|
|
||||||
|
final Iterator<Integer> I = cutIndexes.iterator();
|
||||||
|
while (I.hasNext()) {
|
||||||
|
final int index = I.next();
|
||||||
|
if (index < 0 || index >= spanned.length()) continue;
|
||||||
|
if (!cutToType.containsKey(index)) continue;
|
||||||
|
final int type = cutToType.get(index);
|
||||||
|
if ((type & QUOTE_START) != 0 && (type & QUOTE_END) != 0) {
|
||||||
|
if (spanned.charAt(index) == '\n') continue;
|
||||||
|
if (index - 1 > 0 && spanned.charAt(index - 1) == '\n') continue;
|
||||||
|
I.remove();
|
||||||
|
cutToType.remove(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int codeSpanIndex = 0;
|
int codeSpanIndex = 0;
|
||||||
CodeHighlighting.Span[] codeSpans = spanned.getSpans(0, spanned.length(), CodeHighlighting.Span.class);
|
CodeHighlighting.Span[] codeSpans = spanned.getSpans(0, spanned.length(), CodeHighlighting.Span.class);
|
||||||
for (int i = 0; i < codeSpans.length; ++i) {
|
for (int i = 0; i < codeSpans.length; ++i) {
|
||||||
|
@ -10068,6 +10274,7 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
int from = 0;
|
int from = 0;
|
||||||
|
boolean quoteCollapse = false;
|
||||||
int quoteCount = 0, codeCount = 0;
|
int quoteCount = 0, codeCount = 0;
|
||||||
for (Iterator<Integer> i = cutIndexes.iterator(); i.hasNext(); ) {
|
for (Iterator<Integer> i = cutIndexes.iterator(); i.hasNext(); ) {
|
||||||
int cutIndex = i.next();
|
int cutIndex = i.next();
|
||||||
|
@ -10084,7 +10291,7 @@ public class MessageObject {
|
||||||
codeSpanIndex++;
|
codeSpanIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ranges.add(new TextRange(from, cutIndex, quoteCount > 0, codeCount > 0, lng));
|
ranges.add(new TextRange(from, cutIndex, quoteCount > 0, codeCount > 0, quoteCollapse, lng));
|
||||||
from = cutIndex;
|
from = cutIndex;
|
||||||
if (from + 1 < text.length() && text.charAt(from) == '\n') {
|
if (from + 1 < text.length() && text.charAt(from) == '\n') {
|
||||||
from++;
|
from++;
|
||||||
|
@ -10092,12 +10299,15 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type & QUOTE_END) != 0) quoteCount--;
|
if ((type & QUOTE_END) != 0) quoteCount--;
|
||||||
if ((type & QUOTE_START) != 0) quoteCount++;
|
if ((type & QUOTE_START) != 0 || (type & QUOTE_START_COLLAPSE) != 0) {
|
||||||
|
quoteCount++;
|
||||||
|
quoteCollapse = (type & QUOTE_START_COLLAPSE) != 0;
|
||||||
|
}
|
||||||
if ((type & CODE_END) != 0) codeCount--;
|
if ((type & CODE_END) != 0) codeCount--;
|
||||||
if ((type & CODE_START) != 0) codeCount++;
|
if ((type & CODE_START) != 0) codeCount++;
|
||||||
}
|
}
|
||||||
if (from < text.length()) {
|
if (from < text.length()) {
|
||||||
ranges.add(new TextRange(from, text.length(), quoteCount > 0, codeCount > 0, null));
|
ranges.add(new TextRange(from, text.length(), quoteCount > 0, codeCount > 0, quoteCollapse, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10211,4 +10421,60 @@ public class MessageObject {
|
||||||
public boolean isQuickReply() {
|
public boolean isQuickReply() {
|
||||||
return isQuickReply(messageOwner);
|
return isQuickReply(messageOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TLRPC.TL_availableEffect getEffect() {
|
||||||
|
if (messageOwner == null || (messageOwner.flags2 & 4) == 0)
|
||||||
|
return null;
|
||||||
|
return MessagesController.getInstance(currentAccount).getEffect(messageOwner.effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getEffectId() {
|
||||||
|
if (messageOwner == null || (messageOwner.flags2 & 4) == 0)
|
||||||
|
return 0;
|
||||||
|
return messageOwner.effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TLRPC.TL_factCheck getFactCheck() {
|
||||||
|
return FactCheckController.getInstance(currentAccount).getFactCheck(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean factCheckExpanded;
|
||||||
|
|
||||||
|
private CharSequence factCheckText;
|
||||||
|
public CharSequence getFactCheckText() {
|
||||||
|
if (!isFactCheckable())
|
||||||
|
return null;
|
||||||
|
TLRPC.TL_factCheck factCheck = getFactCheck();
|
||||||
|
if (factCheck == null || factCheck.text == null)
|
||||||
|
return factCheckText = null;
|
||||||
|
// if (factCheckText == null) {
|
||||||
|
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(factCheck.text.text);
|
||||||
|
addEntitiesToText(stringBuilder, factCheck.text.entities, isOutOwner(), false, false, false);
|
||||||
|
factCheckText = stringBuilder;
|
||||||
|
// }
|
||||||
|
return factCheckText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFactCheckable() {
|
||||||
|
return getId() >= 0 && !isSponsored() && (
|
||||||
|
type == TYPE_TEXT ||
|
||||||
|
type == TYPE_VOICE ||
|
||||||
|
type == TYPE_PHOTO ||
|
||||||
|
type == TYPE_VIDEO ||
|
||||||
|
type == TYPE_GIF ||
|
||||||
|
type == TYPE_FILE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasEntitiesFromServer() {
|
||||||
|
if (messageOwner == null) return false;
|
||||||
|
if (messageOwner.entities == null) return false;
|
||||||
|
for (int i = 0; i < messageOwner.entities.size(); ++i) {
|
||||||
|
final TLRPC.MessageEntity e = messageOwner.entities.get(i);
|
||||||
|
if (e instanceof TLRPC.TL_messageEntityPhone || e instanceof TLRPC.TL_messageEntityBankCard)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ import android.os.SystemClock;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.util.SparseBooleanArray;
|
import android.util.SparseBooleanArray;
|
||||||
|
@ -72,20 +71,17 @@ import org.telegram.ui.Components.BulletinFactory;
|
||||||
import org.telegram.ui.Components.ImageUpdater;
|
import org.telegram.ui.Components.ImageUpdater;
|
||||||
import org.telegram.ui.Components.JoinCallAlert;
|
import org.telegram.ui.Components.JoinCallAlert;
|
||||||
import org.telegram.ui.Components.MotionBackgroundDrawable;
|
import org.telegram.ui.Components.MotionBackgroundDrawable;
|
||||||
import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet;
|
|
||||||
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
|
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
|
||||||
import org.telegram.ui.Components.Premium.boosts.BoostRepository;
|
|
||||||
import org.telegram.ui.Components.Premium.boosts.PremiumPreviewGiftToUsersBottomSheet;
|
|
||||||
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
|
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
|
||||||
import org.telegram.ui.Components.SwipeGestureSettingsView;
|
import org.telegram.ui.Components.SwipeGestureSettingsView;
|
||||||
import org.telegram.ui.Components.TranscribeButton;
|
import org.telegram.ui.Components.TranscribeButton;
|
||||||
import org.telegram.ui.DialogsActivity;
|
import org.telegram.ui.DialogsActivity;
|
||||||
import org.telegram.ui.EditWidgetActivity;
|
import org.telegram.ui.EditWidgetActivity;
|
||||||
import org.telegram.ui.LaunchActivity;
|
import org.telegram.ui.LaunchActivity;
|
||||||
import org.telegram.ui.NotificationsSettingsActivity;
|
|
||||||
import org.telegram.ui.PremiumPreviewFragment;
|
import org.telegram.ui.PremiumPreviewFragment;
|
||||||
import org.telegram.ui.ProfileActivity;
|
import org.telegram.ui.ProfileActivity;
|
||||||
import org.telegram.ui.SecretMediaViewer;
|
import org.telegram.ui.SecretMediaViewer;
|
||||||
|
import org.telegram.ui.Stars.StarsController;
|
||||||
import org.telegram.ui.Stories.StoriesController;
|
import org.telegram.ui.Stories.StoriesController;
|
||||||
import org.telegram.ui.TopicsFragment;
|
import org.telegram.ui.TopicsFragment;
|
||||||
|
|
||||||
|
@ -109,7 +105,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
public int lastKnownSessionsCount;
|
public int lastKnownSessionsCount;
|
||||||
private ConcurrentHashMap<Long, TLRPC.Chat> chats = new ConcurrentHashMap<>(100, 1.0f, 2);
|
private ConcurrentHashMap<Long, TLRPC.Chat> chats = new ConcurrentHashMap<>(100, 1.0f, 2);
|
||||||
private ConcurrentHashMap<Integer, TLRPC.EncryptedChat> encryptedChats = new ConcurrentHashMap<>(10, 1.0f, 2);
|
private ConcurrentHashMap<Integer, TLRPC.EncryptedChat> encryptedChats = new ConcurrentHashMap<>(10, 1.0f, 2);
|
||||||
private ConcurrentHashMap<Long, TLRPC.User> users = new ConcurrentHashMap<>(100, 1.0f, 2);
|
private ConcurrentHashMap<Long, TLRPC.User> users = new ConcurrentHashMap<>(100, 1.0f, 3);
|
||||||
private ConcurrentHashMap<String, TLObject> objectsByUsernames = new ConcurrentHashMap<>(100, 1.0f, 2);
|
private ConcurrentHashMap<String, TLObject> objectsByUsernames = new ConcurrentHashMap<>(100, 1.0f, 2);
|
||||||
public static int stableIdPointer = 100;
|
public static int stableIdPointer = 100;
|
||||||
|
|
||||||
|
@ -611,6 +607,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
public boolean androidDisableRoundCamera2;
|
public boolean androidDisableRoundCamera2;
|
||||||
public int storiesPinnedToTopCountMax;
|
public int storiesPinnedToTopCountMax;
|
||||||
public boolean showAnnualPerMonth = false;
|
public boolean showAnnualPerMonth = false;
|
||||||
|
public boolean canEditFactcheck;
|
||||||
|
public int factcheckLengthLimit;
|
||||||
|
|
||||||
public int savedDialogsPinnedLimitDefault;
|
public int savedDialogsPinnedLimitDefault;
|
||||||
public int savedDialogsPinnedLimitPremium;
|
public int savedDialogsPinnedLimitPremium;
|
||||||
|
@ -631,7 +629,11 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
public volatile boolean ignoreSetOnline;
|
public volatile boolean ignoreSetOnline;
|
||||||
public boolean premiumLocked;
|
public boolean premiumLocked;
|
||||||
public int transcribeButtonPressed;
|
public int transcribeButtonPressed;
|
||||||
|
public boolean starsLocked;
|
||||||
|
|
||||||
|
public boolean starsPurchaseAvailable() {
|
||||||
|
return !starsLocked;
|
||||||
|
}
|
||||||
public boolean premiumFeaturesBlocked() {
|
public boolean premiumFeaturesBlocked() {
|
||||||
return premiumLocked && !getUserConfig().isPremium();
|
return premiumLocked && !getUserConfig().isPremium();
|
||||||
}
|
}
|
||||||
|
@ -1462,6 +1464,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
premiumInvoiceSlug = mainPreferences.getString("premiumInvoiceSlug", null);
|
premiumInvoiceSlug = mainPreferences.getString("premiumInvoiceSlug", null);
|
||||||
premiumBotUsername = mainPreferences.getString("premiumBotUsername", null);
|
premiumBotUsername = mainPreferences.getString("premiumBotUsername", null);
|
||||||
premiumLocked = mainPreferences.getBoolean("premiumLocked", false);
|
premiumLocked = mainPreferences.getBoolean("premiumLocked", false);
|
||||||
|
starsLocked = mainPreferences.getBoolean("starsLocked", true);
|
||||||
transcribeButtonPressed = mainPreferences.getInt("transcribeButtonPressed", 0);
|
transcribeButtonPressed = mainPreferences.getInt("transcribeButtonPressed", 0);
|
||||||
forumUpgradeParticipantsMin = mainPreferences.getInt("forumUpgradeParticipantsMin", 200);
|
forumUpgradeParticipantsMin = mainPreferences.getInt("forumUpgradeParticipantsMin", 200);
|
||||||
topicsPinnedLimit = mainPreferences.getInt("topicsPinnedLimit", 3);
|
topicsPinnedLimit = mainPreferences.getInt("topicsPinnedLimit", 3);
|
||||||
|
@ -1544,6 +1547,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
androidDisableRoundCamera2 = mainPreferences.getBoolean("androidDisableRoundCamera2", false);
|
androidDisableRoundCamera2 = mainPreferences.getBoolean("androidDisableRoundCamera2", false);
|
||||||
storiesPinnedToTopCountMax = mainPreferences.getInt("storiesPinnedToTopCountMax", 3);
|
storiesPinnedToTopCountMax = mainPreferences.getInt("storiesPinnedToTopCountMax", 3);
|
||||||
showAnnualPerMonth = mainPreferences.getBoolean("showAnnualPerMonth", false);
|
showAnnualPerMonth = mainPreferences.getBoolean("showAnnualPerMonth", false);
|
||||||
|
canEditFactcheck = mainPreferences.getBoolean("canEditFactcheck", false);
|
||||||
|
factcheckLengthLimit = mainPreferences.getInt("factcheckLengthLimit", 1024);
|
||||||
scheduleTranscriptionUpdate();
|
scheduleTranscriptionUpdate();
|
||||||
BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID);
|
BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID);
|
||||||
if (mainPreferences.contains("dcDomainName2")) {
|
if (mainPreferences.contains("dcDomainName2")) {
|
||||||
|
@ -2535,6 +2540,16 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "stars_purchase_blocked": {
|
||||||
|
if (value.value instanceof TLRPC.TL_jsonBool) {
|
||||||
|
if (starsLocked != ((TLRPC.TL_jsonBool) value.value).value) {
|
||||||
|
starsLocked = ((TLRPC.TL_jsonBool) value.value).value;
|
||||||
|
editor.putBoolean("starsLocked", starsLocked);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "premium_bot_username": {
|
case "premium_bot_username": {
|
||||||
if (value.value instanceof TLRPC.TL_jsonString) {
|
if (value.value instanceof TLRPC.TL_jsonString) {
|
||||||
String string = ((TLRPC.TL_jsonString) value.value).value;
|
String string = ((TLRPC.TL_jsonString) value.value).value;
|
||||||
|
@ -4085,6 +4100,28 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "can_edit_factcheck": {
|
||||||
|
if (value.value instanceof TLRPC.TL_jsonBool) {
|
||||||
|
TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value;
|
||||||
|
if (bool.value != canEditFactcheck) {
|
||||||
|
canEditFactcheck = bool.value;
|
||||||
|
editor.putBoolean("canEditFactcheck", canEditFactcheck);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "factcheck_length_limit": {
|
||||||
|
if (value.value instanceof TLRPC.TL_jsonNumber) {
|
||||||
|
TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value;
|
||||||
|
if ((int) num.value != factcheckLengthLimit) {
|
||||||
|
factcheckLengthLimit = (int) num.value;
|
||||||
|
editor.putInt("factcheckLengthLimit", factcheckLengthLimit);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4617,7 +4654,10 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
collectDeviceStats = false;
|
collectDeviceStats = false;
|
||||||
smsjobsStickyNotificationEnabled = false;
|
smsjobsStickyNotificationEnabled = false;
|
||||||
showAnnualPerMonth = false;
|
showAnnualPerMonth = false;
|
||||||
mainPreferences.edit().remove("getfileExperimentalParams").remove("smsjobsStickyNotificationEnabled").remove("channelRevenueWithdrawalEnabled").remove("showAnnualPerMonth").apply();
|
canEditFactcheck = false;
|
||||||
|
starsLocked = true;
|
||||||
|
factcheckLengthLimit = 1024;
|
||||||
|
mainPreferences.edit().remove("starsLocked").remove("getfileExperimentalParams").remove("smsjobsStickyNotificationEnabled").remove("channelRevenueWithdrawalEnabled").remove("showAnnualPerMonth").remove("canEditFactcheck").remove("factcheckLengthLimit").apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean savePremiumFeaturesPreviewOrder(String key, SparseIntArray array, SharedPreferences.Editor editor, ArrayList<TLRPC.JSONValue> value) {
|
private boolean savePremiumFeaturesPreviewOrder(String key, SparseIntArray array, SharedPreferences.Editor editor, ArrayList<TLRPC.JSONValue> value) {
|
||||||
|
@ -5602,6 +5642,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
statusSettingState = 0;
|
statusSettingState = 0;
|
||||||
|
|
||||||
Utilities.stageQueue.postRunnable(() -> {
|
Utilities.stageQueue.postRunnable(() -> {
|
||||||
|
FileLog.d("cleanup: isUpdating = false");
|
||||||
getConnectionsManager().setIsUpdating(false);
|
getConnectionsManager().setIsUpdating(false);
|
||||||
updatesQueueChannels.clear();
|
updatesQueueChannels.clear();
|
||||||
updatesStartWaitTimeChannels.clear();
|
updatesStartWaitTimeChannels.clear();
|
||||||
|
@ -9704,7 +9745,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
Paint paint = Theme.dialogs_messageNamePaint;
|
Paint paint = Theme.dialogs_messageNamePaint;
|
||||||
if (paint == null) {
|
if (paint == null) {
|
||||||
paint = new Paint();
|
paint = new Paint();
|
||||||
paint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
paint.setTypeface(AndroidUtilities.bold());
|
||||||
paint.setTextSize(AndroidUtilities.dp(14));
|
paint.setTextSize(AndroidUtilities.dp(14));
|
||||||
}
|
}
|
||||||
text = Emoji.replaceEmoji(text, paint.getFontMetricsInt(), false);
|
text = Emoji.replaceEmoji(text, paint.getFontMetricsInt(), false);
|
||||||
|
@ -14793,6 +14834,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
FileLog.d("start getDifference with date = " + date + " pts = " + pts + " qts = " + qts);
|
FileLog.d("start getDifference with date = " + date + " pts = " + pts + " qts = " + qts);
|
||||||
|
FileLog.d("getDifference: isUpdating = true");
|
||||||
}
|
}
|
||||||
getConnectionsManager().setIsUpdating(true);
|
getConnectionsManager().setIsUpdating(true);
|
||||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||||
|
@ -14973,6 +15015,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
getMessagesStorage().setLastDateValue(res.state.date);
|
getMessagesStorage().setLastDateValue(res.state.date);
|
||||||
getMessagesStorage().setLastPtsValue(res.state.pts);
|
getMessagesStorage().setLastPtsValue(res.state.pts);
|
||||||
getMessagesStorage().setLastQtsValue(res.state.qts);
|
getMessagesStorage().setLastQtsValue(res.state.qts);
|
||||||
|
FileLog.d("received difference: isUpdating = false");
|
||||||
getConnectionsManager().setIsUpdating(false);
|
getConnectionsManager().setIsUpdating(false);
|
||||||
for (int a = 0; a < 3; a++) {
|
for (int a = 0; a < 3; a++) {
|
||||||
processUpdatesQueue(a, 1);
|
processUpdatesQueue(a, 1);
|
||||||
|
@ -14986,6 +15029,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
getMessagesStorage().setLastSeqValue(res.seq);
|
getMessagesStorage().setLastSeqValue(res.seq);
|
||||||
getMessagesStorage().setLastDateValue(res.date);
|
getMessagesStorage().setLastDateValue(res.date);
|
||||||
getConnectionsManager().setIsUpdating(false);
|
getConnectionsManager().setIsUpdating(false);
|
||||||
|
FileLog.d("received differenceEmpty: isUpdating = false");
|
||||||
for (int a = 0; a < 3; a++) {
|
for (int a = 0; a < 3; a++) {
|
||||||
processUpdatesQueue(a, 1);
|
processUpdatesQueue(a, 1);
|
||||||
}
|
}
|
||||||
|
@ -15000,6 +15044,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
gettingDifference = false;
|
gettingDifference = false;
|
||||||
getConnectionsManager().setIsUpdating(false);
|
getConnectionsManager().setIsUpdating(false);
|
||||||
|
FileLog.d("received: isUpdating = false");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -17683,7 +17728,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
msg.date = getConnectionsManager().getCurrentTime();
|
msg.date = getConnectionsManager().getCurrentTime();
|
||||||
TLRPC.User user = getMessagesController().getUser(msg.dialog_id);
|
TLRPC.User user = getMessagesController().getUser(msg.dialog_id);
|
||||||
if (user != null && getNotificationsSettings(currentAccount).getBoolean("EnableReactionsPreview", true)) {
|
if (user != null && getNotificationsSettings(currentAccount).getBoolean("EnableReactionsPreview", true)) {
|
||||||
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(update.reaction).flatten();
|
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(update.reaction).flatten();
|
||||||
if (reaction.emojicon != null) {
|
if (reaction.emojicon != null) {
|
||||||
msg.message = LocaleController.formatString(R.string.PushReactStory, UserObject.getFirstName(user), reaction.emojicon);
|
msg.message = LocaleController.formatString(R.string.PushReactStory, UserObject.getFirstName(user), reaction.emojicon);
|
||||||
} else {
|
} else {
|
||||||
|
@ -17703,10 +17748,14 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
getNotificationsController().processNewMessages(messageObjects, true, false, null);
|
getNotificationsController().processNewMessages(messageObjects, true, false, null);
|
||||||
} else if (baseUpdate instanceof TLRPC.TL_updateBroadcastRevenueTransactions) {
|
} else if (baseUpdate instanceof TLRPC.TL_updateBroadcastRevenueTransactions) {
|
||||||
TLRPC.TL_updateBroadcastRevenueTransactions update = (TLRPC.TL_updateBroadcastRevenueTransactions) baseUpdate;
|
TLRPC.TL_updateBroadcastRevenueTransactions update = (TLRPC.TL_updateBroadcastRevenueTransactions) baseUpdate;
|
||||||
if (ChannelMonetizationLayout.instance != null) {
|
if (ChannelMonetizationLayout.instance != null && ChannelMonetizationLayout.instance.dialogId == DialogObject.getPeerDialogId(update.peer)) {
|
||||||
ChannelMonetizationLayout.instance.setupBalances(update.balances);
|
ChannelMonetizationLayout.instance.setupBalances(update.balances);
|
||||||
ChannelMonetizationLayout.instance.reloadTransactions();
|
ChannelMonetizationLayout.instance.reloadTransactions();
|
||||||
}
|
}
|
||||||
|
} else if (baseUpdate instanceof TLRPC.TL_updateStarsBalance) {
|
||||||
|
TLRPC.TL_updateStarsBalance update = (TLRPC.TL_updateStarsBalance) baseUpdate;
|
||||||
|
StarsController.getInstance(currentAccount).updateBalance(update.balance);
|
||||||
|
StarsController.getInstance(currentAccount).invalidateTransactions(false);
|
||||||
} else if (baseUpdate instanceof TLRPC.TL_updateUser) {
|
} else if (baseUpdate instanceof TLRPC.TL_updateUser) {
|
||||||
TLRPC.TL_updateUser update = (TLRPC.TL_updateUser) baseUpdate;
|
TLRPC.TL_updateUser update = (TLRPC.TL_updateUser) baseUpdate;
|
||||||
TLRPC.User currentUser = getUser(update.user_id);
|
TLRPC.User currentUser = getUser(update.user_id);
|
||||||
|
@ -20704,7 +20753,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
long topic_id = MessageObject.getSavedDialogId(getUserConfig().getClientUserId(), message);
|
long topic_id = MessageObject.getSavedDialogId(getUserConfig().getClientUserId(), message);
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (int i = 0; i < message.reactions.results.size(); ++i) {
|
for (int i = 0; i < message.reactions.results.size(); ++i) {
|
||||||
if (updateSavedReactionTags(topic_id, ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(message.reactions.results.get(i).reaction), false, false)) {
|
if (updateSavedReactionTags(topic_id, ReactionsLayoutInBubble.VisibleReaction.fromTL(message.reactions.results.get(i).reaction), false, false)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21023,8 +21072,13 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean loadingPeerColors, loadingProfilePeerColors;
|
||||||
public void checkPeerColors(boolean force) {
|
public void checkPeerColors(boolean force) {
|
||||||
if (peerColors == null || peerColors.needUpdate() || force) {
|
if (getUserConfig().getCurrentUser() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!loadingPeerColors && (peerColors == null || peerColors.needUpdate() || force)) {
|
||||||
|
loadingPeerColors = true;
|
||||||
TLRPC.TL_help_getPeerColors req = new TLRPC.TL_help_getPeerColors();
|
TLRPC.TL_help_getPeerColors req = new TLRPC.TL_help_getPeerColors();
|
||||||
req.hash = peerColors != null ? peerColors.hash : 0;
|
req.hash = peerColors != null ? peerColors.hash : 0;
|
||||||
if (peerColors != null && peerColors.needUpdate()) {
|
if (peerColors != null && peerColors.needUpdate()) {
|
||||||
|
@ -21033,13 +21087,15 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
getConnectionsManager().sendRequest(req, (res, err) -> {
|
getConnectionsManager().sendRequest(req, (res, err) -> {
|
||||||
if (res instanceof TLRPC.TL_help_peerColors) {
|
if (res instanceof TLRPC.TL_help_peerColors) {
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
loadingPeerColors = false;
|
||||||
peerColors = PeerColors.fromTL(PeerColors.TYPE_NAME, (TLRPC.TL_help_peerColors) res);
|
peerColors = PeerColors.fromTL(PeerColors.TYPE_NAME, (TLRPC.TL_help_peerColors) res);
|
||||||
mainPreferences.edit().putString("peerColors", peerColors.toString()).apply();
|
mainPreferences.edit().putString("peerColors", peerColors.toString()).apply();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (profilePeerColors == null || profilePeerColors.needUpdate() || force) {
|
if (!loadingProfilePeerColors && (profilePeerColors == null || profilePeerColors.needUpdate() || force)) {
|
||||||
|
loadingProfilePeerColors = true;
|
||||||
TLRPC.TL_help_getPeerProfileColors req = new TLRPC.TL_help_getPeerProfileColors();
|
TLRPC.TL_help_getPeerProfileColors req = new TLRPC.TL_help_getPeerProfileColors();
|
||||||
req.hash = profilePeerColors != null ? profilePeerColors.hash : 0;
|
req.hash = profilePeerColors != null ? profilePeerColors.hash : 0;
|
||||||
if (profilePeerColors != null && profilePeerColors.needUpdate()) {
|
if (profilePeerColors != null && profilePeerColors.needUpdate()) {
|
||||||
|
@ -21048,6 +21104,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
getConnectionsManager().sendRequest(req, (res, err) -> {
|
getConnectionsManager().sendRequest(req, (res, err) -> {
|
||||||
if (res instanceof TLRPC.TL_help_peerColors) {
|
if (res instanceof TLRPC.TL_help_peerColors) {
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
loadingProfilePeerColors = false;
|
||||||
profilePeerColors = PeerColors.fromTL(PeerColors.TYPE_PROFILE, (TLRPC.TL_help_peerColors) res);
|
profilePeerColors = PeerColors.fromTL(PeerColors.TYPE_PROFILE, (TLRPC.TL_help_peerColors) res);
|
||||||
mainPreferences.edit().putString("profilePeerColors", profilePeerColors.toString()).apply();
|
mainPreferences.edit().putString("profilePeerColors", profilePeerColors.toString()).apply();
|
||||||
});
|
});
|
||||||
|
@ -21087,7 +21144,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
return isUserPremiumBlocked(userId, false);
|
return isUserPremiumBlocked(userId, false);
|
||||||
}
|
}
|
||||||
public boolean isUserPremiumBlocked(long userId, boolean cache) {
|
public boolean isUserPremiumBlocked(long userId, boolean cache) {
|
||||||
if (getUserConfig().isPremium()) {
|
if (getUserConfig().isPremium() || getUserConfig().getClientUserId() == userId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Boolean cached = cachedIsUserPremiumBlocked.get(userId);
|
Boolean cached = cachedIsUserPremiumBlocked.get(userId);
|
||||||
|
@ -21183,4 +21240,145 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
if (userFull == null) return false;
|
if (userFull == null) return false;
|
||||||
return !userFull.sponsored_enabled;
|
return !userFull.sponsored_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean loadingAvailableEffects;
|
||||||
|
private TLRPC.messages_AvailableEffects availableEffects;
|
||||||
|
public TLRPC.messages_AvailableEffects getAvailableEffects() {
|
||||||
|
if (!loadingAvailableEffects) {
|
||||||
|
loadingAvailableEffects = true;
|
||||||
|
effectsFetcher.fetch(currentAccount, 0, effects -> {
|
||||||
|
if (availableEffects != effects) {
|
||||||
|
availableEffects = effects;
|
||||||
|
if (availableEffects != null) {
|
||||||
|
AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).putDocuments(availableEffects.documents);
|
||||||
|
}
|
||||||
|
getNotificationCenter().postNotificationName(NotificationCenter.availableEffectsUpdate);
|
||||||
|
}
|
||||||
|
loadingAvailableEffects = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return availableEffects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAvailableEffects() {
|
||||||
|
return availableEffects != null && !availableEffects.effects.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TLRPC.TL_availableEffect getEffect(long id) {
|
||||||
|
getAvailableEffects();
|
||||||
|
if (availableEffects != null) {
|
||||||
|
for (int i = 0; i < availableEffects.effects.size(); ++i) {
|
||||||
|
if (availableEffects.effects.get(i).id == id)
|
||||||
|
return availableEffects.effects.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TLRPC.Document getEffectDocument(long documentId) {
|
||||||
|
if (availableEffects != null) {
|
||||||
|
for (int i = 0; i < availableEffects.documents.size(); ++i) {
|
||||||
|
if (availableEffects.documents.get(i).id == documentId)
|
||||||
|
return availableEffects.documents.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final CacheFetcher<Integer, TLRPC.messages_AvailableEffects> effectsFetcher = new CacheFetcher<Integer, TLRPC.messages_AvailableEffects>() {
|
||||||
|
@Override
|
||||||
|
protected void getRemote(int currentAccount, Integer arguments, long hash, Utilities.Callback4<Boolean, TLRPC.messages_AvailableEffects, Long, Boolean> onResult) {
|
||||||
|
TLRPC.TL_messages_getAvailableEffects req = new TLRPC.TL_messages_getAvailableEffects();
|
||||||
|
req.hash = (int) hash;
|
||||||
|
getConnectionsManager().sendRequest(req, (res, err) -> {
|
||||||
|
if (res instanceof TLRPC.TL_messages_availableEffectsNotModified) {
|
||||||
|
onResult.run(true, null, 0L, true);
|
||||||
|
} else if (res instanceof TLRPC.TL_messages_availableEffects) {
|
||||||
|
onResult.run(false, (TLRPC.TL_messages_availableEffects) res, (long) ((TLRPC.TL_messages_availableEffects) res).hash, true);
|
||||||
|
} else {
|
||||||
|
FileLog.e("getting available effects error " + (err != null ? err.code + " " + err.text : ""));
|
||||||
|
onResult.run(false, null, 0L, err == null || !(err.code == -2000 || err.code == -2001));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void getLocal(int currentAccount, Integer arguments, Utilities.Callback2<Long, TLRPC.messages_AvailableEffects> onResult) {
|
||||||
|
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||||
|
SQLiteCursor cursor = null;
|
||||||
|
try {
|
||||||
|
SQLiteDatabase database = MessagesStorage.getInstance(currentAccount).getDatabase();
|
||||||
|
if (database != null) {
|
||||||
|
TLRPC.messages_AvailableEffects maybeResult = null;
|
||||||
|
cursor = database.queryFinalized("SELECT data FROM effects");
|
||||||
|
if (cursor.next()) {
|
||||||
|
NativeByteBuffer data = cursor.byteBufferValue(0);
|
||||||
|
if (data != null) {
|
||||||
|
maybeResult = TLRPC.messages_AvailableEffects.TLdeserialize(data, data.readInt32(false), true);
|
||||||
|
data.reuse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maybeResult instanceof TLRPC.TL_messages_availableEffects) {
|
||||||
|
TLRPC.TL_messages_availableEffects result = (TLRPC.TL_messages_availableEffects) maybeResult;
|
||||||
|
onResult.run((long) result.hash, result);
|
||||||
|
} else {
|
||||||
|
onResult.run(0L, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
onResult.run(0L, null);
|
||||||
|
} finally {
|
||||||
|
if (cursor != null) {
|
||||||
|
cursor.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setLocal(int currentAccount, Integer arguments, TLRPC.messages_AvailableEffects data, long hash) {
|
||||||
|
MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> {
|
||||||
|
try {
|
||||||
|
SQLiteDatabase database = MessagesStorage.getInstance(currentAccount).getDatabase();
|
||||||
|
if (database != null) {
|
||||||
|
database.executeFast("DELETE FROM effects").stepThis().dispose();
|
||||||
|
if (data != null) {
|
||||||
|
SQLitePreparedStatement state = database.executeFast("INSERT INTO effects VALUES(?)");
|
||||||
|
state.requery();
|
||||||
|
NativeByteBuffer buffer = new NativeByteBuffer(data.getObjectSize());
|
||||||
|
data.serializeToStream(buffer);
|
||||||
|
state.bindByteBuffer(1, buffer);
|
||||||
|
state.step();
|
||||||
|
buffer.reuse();
|
||||||
|
state.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean saveLastTimeRequested() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected long getSavedLastTimeRequested(int hashCode) {
|
||||||
|
return mainPreferences.getLong("effects_last_" + hashCode, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setSavedLastTimeRequested(int hashCode, long time) {
|
||||||
|
mainPreferences.edit().putLong("effects_last_" + hashCode, time).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean emitLocal(Integer arguments) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class MessagesStorage extends BaseController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static int LAST_DB_VERSION = 153;
|
public final static int LAST_DB_VERSION = 155;
|
||||||
private boolean databaseMigrationInProgress;
|
private boolean databaseMigrationInProgress;
|
||||||
public boolean showClearDatabaseAlert;
|
public boolean showClearDatabaseAlert;
|
||||||
private LongSparseIntArray dialogIsForum = new LongSparseIntArray();
|
private LongSparseIntArray dialogIsForum = new LongSparseIntArray();
|
||||||
|
@ -694,6 +694,7 @@ public class MessagesStorage extends BaseController {
|
||||||
|
|
||||||
database.executeFast("CREATE TABLE emoji_groups(type INTEGER PRIMARY KEY, data BLOB)").stepThis().dispose();
|
database.executeFast("CREATE TABLE emoji_groups(type INTEGER PRIMARY KEY, data BLOB)").stepThis().dispose();
|
||||||
database.executeFast("CREATE TABLE app_config(data BLOB)").stepThis().dispose();
|
database.executeFast("CREATE TABLE app_config(data BLOB)").stepThis().dispose();
|
||||||
|
database.executeFast("CREATE TABLE effects(data BLOB)").stepThis().dispose();
|
||||||
|
|
||||||
database.executeFast("CREATE TABLE stories (dialog_id INTEGER, story_id INTEGER, data BLOB, custom_params BLOB, PRIMARY KEY (dialog_id, story_id));").stepThis().dispose();
|
database.executeFast("CREATE TABLE stories (dialog_id INTEGER, story_id INTEGER, data BLOB, custom_params BLOB, PRIMARY KEY (dialog_id, story_id));").stepThis().dispose();
|
||||||
database.executeFast("CREATE TABLE stories_counter (dialog_id INTEGER PRIMARY KEY, count INTEGER, max_read INTEGER);").stepThis().dispose();
|
database.executeFast("CREATE TABLE stories_counter (dialog_id INTEGER PRIMARY KEY, count INTEGER, max_read INTEGER);").stepThis().dispose();
|
||||||
|
@ -721,7 +722,7 @@ public class MessagesStorage extends BaseController {
|
||||||
database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_quick_replies_messages ON quick_replies_messages(reply_to_message_id, mid);").stepThis().dispose();
|
database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_quick_replies_messages ON quick_replies_messages(reply_to_message_id, mid);").stepThis().dispose();
|
||||||
|
|
||||||
database.executeFast("CREATE TABLE business_links(data BLOB, order_value INTEGER);").stepThis().dispose();
|
database.executeFast("CREATE TABLE business_links(data BLOB, order_value INTEGER);").stepThis().dispose();
|
||||||
|
database.executeFast("CREATE TABLE fact_checks(hash INTEGER PRIMARY KEY, data BLOB, expires INTEGER);").stepThis().dispose();
|
||||||
|
|
||||||
database.executeFast("PRAGMA user_version = " + MessagesStorage.LAST_DB_VERSION).stepThis().dispose();
|
database.executeFast("PRAGMA user_version = " + MessagesStorage.LAST_DB_VERSION).stepThis().dispose();
|
||||||
|
|
||||||
|
@ -1402,6 +1403,7 @@ public class MessagesStorage extends BaseController {
|
||||||
database.executeFast("DELETE FROM saved_reaction_tags").stepThis().dispose();
|
database.executeFast("DELETE FROM saved_reaction_tags").stepThis().dispose();
|
||||||
database.executeFast("DELETE FROM business_replies").stepThis().dispose();
|
database.executeFast("DELETE FROM business_replies").stepThis().dispose();
|
||||||
database.executeFast("DELETE FROM quick_replies_messages").stepThis().dispose();
|
database.executeFast("DELETE FROM quick_replies_messages").stepThis().dispose();
|
||||||
|
database.executeFast("DELETE FROM effects").stepThis().dispose();
|
||||||
|
|
||||||
|
|
||||||
cursor = database.queryFinalized("SELECT did FROM dialogs WHERE 1");
|
cursor = database.queryFinalized("SELECT did FROM dialogs WHERE 1");
|
||||||
|
@ -1833,7 +1835,7 @@ public class MessagesStorage extends BaseController {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
@ -2169,7 +2171,7 @@ public class MessagesStorage extends BaseController {
|
||||||
getEncryptedChatsInternal(TextUtils.join(",", encryptedChatIds), encryptedChats, usersToLoad);
|
getEncryptedChatsInternal(TextUtils.join(",", encryptedChatIds), encryptedChats, usersToLoad);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
|
@ -2544,7 +2546,7 @@ public class MessagesStorage extends BaseController {
|
||||||
getEncryptedChatsInternal(TextUtils.join(",", encryptedToLoad), encryptedChats, usersToLoad);
|
getEncryptedChatsInternal(TextUtils.join(",", encryptedToLoad), encryptedChats, usersToLoad);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
|
@ -2652,7 +2654,7 @@ public class MessagesStorage extends BaseController {
|
||||||
LongSparseArray<Boolean> mutedDialogs = new LongSparseArray<>();
|
LongSparseArray<Boolean> mutedDialogs = new LongSparseArray<>();
|
||||||
LongSparseArray<Boolean> archivedDialogs = new LongSparseArray<>();
|
LongSparseArray<Boolean> archivedDialogs = new LongSparseArray<>();
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users, true);
|
||||||
for (int a = 0, N = users.size(); a < N; a++) {
|
for (int a = 0, N = users.size(); a < N; a++) {
|
||||||
TLRPC.User user = users.get(a);
|
TLRPC.User user = users.get(a);
|
||||||
boolean muted = getMessagesController().isDialogMuted(user.id, 0);
|
boolean muted = getMessagesController().isDialogMuted(user.id, 0);
|
||||||
|
@ -2679,7 +2681,7 @@ public class MessagesStorage extends BaseController {
|
||||||
ArrayList<TLRPC.EncryptedChat> encryptedChats = new ArrayList<>();
|
ArrayList<TLRPC.EncryptedChat> encryptedChats = new ArrayList<>();
|
||||||
getEncryptedChatsInternal(TextUtils.join(",", encryptedToLoad), encryptedChats, encUsersToLoad);
|
getEncryptedChatsInternal(TextUtils.join(",", encryptedToLoad), encryptedChats, encUsersToLoad);
|
||||||
if (!encUsersToLoad.isEmpty()) {
|
if (!encUsersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", encUsersToLoad), encUsers);
|
getUsersInternal(encUsersToLoad, encUsers, true);
|
||||||
for (int a = 0, N = encUsers.size(); a < N; a++) {
|
for (int a = 0, N = encUsers.size(); a < N; a++) {
|
||||||
TLRPC.User user = encUsers.get(a);
|
TLRPC.User user = encUsers.get(a);
|
||||||
encUsersDict.put(user.id, user);
|
encUsersDict.put(user.id, user);
|
||||||
|
@ -3333,7 +3335,7 @@ public class MessagesStorage extends BaseController {
|
||||||
}
|
}
|
||||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
for (int a = 0, N = users.size(); a < N; a++) {
|
for (int a = 0, N = users.size(); a < N; a++) {
|
||||||
TLRPC.User user = users.get(a);
|
TLRPC.User user = users.get(a);
|
||||||
usersToLoadMap.remove(user.id);
|
usersToLoadMap.remove(user.id);
|
||||||
|
@ -3744,7 +3746,7 @@ public class MessagesStorage extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
|
@ -3809,7 +3811,7 @@ public class MessagesStorage extends BaseController {
|
||||||
cursor = null;
|
cursor = null;
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
|
@ -4761,7 +4763,7 @@ public class MessagesStorage extends BaseController {
|
||||||
// loadReplyMessages(replyMessageOwners, dialogReplyMessagesIds, usersToLoad, chatsToLoad, false);
|
// loadReplyMessages(replyMessageOwners, dialogReplyMessagesIds, usersToLoad, chatsToLoad, false);
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
|
@ -4891,7 +4893,7 @@ public class MessagesStorage extends BaseController {
|
||||||
|
|
||||||
if (a != null && a.results != null && a.reactions_as_tags) {
|
if (a != null && a.results != null && a.reactions_as_tags) {
|
||||||
for (int j = 0; j < a.results.size(); ++j) {
|
for (int j = 0; j < a.results.size(); ++j) {
|
||||||
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(a.results.get(j).reaction);
|
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(a.results.get(j).reaction);
|
||||||
if (reaction != null) {
|
if (reaction != null) {
|
||||||
oldTags.put(reaction.hash, reaction);
|
oldTags.put(reaction.hash, reaction);
|
||||||
}
|
}
|
||||||
|
@ -4899,7 +4901,7 @@ public class MessagesStorage extends BaseController {
|
||||||
}
|
}
|
||||||
if (b != null && b.results != null && b.reactions_as_tags) {
|
if (b != null && b.results != null && b.reactions_as_tags) {
|
||||||
for (int j = 0; j < b.results.size(); ++j) {
|
for (int j = 0; j < b.results.size(); ++j) {
|
||||||
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(b.results.get(j).reaction);
|
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(b.results.get(j).reaction);
|
||||||
if (reaction != null) {
|
if (reaction != null) {
|
||||||
newTags.put(reaction.hash, reaction);
|
newTags.put(reaction.hash, reaction);
|
||||||
}
|
}
|
||||||
|
@ -4943,13 +4945,13 @@ public class MessagesStorage extends BaseController {
|
||||||
LongSparseArray<ReactionsLayoutInBubble.VisibleReaction> newTags = new LongSparseArray<>();
|
LongSparseArray<ReactionsLayoutInBubble.VisibleReaction> newTags = new LongSparseArray<>();
|
||||||
if (a != null && a.results != null && a.reactions_as_tags) {
|
if (a != null && a.results != null && a.reactions_as_tags) {
|
||||||
for (int i = 0; i < a.results.size(); ++i) {
|
for (int i = 0; i < a.results.size(); ++i) {
|
||||||
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(a.results.get(i).reaction);
|
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(a.results.get(i).reaction);
|
||||||
oldTags.put(reaction.hash, reaction);
|
oldTags.put(reaction.hash, reaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (b != null && b.results != null && b.reactions_as_tags) {
|
if (b != null && b.results != null && b.reactions_as_tags) {
|
||||||
for (int i = 0; i < b.results.size(); ++i) {
|
for (int i = 0; i < b.results.size(); ++i) {
|
||||||
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(b.results.get(i).reaction);
|
ReactionsLayoutInBubble.VisibleReaction reaction = ReactionsLayoutInBubble.VisibleReaction.fromTL(b.results.get(i).reaction);
|
||||||
newTags.put(reaction.hash, reaction);
|
newTags.put(reaction.hash, reaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5663,7 +5665,7 @@ public class MessagesStorage extends BaseController {
|
||||||
LongSparseArray<Boolean> mutedDialogs = new LongSparseArray<>();
|
LongSparseArray<Boolean> mutedDialogs = new LongSparseArray<>();
|
||||||
LongSparseArray<Boolean> archivedDialogs = new LongSparseArray<>();
|
LongSparseArray<Boolean> archivedDialogs = new LongSparseArray<>();
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
for (int a = 0, N = users.size(); a < N; a++) {
|
for (int a = 0, N = users.size(); a < N; a++) {
|
||||||
TLRPC.User user = users.get(a);
|
TLRPC.User user = users.get(a);
|
||||||
boolean muted = getMessagesController().isDialogMuted(user.id, 0);
|
boolean muted = getMessagesController().isDialogMuted(user.id, 0);
|
||||||
|
@ -5691,7 +5693,7 @@ public class MessagesStorage extends BaseController {
|
||||||
ArrayList<TLRPC.EncryptedChat> encryptedChats = new ArrayList<>();
|
ArrayList<TLRPC.EncryptedChat> encryptedChats = new ArrayList<>();
|
||||||
getEncryptedChatsInternal(TextUtils.join(",", encryptedToLoad), encryptedChats, encUsersToLoad);
|
getEncryptedChatsInternal(TextUtils.join(",", encryptedToLoad), encryptedChats, encUsersToLoad);
|
||||||
if (!encUsersToLoad.isEmpty()) {
|
if (!encUsersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", encUsersToLoad), encUsers);
|
getUsersInternal(encUsersToLoad, encUsers);
|
||||||
for (int a = 0, N = encUsers.size(); a < N; a++) {
|
for (int a = 0, N = encUsers.size(); a < N; a++) {
|
||||||
TLRPC.User user = encUsers.get(a);
|
TLRPC.User user = encUsers.get(a);
|
||||||
encUsersDict.put(user.id, user);
|
encUsersDict.put(user.id, user);
|
||||||
|
@ -7405,17 +7407,11 @@ public class MessagesStorage extends BaseController {
|
||||||
cursor.dispose();
|
cursor.dispose();
|
||||||
cursor = null;
|
cursor = null;
|
||||||
|
|
||||||
|
ArrayList<Long> usersToLoad = new ArrayList<Long>();
|
||||||
if (info instanceof TLRPC.TL_chatFull) {
|
if (info instanceof TLRPC.TL_chatFull) {
|
||||||
StringBuilder usersToLoad = new StringBuilder();
|
|
||||||
for (int a = 0; a < info.participants.participants.size(); a++) {
|
for (int a = 0; a < info.participants.participants.size(); a++) {
|
||||||
TLRPC.ChatParticipant c = info.participants.participants.get(a);
|
TLRPC.ChatParticipant c = info.participants.participants.get(a);
|
||||||
if (usersToLoad.length() != 0) {
|
usersToLoad.add(c.user_id);
|
||||||
usersToLoad.append(",");
|
|
||||||
}
|
|
||||||
usersToLoad.append(c.user_id);
|
|
||||||
}
|
|
||||||
if (usersToLoad.length() != 0) {
|
|
||||||
getUsersInternal(usersToLoad.toString(), loadedUsers);
|
|
||||||
}
|
}
|
||||||
} else if (info instanceof TLRPC.TL_channelFull) {
|
} else if (info instanceof TLRPC.TL_channelFull) {
|
||||||
cursor = database.queryFinalized("SELECT us.data, us.status, cu.data, cu.date FROM channel_users_v2 as cu LEFT JOIN users as us ON us.uid = cu.uid WHERE cu.did = " + (-chatId) + " ORDER BY cu.date DESC");
|
cursor = database.queryFinalized("SELECT us.data, us.status, cu.data, cu.date FROM channel_users_v2 as cu LEFT JOIN users as us ON us.uid = cu.uid WHERE cu.did = " + (-chatId) + " ORDER BY cu.date DESC");
|
||||||
|
@ -7456,34 +7452,20 @@ public class MessagesStorage extends BaseController {
|
||||||
}
|
}
|
||||||
cursor.dispose();
|
cursor.dispose();
|
||||||
cursor = null;
|
cursor = null;
|
||||||
StringBuilder usersToLoad = new StringBuilder();
|
|
||||||
for (int a = 0; a < info.bot_info.size(); a++) {
|
for (int a = 0; a < info.bot_info.size(); a++) {
|
||||||
TLRPC.BotInfo botInfo = info.bot_info.get(a);
|
TLRPC.BotInfo botInfo = info.bot_info.get(a);
|
||||||
if (usersToLoad.length() != 0) {
|
usersToLoad.add(botInfo.user_id);
|
||||||
usersToLoad.append(",");
|
|
||||||
}
|
|
||||||
usersToLoad.append(botInfo.user_id);
|
|
||||||
}
|
|
||||||
if (usersToLoad.length() != 0) {
|
|
||||||
getUsersInternal(usersToLoad.toString(), loadedUsers);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (info != null && info.inviterId != 0) {
|
if (info != null && info.inviterId != 0) {
|
||||||
getUsersInternal("" + info.inviterId, loadedUsers);
|
usersToLoad.add(info.inviterId);
|
||||||
}
|
}
|
||||||
if (info != null && info.recent_requesters != null && !info.recent_requesters.isEmpty()) {
|
if (info != null && info.recent_requesters != null && !info.recent_requesters.isEmpty()) {
|
||||||
StringBuilder usersToLoad = new StringBuilder();
|
|
||||||
for (int i = 0; i < Math.min(3, info.recent_requesters.size()); ++i) {
|
for (int i = 0; i < Math.min(3, info.recent_requesters.size()); ++i) {
|
||||||
long uid = info.recent_requesters.get(info.recent_requesters.size() - 1 - i);
|
usersToLoad.add(info.recent_requesters.get(info.recent_requesters.size() - 1 - i));
|
||||||
if (i > 0) {
|
|
||||||
usersToLoad.append(',');
|
|
||||||
}
|
|
||||||
usersToLoad.append(uid);
|
|
||||||
}
|
|
||||||
if (usersToLoad.length() > 0) {
|
|
||||||
getUsersInternal(usersToLoad.toString(), loadedUsers);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
getUsersInternal(usersToLoad, loadedUsers);
|
||||||
|
|
||||||
cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT mid FROM chat_pinned_v2 WHERE uid = %d ORDER BY mid DESC", -chatId));
|
cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT mid FROM chat_pinned_v2 WHERE uid = %d ORDER BY mid DESC", -chatId));
|
||||||
while (cursor.next()) {
|
while (cursor.next()) {
|
||||||
|
@ -7956,23 +7938,20 @@ public class MessagesStorage extends BaseController {
|
||||||
SQLiteCursor cursor = null;
|
SQLiteCursor cursor = null;
|
||||||
try {
|
try {
|
||||||
cursor = database.queryFinalized("SELECT * FROM contacts WHERE 1");
|
cursor = database.queryFinalized("SELECT * FROM contacts WHERE 1");
|
||||||
StringBuilder uids = new StringBuilder();
|
ArrayList<Long> uids = new ArrayList<>();
|
||||||
while (cursor.next()) {
|
while (cursor.next()) {
|
||||||
long userId = cursor.intValue(0);
|
long userId = cursor.intValue(0);
|
||||||
TLRPC.TL_contact contact = new TLRPC.TL_contact();
|
TLRPC.TL_contact contact = new TLRPC.TL_contact();
|
||||||
contact.user_id = userId;
|
contact.user_id = userId;
|
||||||
contact.mutual = cursor.intValue(1) == 1;
|
contact.mutual = cursor.intValue(1) == 1;
|
||||||
if (uids.length() != 0) {
|
|
||||||
uids.append(",");
|
|
||||||
}
|
|
||||||
contacts.add(contact);
|
contacts.add(contact);
|
||||||
uids.append(contact.user_id);
|
uids.add(contact.user_id);
|
||||||
}
|
}
|
||||||
cursor.dispose();
|
cursor.dispose();
|
||||||
cursor = null;
|
cursor = null;
|
||||||
|
|
||||||
if (uids.length() != 0) {
|
if (!uids.isEmpty()) {
|
||||||
getUsersInternal(uids.toString(), users);
|
getUsersInternal(uids, users);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
contacts.clear();
|
contacts.clear();
|
||||||
|
@ -8161,7 +8140,7 @@ public class MessagesStorage extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
|
@ -9203,7 +9182,7 @@ public class MessagesStorage extends BaseController {
|
||||||
loadReplyMessages(replyMessageOwners, dialogReplyMessagesIds, usersToLoad, chatsToLoad, mode);
|
loadReplyMessages(replyMessageOwners, dialogReplyMessagesIds, usersToLoad, chatsToLoad, mode);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), res.users);
|
getUsersInternal(usersToLoad, res.users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), res.chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), res.chats);
|
||||||
|
@ -9478,7 +9457,7 @@ public class MessagesStorage extends BaseController {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -9600,7 +9579,7 @@ public class MessagesStorage extends BaseController {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
checkSQLException(e);
|
checkSQLException(e);
|
||||||
|
@ -9855,7 +9834,7 @@ public class MessagesStorage extends BaseController {
|
||||||
getEncryptedChatsInternal("" + chatId, encryptedChats, usersToLoad);
|
getEncryptedChatsInternal("" + chatId, encryptedChats, usersToLoad);
|
||||||
if (!encryptedChats.isEmpty() && !usersToLoad.isEmpty()) {
|
if (!encryptedChats.isEmpty() && !usersToLoad.isEmpty()) {
|
||||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
getUsersInternal(usersToLoad, users);
|
||||||
if (!users.isEmpty()) {
|
if (!users.isEmpty()) {
|
||||||
result.add(encryptedChats.get(0));
|
result.add(encryptedChats.get(0));
|
||||||
result.add(users.get(0));
|
result.add(users.get(0));
|
||||||
|
@ -10197,29 +10176,87 @@ public class MessagesStorage extends BaseController {
|
||||||
state.dispose();
|
state.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getUsersInternal(String usersToLoad, ArrayList<TLRPC.User> result) throws Exception {
|
public void getUsersInternal(ArrayList<Long> userIds, ArrayList<TLRPC.User> result) throws Exception {
|
||||||
if (usersToLoad == null || usersToLoad.length() == 0 || result == null) {
|
getUsersInternal(userIds, result, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getUsersInternal(ArrayList<Long> userIds, ArrayList<TLRPC.User> result, boolean putUnknown) throws Exception {
|
||||||
|
if (userIds == null || userIds.isEmpty() || result == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad));
|
if (userIds.size() > 50) {
|
||||||
while (cursor.next()) {
|
for (int i = 0; i < userIds.size(); ++i) {
|
||||||
try {
|
long userId = userIds.get(i);
|
||||||
NativeByteBuffer data = cursor.byteBufferValue(0);
|
TLRPC.User user = getMessagesController().getUser(userId);
|
||||||
if (data != null) {
|
if (user != null) {
|
||||||
TLRPC.User user = TLRPC.User.TLdeserialize(data, data.readInt32(false), false);
|
result.add(user);
|
||||||
data.reuse();
|
userIds.remove(i);
|
||||||
if (user != null) {
|
i--;
|
||||||
if (user.status != null) {
|
|
||||||
user.status.expires = cursor.intValue(1);
|
|
||||||
}
|
|
||||||
result.add(user);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
checkSQLException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor.dispose();
|
if (!userIds.isEmpty()) {
|
||||||
|
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", TextUtils.join(",", userIds)));
|
||||||
|
while (cursor.next()) {
|
||||||
|
try {
|
||||||
|
NativeByteBuffer data = cursor.byteBufferValue(0);
|
||||||
|
if (data != null) {
|
||||||
|
TLRPC.User user = TLRPC.User.TLdeserialize(data, data.readInt32(false), false);
|
||||||
|
data.reuse();
|
||||||
|
if (user != null) {
|
||||||
|
if (user.status != null) {
|
||||||
|
user.status.expires = cursor.intValue(1);
|
||||||
|
}
|
||||||
|
result.add(user);
|
||||||
|
if (userIds.size() > 50 && putUnknown) {
|
||||||
|
getMessagesController().putUser(user, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
checkSQLException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getUsersInternal(HashSet<Long> userIds, ArrayList<TLRPC.User> result) throws Exception {
|
||||||
|
if (userIds == null || userIds.isEmpty() || result == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (userIds.size() > 50) {
|
||||||
|
Iterator<Long> iterator = userIds.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Long userId = iterator.next();
|
||||||
|
TLRPC.User user = getMessagesController().getUser(userId);
|
||||||
|
if (user != null) {
|
||||||
|
result.add(user);
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!userIds.isEmpty()) {
|
||||||
|
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", TextUtils.join(",", userIds)));
|
||||||
|
while (cursor.next()) {
|
||||||
|
try {
|
||||||
|
NativeByteBuffer data = cursor.byteBufferValue(0);
|
||||||
|
if (data != null) {
|
||||||
|
TLRPC.User user = TLRPC.User.TLdeserialize(data, data.readInt32(false), false);
|
||||||
|
data.reuse();
|
||||||
|
if (user != null) {
|
||||||
|
if (user.status != null) {
|
||||||
|
user.status.expires = cursor.intValue(1);
|
||||||
|
}
|
||||||
|
result.add(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
checkSQLException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getChatsInternal(String chatsToLoad, ArrayList<TLRPC.Chat> result) throws Exception {
|
public void getChatsInternal(String chatsToLoad, ArrayList<TLRPC.Chat> result) throws Exception {
|
||||||
|
@ -12760,18 +12797,15 @@ public class MessagesStorage extends BaseController {
|
||||||
database.commitTransaction();
|
database.commitTransaction();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
StringBuilder ids = new StringBuilder();
|
ArrayList<Long> ids = new ArrayList<Long>();
|
||||||
LongSparseArray<TLRPC.User> usersDict = new LongSparseArray<>();
|
LongSparseArray<TLRPC.User> usersDict = new LongSparseArray<>();
|
||||||
for (int a = 0, N = users.size(); a < N; a++) {
|
for (int a = 0, N = users.size(); a < N; a++) {
|
||||||
TLRPC.User user = users.get(a);
|
TLRPC.User user = users.get(a);
|
||||||
if (ids.length() != 0) {
|
ids.add(user.id);
|
||||||
ids.append(",");
|
|
||||||
}
|
|
||||||
ids.append(user.id);
|
|
||||||
usersDict.put(user.id, user);
|
usersDict.put(user.id, user);
|
||||||
}
|
}
|
||||||
ArrayList<TLRPC.User> loadedUsers = new ArrayList<>();
|
ArrayList<TLRPC.User> loadedUsers = new ArrayList<>();
|
||||||
getUsersInternal(ids.toString(), loadedUsers);
|
getUsersInternal(ids, loadedUsers);
|
||||||
for (int a = 0, N = loadedUsers.size(); a < N; a++) {
|
for (int a = 0, N = loadedUsers.size(); a < N; a++) {
|
||||||
TLRPC.User user = loadedUsers.get(a);
|
TLRPC.User user = loadedUsers.get(a);
|
||||||
TLRPC.User updateUser = usersDict.get(user.id);
|
TLRPC.User updateUser = usersDict.get(user.id);
|
||||||
|
@ -13795,7 +13829,7 @@ public class MessagesStorage extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), dialogs.users);
|
getUsersInternal(usersToLoad, dialogs.users);
|
||||||
}
|
}
|
||||||
|
|
||||||
getMessagesController().getTopicsController().updateTopicsWithDeletedMessages(originalDialogId, messages);
|
getMessagesController().getTopicsController().updateTopicsWithDeletedMessages(originalDialogId, messages);
|
||||||
|
@ -15648,7 +15682,7 @@ public class MessagesStorage extends BaseController {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), dialogs.chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), dialogs.chats);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
getUsersInternal(TextUtils.join(",", usersToLoad), dialogs.users);
|
getUsersInternal(usersToLoad, dialogs.users);
|
||||||
}
|
}
|
||||||
ArrayList<TLRPC.UserFull> fullUsers = null;
|
ArrayList<TLRPC.UserFull> fullUsers = null;
|
||||||
if (!dialogUsers.isEmpty()) {
|
if (!dialogUsers.isEmpty()) {
|
||||||
|
@ -16489,7 +16523,9 @@ public class MessagesStorage extends BaseController {
|
||||||
TLRPC.User user = null;
|
TLRPC.User user = null;
|
||||||
try {
|
try {
|
||||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||||
getUsersInternal("" + userId, users);
|
ArrayList<Long> userIds = new ArrayList<>();
|
||||||
|
userIds.add(userId);
|
||||||
|
getUsersInternal(userIds, users);
|
||||||
if (!users.isEmpty()) {
|
if (!users.isEmpty()) {
|
||||||
user = users.get(0);
|
user = users.get(0);
|
||||||
}
|
}
|
||||||
|
@ -16502,7 +16538,7 @@ public class MessagesStorage extends BaseController {
|
||||||
public ArrayList<TLRPC.User> getUsers(ArrayList<Long> uids) {
|
public ArrayList<TLRPC.User> getUsers(ArrayList<Long> uids) {
|
||||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
getUsersInternal(TextUtils.join(",", uids), users);
|
getUsersInternal(uids, users);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
users.clear();
|
users.clear();
|
||||||
checkSQLException(e);
|
checkSQLException(e);
|
||||||
|
|
|
@ -221,7 +221,7 @@ public class MusicBrowserService extends MediaBrowserService implements Notifica
|
||||||
cursor.dispose();
|
cursor.dispose();
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
ArrayList<TLRPC.User> usersArrayList = new ArrayList<>();
|
ArrayList<TLRPC.User> usersArrayList = new ArrayList<>();
|
||||||
messagesStorage.getUsersInternal(TextUtils.join(",", usersToLoad), usersArrayList);
|
messagesStorage.getUsersInternal(usersToLoad, usersArrayList);
|
||||||
for (int a = 0; a < usersArrayList.size(); a++) {
|
for (int a = 0; a < usersArrayList.size(); a++) {
|
||||||
TLRPC.User user = usersArrayList.get(a);
|
TLRPC.User user = usersArrayList.get(a);
|
||||||
users.put(user.id, user);
|
users.put(user.id, user);
|
||||||
|
|
|
@ -643,7 +643,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No
|
||||||
|
|
||||||
private float getPlaybackSpeed(boolean isPlaying, MessageObject messageObject) {
|
private float getPlaybackSpeed(boolean isPlaying, MessageObject messageObject) {
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
if (messageObject.isVoice() || messageObject.isRoundVideo()) {
|
if (messageObject != null && (messageObject.isVoice() || messageObject.isRoundVideo())) {
|
||||||
return MediaController.getInstance().getPlaybackSpeed(false);
|
return MediaController.getInstance().getPlaybackSpeed(false);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -93,6 +93,7 @@ public class NotificationCenter {
|
||||||
public static final int pinnedInfoDidLoad = totalEvents++;
|
public static final int pinnedInfoDidLoad = totalEvents++;
|
||||||
public static final int botKeyboardDidLoad = totalEvents++;
|
public static final int botKeyboardDidLoad = totalEvents++;
|
||||||
public static final int chatSearchResultsAvailable = totalEvents++;
|
public static final int chatSearchResultsAvailable = totalEvents++;
|
||||||
|
public static final int hashtagSearchUpdated = totalEvents++;
|
||||||
public static final int chatSearchResultsLoading = totalEvents++;
|
public static final int chatSearchResultsLoading = totalEvents++;
|
||||||
public static final int musicDidLoad = totalEvents++;
|
public static final int musicDidLoad = totalEvents++;
|
||||||
public static final int moreMusicDidLoad = totalEvents++;
|
public static final int moreMusicDidLoad = totalEvents++;
|
||||||
|
@ -247,6 +248,11 @@ public class NotificationCenter {
|
||||||
public static final int timezonesUpdated = totalEvents++;
|
public static final int timezonesUpdated = totalEvents++;
|
||||||
public static final int customStickerCreated = totalEvents++;
|
public static final int customStickerCreated = totalEvents++;
|
||||||
public static final int premiumFloodWaitReceived = totalEvents++;
|
public static final int premiumFloodWaitReceived = totalEvents++;
|
||||||
|
public static final int availableEffectsUpdate = totalEvents++;
|
||||||
|
public static final int starOptionsLoaded = totalEvents++;
|
||||||
|
public static final int starBalanceUpdated = totalEvents++;
|
||||||
|
public static final int starTransactionsLoaded = totalEvents++;
|
||||||
|
public static final int factCheckLoaded = totalEvents++;
|
||||||
|
|
||||||
//global
|
//global
|
||||||
public static final int pushMessagesUpdated = totalEvents++;
|
public static final int pushMessagesUpdated = totalEvents++;
|
||||||
|
|
|
@ -3933,7 +3933,8 @@ public class NotificationsController extends BaseController {
|
||||||
chatName = UserObject.getUserName(user);
|
chatName = UserObject.getUserName(user);
|
||||||
}
|
}
|
||||||
boolean passcode = AndroidUtilities.needShowPasscode() || SharedConfig.isWaitingForPasscodeEnter;
|
boolean passcode = AndroidUtilities.needShowPasscode() || SharedConfig.isWaitingForPasscodeEnter;
|
||||||
if (DialogObject.isEncryptedDialog(dialog_id) || pushDialogs.size() > 1 || passcode) {
|
final boolean allowSummary = !"samsung".equalsIgnoreCase(Build.MANUFACTURER);
|
||||||
|
if (DialogObject.isEncryptedDialog(dialog_id) || allowSummary && pushDialogs.size() > 1 || passcode) {
|
||||||
if (passcode) {
|
if (passcode) {
|
||||||
if (chatId != 0) {
|
if (chatId != 0) {
|
||||||
name = LocaleController.getString("NotificationHiddenChatName", R.string.NotificationHiddenChatName);
|
name = LocaleController.getString("NotificationHiddenChatName", R.string.NotificationHiddenChatName);
|
||||||
|
@ -3952,29 +3953,33 @@ public class NotificationsController extends BaseController {
|
||||||
}
|
}
|
||||||
|
|
||||||
String detailText;
|
String detailText;
|
||||||
if (UserConfig.getActivatedAccountsCount() > 1) {
|
if (allowSummary) {
|
||||||
if (pushDialogs.size() == 1) {
|
if (UserConfig.getActivatedAccountsCount() > 1) {
|
||||||
detailText = UserObject.getFirstName(getUserConfig().getCurrentUser());
|
if (pushDialogs.size() == 1) {
|
||||||
|
detailText = UserObject.getFirstName(getUserConfig().getCurrentUser());
|
||||||
|
} else {
|
||||||
|
detailText = UserObject.getFirstName(getUserConfig().getCurrentUser()) + "・";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
detailText = UserObject.getFirstName(getUserConfig().getCurrentUser()) + "・";
|
detailText = "";
|
||||||
|
}
|
||||||
|
if (pushDialogs.size() != 1 || Build.VERSION.SDK_INT < 23) {
|
||||||
|
if (pushDialogs.size() == 1) {
|
||||||
|
detailText += LocaleController.formatPluralString("NewMessages", total_unread_count);
|
||||||
|
} else {
|
||||||
|
detailText += LocaleController.formatString("NotificationMessagesPeopleDisplayOrder", R.string.NotificationMessagesPeopleDisplayOrder, LocaleController.formatPluralString("NewMessages", total_unread_count), LocaleController.formatPluralString("FromChats", pushDialogs.size()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
detailText = "";
|
detailText = "";
|
||||||
}
|
}
|
||||||
if (pushDialogs.size() != 1 || Build.VERSION.SDK_INT < 23) {
|
|
||||||
if (pushDialogs.size() == 1) {
|
|
||||||
detailText += LocaleController.formatPluralString("NewMessages", total_unread_count);
|
|
||||||
} else {
|
|
||||||
detailText += LocaleController.formatString("NotificationMessagesPeopleDisplayOrder", R.string.NotificationMessagesPeopleDisplayOrder, LocaleController.formatPluralString("NewMessages", total_unread_count), LocaleController.formatPluralString("FromChats", pushDialogs.size()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ApplicationLoader.applicationContext);
|
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ApplicationLoader.applicationContext);
|
||||||
|
|
||||||
int silent = 2;
|
int silent = 2;
|
||||||
String lastMessage = null;
|
String lastMessage = null;
|
||||||
boolean hasNewMessages = false;
|
boolean hasNewMessages = false;
|
||||||
if (pushMessages.size() <= 1) {
|
if (pushMessages.size() <= 1 || !allowSummary) {
|
||||||
boolean[] text = new boolean[1];
|
boolean[] text = new boolean[1];
|
||||||
String message = lastMessage = getStringForMessage(lastMessageObject, false, text, null);
|
String message = lastMessage = getStringForMessage(lastMessageObject, false, text, null);
|
||||||
silent = isSilentMessage(lastMessageObject) ? 1 : 0;
|
silent = isSilentMessage(lastMessageObject) ? 1 : 0;
|
||||||
|
@ -3993,6 +3998,9 @@ public class NotificationsController extends BaseController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mBuilder.setContentText(message);
|
mBuilder.setContentText(message);
|
||||||
|
if (!allowSummary) {
|
||||||
|
detailText = message;
|
||||||
|
}
|
||||||
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
|
mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(message));
|
||||||
} else {
|
} else {
|
||||||
mBuilder.setContentText(detailText);
|
mBuilder.setContentText(detailText);
|
||||||
|
@ -5043,11 +5051,19 @@ public class NotificationsController extends BaseController {
|
||||||
Uri uriFinal = uri;
|
Uri uriFinal = uri;
|
||||||
ApplicationLoader.applicationContext.grantUriPermission("com.android.systemui", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
ApplicationLoader.applicationContext.grantUriPermission("com.android.systemui", uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
ApplicationLoader.applicationContext.revokeUriPermission(uriFinal, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
try {
|
||||||
if (blurredAttach != null) {
|
ApplicationLoader.applicationContext.revokeUriPermission(uriFinal, Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
blurredAttach.delete();
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
}, 20000);
|
try {
|
||||||
|
if (blurredAttach != null) {
|
||||||
|
blurredAttach.delete();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
}
|
||||||
|
}, 20_000);
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(messageObject.caption)) {
|
if (!TextUtils.isEmpty(messageObject.caption)) {
|
||||||
messagingStyle.addMessage(messageObject.caption, ((long) messageObject.messageOwner.date) * 1000, person);
|
messagingStyle.addMessage(messageObject.caption, ((long) messageObject.messageOwner.date) * 1000, person);
|
||||||
|
@ -5438,7 +5454,7 @@ public class NotificationsController extends BaseController {
|
||||||
|
|
||||||
if (textPaint == null) {
|
if (textPaint == null) {
|
||||||
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
textPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
textPaint.setTypeface(AndroidUtilities.bold());
|
||||||
textPaint.setTextSize(sz * .25f);
|
textPaint.setTextSize(sz * .25f);
|
||||||
textPaint.setColor(0xFFFFFFFF);
|
textPaint.setColor(0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
|
@ -811,7 +811,7 @@ public class SavedMessagesController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
messagesStorage.getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
messagesStorage.getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
messagesStorage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
messagesStorage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
|
@ -886,7 +886,7 @@ public class SavedMessagesController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
messagesStorage.getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
messagesStorage.getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
messagesStorage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
messagesStorage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
|
|
|
@ -960,7 +960,7 @@ public class SecretChatHelper extends BaseController {
|
||||||
}
|
}
|
||||||
newMessage.media.document.thumbs.add(photoSize);
|
newMessage.media.document.thumbs.add(photoSize);
|
||||||
newMessage.media.document.flags |= 1;
|
newMessage.media.document.flags |= 1;
|
||||||
TLRPC.TL_documentAttributeVideo attributeVideo = new TLRPC.TL_documentAttributeVideo();
|
TLRPC.TL_documentAttributeVideo_layer159 attributeVideo = new TLRPC.TL_documentAttributeVideo_layer159();
|
||||||
attributeVideo.w = decryptedMessage.media.w;
|
attributeVideo.w = decryptedMessage.media.w;
|
||||||
attributeVideo.h = decryptedMessage.media.h;
|
attributeVideo.h = decryptedMessage.media.h;
|
||||||
attributeVideo.duration = decryptedMessage.media.duration;
|
attributeVideo.duration = decryptedMessage.media.duration;
|
||||||
|
|
|
@ -66,6 +66,9 @@ import org.telegram.ui.ChatActivity;
|
||||||
import org.telegram.ui.Components.AlertsCreator;
|
import org.telegram.ui.Components.AlertsCreator;
|
||||||
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
||||||
import org.telegram.ui.Components.AnimatedFileDrawable;
|
import org.telegram.ui.Components.AnimatedFileDrawable;
|
||||||
|
import org.telegram.ui.LaunchActivity;
|
||||||
|
import org.telegram.ui.Stars.StarsController;
|
||||||
|
import org.telegram.ui.Stars.StarsIntroActivity;
|
||||||
import org.telegram.ui.bots.BotWebViewSheet;
|
import org.telegram.ui.bots.BotWebViewSheet;
|
||||||
import org.telegram.ui.Components.Bulletin;
|
import org.telegram.ui.Components.Bulletin;
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
|
@ -1672,7 +1675,22 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
newDocument.size = document.size;
|
newDocument.size = document.size;
|
||||||
newDocument.dc_id = document.dc_id;
|
newDocument.dc_id = document.dc_id;
|
||||||
newDocument.attributes = new ArrayList<>(document.attributes);
|
newDocument.attributes = new ArrayList<>();
|
||||||
|
for (int i = 0; i < document.attributes.size(); ++i) {
|
||||||
|
TLRPC.DocumentAttribute attr = document.attributes.get(i);
|
||||||
|
if (attr instanceof TLRPC.TL_documentAttributeVideo) {
|
||||||
|
TLRPC.TL_documentAttributeVideo_layer159 attr2 = new TLRPC.TL_documentAttributeVideo_layer159();
|
||||||
|
attr2.flags = attr.flags;
|
||||||
|
attr2.round_message = attr.round_message;
|
||||||
|
attr2.supports_streaming = attr.supports_streaming;
|
||||||
|
attr2.duration = attr.duration;
|
||||||
|
attr2.w = attr.w;
|
||||||
|
attr2.h = attr.h;
|
||||||
|
newDocument.attributes.add(attr2);
|
||||||
|
} else {
|
||||||
|
newDocument.attributes.add(attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (newDocument.mime_type == null) {
|
if (newDocument.mime_type == null) {
|
||||||
newDocument.mime_type = "";
|
newDocument.mime_type = "";
|
||||||
}
|
}
|
||||||
|
@ -1993,6 +2011,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
newMsg.media = msgObj.messageOwner.media;
|
newMsg.media = msgObj.messageOwner.media;
|
||||||
}
|
}
|
||||||
|
newMsg.invert_media = msgObj.messageOwner.invert_media;
|
||||||
if (newMsg.media != null) {
|
if (newMsg.media != null) {
|
||||||
newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_MEDIA;
|
newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_MEDIA;
|
||||||
}
|
}
|
||||||
|
@ -3154,12 +3173,20 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
AlertsCreator.showOpenUrlAlert(parentFragment, button.url, false, true);
|
AlertsCreator.showOpenUrlAlert(parentFragment, button.url, false, true);
|
||||||
}
|
}
|
||||||
} else if (button instanceof TLRPC.TL_keyboardButtonBuy) {
|
} else if (button instanceof TLRPC.TL_keyboardButtonBuy) {
|
||||||
if (response instanceof TLRPC.TL_payments_paymentForm) {
|
if (response instanceof TLRPC.TL_payments_paymentFormStars) {
|
||||||
final TLRPC.TL_payments_paymentForm form = (TLRPC.TL_payments_paymentForm) response;
|
TLRPC.InputInvoice inputInvoice = ((TLRPC.TL_payments_getPaymentForm) request[0]).invoice;
|
||||||
|
StarsController.getInstance(currentAccount).openPaymentForm(inputInvoice, (TLRPC.TL_payments_paymentFormStars) response, () -> {
|
||||||
|
waitingForCallback.remove(key);
|
||||||
|
finalKeys.remove(key);
|
||||||
|
}, status -> {});
|
||||||
|
} else if (response instanceof TLRPC.PaymentForm) {
|
||||||
|
final TLRPC.PaymentForm form = (TLRPC.PaymentForm) response;
|
||||||
getMessagesController().putUsers(form.users, false);
|
getMessagesController().putUsers(form.users, false);
|
||||||
parentFragment.presentFragment(new PaymentFormActivity(form, messageObject, parentFragment));
|
parentFragment.presentFragment(new PaymentFormActivity(form, messageObject, parentFragment));
|
||||||
} else if (response instanceof TLRPC.TL_payments_paymentReceipt) {
|
} else if (response instanceof TLRPC.TL_payments_paymentReceiptStars) {
|
||||||
parentFragment.presentFragment(new PaymentFormActivity((TLRPC.TL_payments_paymentReceipt) response));
|
StarsIntroActivity.showTransactionSheet(LaunchActivity.instance != null ? LaunchActivity.instance : ApplicationLoader.applicationContext, currentAccount, (TLRPC.TL_payments_paymentReceiptStars) response, null);
|
||||||
|
} else if (response instanceof TLRPC.PaymentReceipt) {
|
||||||
|
parentFragment.presentFragment(new PaymentFormActivity((TLRPC.PaymentReceipt) response));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TLRPC.TL_messages_botCallbackAnswer res = (TLRPC.TL_messages_botCallbackAnswer) response;
|
TLRPC.TL_messages_botCallbackAnswer res = (TLRPC.TL_messages_botCallbackAnswer) response;
|
||||||
|
@ -3333,11 +3360,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
req.theme_params.data = themeParams.toString();
|
req.theme_params.data = themeParams.toString();
|
||||||
req.flags |= 1;
|
req.flags |= 1;
|
||||||
}
|
}
|
||||||
|
request[0] = req;
|
||||||
getConnectionsManager().sendRequest(req, requestDelegate, ConnectionsManager.RequestFlagFailOnServerErrors);
|
getConnectionsManager().sendRequest(req, requestDelegate, ConnectionsManager.RequestFlagFailOnServerErrors);
|
||||||
} else {
|
} else {
|
||||||
TLRPC.TL_payments_getPaymentReceipt req = new TLRPC.TL_payments_getPaymentReceipt();
|
TLRPC.TL_payments_getPaymentReceipt req = new TLRPC.TL_payments_getPaymentReceipt();
|
||||||
req.msg_id = messageObject.messageOwner.media.receipt_msg_id;
|
req.msg_id = messageObject.messageOwner.media.receipt_msg_id;
|
||||||
req.peer = getMessagesController().getInputPeer(messageObject.messageOwner.peer_id);
|
req.peer = getMessagesController().getInputPeer(messageObject.messageOwner.peer_id);
|
||||||
|
request[0] = req;
|
||||||
getConnectionsManager().sendRequest(req, requestDelegate, ConnectionsManager.RequestFlagFailOnServerErrors);
|
getConnectionsManager().sendRequest(req, requestDelegate, ConnectionsManager.RequestFlagFailOnServerErrors);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -3866,6 +3895,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
newMsg.flags |= 1073741824;
|
newMsg.flags |= 1073741824;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sendMessageParams.effect_id != 0) {
|
||||||
|
newMsg.flags2 |= 4;
|
||||||
|
newMsg.effect = sendMessageParams.effect_id;
|
||||||
|
}
|
||||||
if (params != null && params.containsKey("bot")) {
|
if (params != null && params.containsKey("bot")) {
|
||||||
if (encryptedChat != null) {
|
if (encryptedChat != null) {
|
||||||
newMsg.via_bot_name = params.get("bot_name");
|
newMsg.via_bot_name = params.get("bot_name");
|
||||||
|
@ -4203,6 +4236,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
reqSend.flags |= 131072;
|
reqSend.flags |= 131072;
|
||||||
reqSend.quick_reply_shortcut = newMsg.quick_reply_shortcut;
|
reqSend.quick_reply_shortcut = newMsg.quick_reply_shortcut;
|
||||||
}
|
}
|
||||||
|
if (sendMessageParams.effect_id != 0) {
|
||||||
|
reqSend.flags |= 262144;
|
||||||
|
reqSend.effect = sendMessageParams.effect_id;
|
||||||
|
}
|
||||||
reqSend.invert_media = newMsg.invert_media;
|
reqSend.invert_media = newMsg.invert_media;
|
||||||
performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0);
|
performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0);
|
||||||
if (retryMessageObject == null) {
|
if (retryMessageObject == null) {
|
||||||
|
@ -4243,6 +4280,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
reqSend.schedule_date = scheduleDate;
|
reqSend.schedule_date = scheduleDate;
|
||||||
reqSend.flags |= 1024;
|
reqSend.flags |= 1024;
|
||||||
}
|
}
|
||||||
|
if (sendMessageParams.effect_id != 0) {
|
||||||
|
reqSend.flags |= 262144;
|
||||||
|
reqSend.effect = sendMessageParams.effect_id;
|
||||||
|
}
|
||||||
reqSend.invert_media = newMsg.invert_media;
|
reqSend.invert_media = newMsg.invert_media;
|
||||||
performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0);
|
performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0);
|
||||||
if (retryMessageObject == null) {
|
if (retryMessageObject == null) {
|
||||||
|
@ -4581,6 +4622,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
request.quick_reply_shortcut = newMsg.quick_reply_shortcut;
|
request.quick_reply_shortcut = newMsg.quick_reply_shortcut;
|
||||||
request.flags |= 131072;
|
request.flags |= 131072;
|
||||||
}
|
}
|
||||||
|
if (newMsg.effect != 0) {
|
||||||
|
request.flags |= 262144;
|
||||||
|
request.effect = newMsg.effect;
|
||||||
|
}
|
||||||
|
request.invert_media = sendMessageParams.invert_media;
|
||||||
delayedMessage.sendRequest = request;
|
delayedMessage.sendRequest = request;
|
||||||
}
|
}
|
||||||
delayedMessage.messageObjects.add(newMsgObj);
|
delayedMessage.messageObjects.add(newMsgObj);
|
||||||
|
@ -4637,6 +4683,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
request.flags |= 131072;
|
request.flags |= 131072;
|
||||||
request.quick_reply_shortcut = newMsg.quick_reply_shortcut;
|
request.quick_reply_shortcut = newMsg.quick_reply_shortcut;
|
||||||
}
|
}
|
||||||
|
if (sendMessageParams.effect_id != 0) {
|
||||||
|
request.flags |= 262144;
|
||||||
|
request.effect = sendMessageParams.effect_id;
|
||||||
|
}
|
||||||
|
request.invert_media = newMsg.invert_media;
|
||||||
|
|
||||||
if (delayedMessage != null) {
|
if (delayedMessage != null) {
|
||||||
delayedMessage.sendRequest = request;
|
delayedMessage.sendRequest = request;
|
||||||
|
@ -6738,7 +6789,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
private final static int ERROR_TYPE_UNSUPPORTED = 1;
|
private final static int ERROR_TYPE_UNSUPPORTED = 1;
|
||||||
private final static int ERROR_TYPE_FILE_TOO_LARGE = 2;
|
private final static int ERROR_TYPE_FILE_TOO_LARGE = 2;
|
||||||
|
|
||||||
private static int prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, final ArrayList<TLRPC.MessageEntity> entities, final MessageObject editingMessageObject, long[] groupId, boolean isGroupFinal, CharSequence caption, boolean notify, int scheduleDate, Integer[] docType, boolean forceDocument, String quickReplyShortcut, int quickReplyShortcutId) {
|
private static int prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, final ArrayList<TLRPC.MessageEntity> entities, final MessageObject editingMessageObject, long[] groupId, boolean isGroupFinal, CharSequence caption, boolean notify, int scheduleDate, Integer[] docType, boolean forceDocument, String quickReplyShortcut, int quickReplyShortcutId, long effectId, boolean invertMedia) {
|
||||||
if ((path == null || path.length() == 0) && uri == null) {
|
if ((path == null || path.length() == 0) && uri == null) {
|
||||||
return ERROR_TYPE_UNSUPPORTED;
|
return ERROR_TYPE_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
@ -7023,6 +7074,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
sendMessageParams.replyQuote = quote;
|
sendMessageParams.replyQuote = quote;
|
||||||
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
||||||
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
||||||
|
sendMessageParams.effect_id = effectId;
|
||||||
|
sendMessageParams.invert_media = invertMedia;
|
||||||
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -7054,7 +7107,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingDocument(AccountInstance accountInstance, String path, String originalPath, Uri uri, String caption, String mine, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, MessageObject editingMessageObject, boolean notify, int scheduleDate, InputContentInfoCompat inputContent, String quickReplyShortcut, int quickReplyShortcutId) {
|
public static void prepareSendingDocument(AccountInstance accountInstance, String path, String originalPath, Uri uri, String caption, String mine, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, MessageObject editingMessageObject, boolean notify, int scheduleDate, InputContentInfoCompat inputContent, String quickReplyShortcut, int quickReplyShortcutId, boolean invertMedia) {
|
||||||
if ((path == null || originalPath == null) && uri == null) {
|
if ((path == null || originalPath == null) && uri == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -7069,11 +7122,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
paths.add(path);
|
paths.add(path);
|
||||||
originalPaths.add(originalPath);
|
originalPaths.add(originalPath);
|
||||||
}
|
}
|
||||||
prepareSendingDocuments(accountInstance, paths, originalPaths, uris, caption, mine, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, editingMessageObject, notify, scheduleDate, inputContent, quickReplyShortcut, quickReplyShortcutId);
|
prepareSendingDocuments(accountInstance, paths, originalPaths, uris, caption, mine, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, editingMessageObject, notify, scheduleDate, inputContent, quickReplyShortcut, quickReplyShortcutId, 0, invertMedia);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingAudioDocuments(AccountInstance accountInstance, ArrayList<MessageObject> messageObjects, CharSequence caption, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, boolean notify, int scheduleDate, MessageObject editingMessageObject, String quickReplyShortcut, int quickReplyShortcutId) {
|
public static void prepareSendingAudioDocuments(AccountInstance accountInstance, ArrayList<MessageObject> messageObjects, CharSequence caption, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, boolean notify, int scheduleDate, MessageObject editingMessageObject, String quickReplyShortcut, int quickReplyShortcutId, long effectId, boolean invertMedia) {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
int count = messageObjects.size();
|
int count = messageObjects.size();
|
||||||
long groupId = 0;
|
long groupId = 0;
|
||||||
|
@ -7140,6 +7193,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
sendMessageParams.replyToStoryItem = storyItem;
|
sendMessageParams.replyToStoryItem = storyItem;
|
||||||
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
||||||
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
||||||
|
sendMessageParams.effect_id = effectId;
|
||||||
|
sendMessageParams.invert_media = invertMedia;
|
||||||
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -7168,7 +7223,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingDocuments(AccountInstance accountInstance, ArrayList<String> paths, ArrayList<String> originalPaths, ArrayList<Uri> uris, String caption, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, MessageObject editingMessageObject, boolean notify, int scheduleDate, InputContentInfoCompat inputContent, String quickReplyShortcut, int quickReplyShortcutId) {
|
public static void prepareSendingDocuments(AccountInstance accountInstance, ArrayList<String> paths, ArrayList<String> originalPaths, ArrayList<Uri> uris, String caption, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, MessageObject editingMessageObject, boolean notify, int scheduleDate, InputContentInfoCompat inputContent, String quickReplyShortcut, int quickReplyShortcutId, long effectId, boolean invertMedia) {
|
||||||
if (paths == null && originalPaths == null && uris == null || paths != null && originalPaths != null && paths.size() != originalPaths.size()) {
|
if (paths == null && originalPaths == null && uris == null || paths != null && originalPaths != null && paths.size() != originalPaths.size()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -7179,7 +7234,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
Integer[] docType = new Integer[1];
|
Integer[] docType = new Integer[1];
|
||||||
|
|
||||||
boolean isEncrypted = DialogObject.isEncryptedDialog(dialogId);
|
boolean isEncrypted = DialogObject.isEncryptedDialog(dialogId);
|
||||||
|
boolean first = true;
|
||||||
if (paths != null) {
|
if (paths != null) {
|
||||||
int count = paths.size();
|
int count = paths.size();
|
||||||
for (int a = 0; a < count; a++) {
|
for (int a = 0; a < count; a++) {
|
||||||
|
@ -7193,7 +7248,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
mediaCount++;
|
mediaCount++;
|
||||||
long prevGroupId = groupId[0];
|
long prevGroupId = groupId[0];
|
||||||
error = prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, captionFinal, notify, scheduleDate, docType, inputContent == null, quickReplyShortcut, quickReplyShortcutId);
|
error = prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, captionFinal, notify, scheduleDate, docType, inputContent == null, quickReplyShortcut, quickReplyShortcutId, first ? effectId : 0, invertMedia);
|
||||||
|
first = false;
|
||||||
if (prevGroupId != groupId[0] || groupId[0] == -1) {
|
if (prevGroupId != groupId[0] || groupId[0] == -1) {
|
||||||
mediaCount = 1;
|
mediaCount = 1;
|
||||||
}
|
}
|
||||||
|
@ -7214,7 +7270,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
mediaCount++;
|
mediaCount++;
|
||||||
long prevGroupId = groupId[0];
|
long prevGroupId = groupId[0];
|
||||||
error = prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, captionFinal, notify, scheduleDate, docType, inputContent == null, quickReplyShortcut, quickReplyShortcutId);
|
error = prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, captionFinal, notify, scheduleDate, docType, inputContent == null, quickReplyShortcut, quickReplyShortcutId, first ? effectId : 0, invertMedia);
|
||||||
|
first = false;
|
||||||
if (prevGroupId != groupId[0] || groupId[0] == -1) {
|
if (prevGroupId != groupId[0] || groupId[0] == -1) {
|
||||||
mediaCount = 1;
|
mediaCount = 1;
|
||||||
}
|
}
|
||||||
|
@ -7246,11 +7303,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, ChatActivity.ReplyQuote quote, CharSequence caption, ArrayList<TLRPC.MessageEntity> entities, ArrayList<TLRPC.InputDocument> stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate, int mode, String quickReplyShortcut, int quickReplyShortcutId) {
|
public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, ChatActivity.ReplyQuote quote, CharSequence caption, ArrayList<TLRPC.MessageEntity> entities, ArrayList<TLRPC.InputDocument> stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate, int mode, String quickReplyShortcut, int quickReplyShortcutId) {
|
||||||
prepareSendingPhoto(accountInstance, imageFilePath, null, imageUri, dialogId, replyToMsg, replyToTopMsg, null, null, entities, stickers, inputContent, ttl, editingMessageObject, null, notify, scheduleDate, mode, false, caption, quickReplyShortcut, quickReplyShortcutId);
|
prepareSendingPhoto(accountInstance, imageFilePath, null, imageUri, dialogId, replyToMsg, replyToTopMsg, null, null, entities, stickers, inputContent, ttl, editingMessageObject, null, notify, scheduleDate, mode, false, caption, quickReplyShortcut, quickReplyShortcutId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, String thumbFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, ArrayList<TLRPC.MessageEntity> entities, ArrayList<TLRPC.InputDocument> stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, int mode, boolean forceDocument, CharSequence caption, String quickReplyShortcut, int quickReplyShortcutId) {
|
public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, String thumbFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, ArrayList<TLRPC.MessageEntity> entities, ArrayList<TLRPC.InputDocument> stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, int mode, boolean forceDocument, CharSequence caption, String quickReplyShortcut, int quickReplyShortcutId, long effectId) {
|
||||||
SendingMediaInfo info = new SendingMediaInfo();
|
SendingMediaInfo info = new SendingMediaInfo();
|
||||||
info.path = imageFilePath;
|
info.path = imageFilePath;
|
||||||
info.thumbPath = thumbFilePath;
|
info.thumbPath = thumbFilePath;
|
||||||
|
@ -7266,7 +7323,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
info.videoEditedInfo = videoEditedInfo;
|
info.videoEditedInfo = videoEditedInfo;
|
||||||
ArrayList<SendingMediaInfo> infos = new ArrayList<>();
|
ArrayList<SendingMediaInfo> infos = new ArrayList<>();
|
||||||
infos.add(info);
|
infos.add(info);
|
||||||
prepareSendingMedia(accountInstance, infos, dialogId, replyToMsg, replyToTopMsg, null, quote, forceDocument, false, editingMessageObject, notify, scheduleDate, mode, false, inputContent, quickReplyShortcut, quickReplyShortcutId);
|
prepareSendingMedia(accountInstance, infos, dialogId, replyToMsg, replyToTopMsg, null, quote, forceDocument, false, editingMessageObject, notify, scheduleDate, mode, false, inputContent, quickReplyShortcut, quickReplyShortcutId, effectId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
|
@ -7517,6 +7574,22 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
final Bitmap[] precahcedThumb = new Bitmap[1];
|
final Bitmap[] precahcedThumb = new Bitmap[1];
|
||||||
final String[] precachedKey = new String[1];
|
final String[] precachedKey = new String[1];
|
||||||
|
|
||||||
|
if (isEncrypted && document != null) {
|
||||||
|
for (int i = 0; i < document.attributes.size(); ++i) {
|
||||||
|
if (document.attributes.get(i) instanceof TLRPC.TL_documentAttributeVideo) {
|
||||||
|
TLRPC.TL_documentAttributeVideo attr = (TLRPC.TL_documentAttributeVideo) document.attributes.get(i);
|
||||||
|
TLRPC.TL_documentAttributeVideo_layer159 attr2 = new TLRPC.TL_documentAttributeVideo_layer159();
|
||||||
|
attr2.flags = attr.flags;
|
||||||
|
attr2.round_message = attr.round_message;
|
||||||
|
attr2.supports_streaming = attr.supports_streaming;
|
||||||
|
attr2.duration = attr.duration;
|
||||||
|
attr2.w = attr.w;
|
||||||
|
attr2.h = attr.h;
|
||||||
|
document.attributes.set(i, attr2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (MessageObject.isGifDocument(document)) {
|
if (MessageObject.isGifDocument(document)) {
|
||||||
TLRPC.PhotoSize photoSizeThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 320);
|
TLRPC.PhotoSize photoSizeThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 320);
|
||||||
File gifFile = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(document);
|
File gifFile = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(document);
|
||||||
|
@ -7668,12 +7741,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingText(AccountInstance accountInstance, String text, long dialogId, boolean notify, int scheduleDate) {
|
public static void prepareSendingText(AccountInstance accountInstance, String text, long dialogId, boolean notify, int scheduleDate, long effectId) {
|
||||||
prepareSendingText(accountInstance, text, dialogId, 0, notify, scheduleDate);
|
prepareSendingText(accountInstance, text, dialogId, 0, notify, scheduleDate, effectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingText(AccountInstance accountInstance, String text, long dialogId, long topicId, boolean notify, int scheduleDate) {
|
public static void prepareSendingText(AccountInstance accountInstance, String text, long dialogId, long topicId, boolean notify, int scheduleDate, long effectId) {
|
||||||
accountInstance.getMessagesStorage().getStorageQueue().postRunnable(() -> Utilities.stageQueue.postRunnable(() -> AndroidUtilities.runOnUIThread(() -> {
|
accountInstance.getMessagesStorage().getStorageQueue().postRunnable(() -> Utilities.stageQueue.postRunnable(() -> AndroidUtilities.runOnUIThread(() -> {
|
||||||
String textFinal = getTrimmedString(text);
|
String textFinal = getTrimmedString(text);
|
||||||
if (textFinal.length() != 0) {
|
if (textFinal.length() != 0) {
|
||||||
|
@ -7688,7 +7761,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
for (int a = 0; a < count; a++) {
|
for (int a = 0; a < count; a++) {
|
||||||
String mess = textFinal.substring(a * 4096, Math.min((a + 1) * 4096, textFinal.length()));
|
String mess = textFinal.substring(a * 4096, Math.min((a + 1) * 4096, textFinal.length()));
|
||||||
accountInstance.getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of(mess, dialogId, replyToMsg, replyToMsg, null, true, null, null, null, notify, scheduleDate, null, false));
|
SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(mess, dialogId, replyToMsg, replyToMsg, null, true, null, null, null, notify, scheduleDate, null, false);
|
||||||
|
if (a == 0) {
|
||||||
|
params.effect_id = effectId;
|
||||||
|
}
|
||||||
|
accountInstance.getSendMessagesHelper().sendMessage(params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
@ -7821,7 +7898,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingMedia(AccountInstance accountInstance, ArrayList<SendingMediaInfo> media, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, boolean forceDocument, boolean groupMedia, MessageObject editingMessageObject, boolean notify, int scheduleDate, int mode, boolean updateStikcersOrder, InputContentInfoCompat inputContent, String quickReplyShortcut, int quickReplyShortcutId) {
|
public static void prepareSendingMedia(AccountInstance accountInstance, ArrayList<SendingMediaInfo> media, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, boolean forceDocument, boolean groupMedia, MessageObject editingMessageObject, boolean notify, int scheduleDate, int mode, boolean updateStikcersOrder, InputContentInfoCompat inputContent, String quickReplyShortcut, int quickReplyShortcutId, long effectId, boolean invertMedia) {
|
||||||
if (media.isEmpty()) {
|
if (media.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -7926,6 +8003,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
int mediaCount = 0;
|
int mediaCount = 0;
|
||||||
for (int a = 0; a < count; a++) {
|
for (int a = 0; a < count; a++) {
|
||||||
final SendingMediaInfo info = media.get(a);
|
final SendingMediaInfo info = media.get(a);
|
||||||
|
final boolean last = mediaCount == 0;
|
||||||
if (groupMediaFinal && count > 1 && mediaCount % 10 == 0) {
|
if (groupMediaFinal && count > 1 && mediaCount % 10 == 0) {
|
||||||
lastGroupId = groupId = Utilities.random.nextLong();
|
lastGroupId = groupId = Utilities.random.nextLong();
|
||||||
mediaCount = 0;
|
mediaCount = 0;
|
||||||
|
@ -8030,6 +8108,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
sendMessageParams.replyQuote = quote;
|
sendMessageParams.replyQuote = quote;
|
||||||
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
||||||
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
||||||
|
if (last) {
|
||||||
|
sendMessageParams.effect_id = effectId;
|
||||||
|
}
|
||||||
|
sendMessageParams.invert_media = invertMedia;
|
||||||
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -8106,6 +8188,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
sendMessageParams.replyQuote = quote;
|
sendMessageParams.replyQuote = quote;
|
||||||
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
||||||
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
||||||
|
sendMessageParams.effect_id = effectId;
|
||||||
|
sendMessageParams.invert_media = invertMedia;
|
||||||
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -8301,6 +8385,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
sendMessageParams.replyQuote = quote;
|
sendMessageParams.replyQuote = quote;
|
||||||
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
||||||
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
||||||
|
sendMessageParams.effect_id = effectId;
|
||||||
|
sendMessageParams.invert_media = invertMedia;
|
||||||
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -8503,6 +8589,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
sendMessageParams.replyQuote = quote;
|
sendMessageParams.replyQuote = quote;
|
||||||
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
||||||
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
||||||
|
sendMessageParams.effect_id = effectId;
|
||||||
|
sendMessageParams.invert_media = invertMedia;
|
||||||
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -8539,7 +8627,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
mediaCount = 0;
|
mediaCount = 0;
|
||||||
}
|
}
|
||||||
mediaCount++;
|
mediaCount++;
|
||||||
int error = prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), sendAsDocumentsUri.get(a), extension, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, sendAsDocumentsEntities.get(a), editingMessageObject, groupId2, mediaCount == 10 || a == documentsCount - 1, sendAsDocumentsCaptions.get(a), notify, scheduleDate, null, forceDocument, quickReplyShortcut, quickReplyShortcutId);
|
int error = prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), sendAsDocumentsUri.get(a), extension, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, sendAsDocumentsEntities.get(a), editingMessageObject, groupId2, mediaCount == 10 || a == documentsCount - 1, sendAsDocumentsCaptions.get(a), notify, scheduleDate, null, forceDocument, quickReplyShortcut, quickReplyShortcutId, effectId, invertMedia);
|
||||||
handleError(error, accountInstance);
|
handleError(error, accountInstance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8804,7 +8892,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public static void prepareSendingVideo(AccountInstance accountInstance, String videoPath, VideoEditedInfo info, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, ArrayList<TLRPC.MessageEntity> entities, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate, boolean forceDocument, boolean hasMediaSpoilers, CharSequence caption, String quickReplyShortcut, int quickReplyShortcutId) {
|
public static void prepareSendingVideo(AccountInstance accountInstance, String videoPath, VideoEditedInfo info, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, ArrayList<TLRPC.MessageEntity> entities, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate, boolean forceDocument, boolean hasMediaSpoilers, CharSequence caption, String quickReplyShortcut, int quickReplyShortcutId, long effectId) {
|
||||||
if (videoPath == null || videoPath.length() == 0) {
|
if (videoPath == null || videoPath.length() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -8966,11 +9054,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
sendMessageParams.replyQuote = quote;
|
sendMessageParams.replyQuote = quote;
|
||||||
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
sendMessageParams.quick_reply_shortcut_id = quickReplyShortcutId;
|
||||||
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
sendMessageParams.quick_reply_shortcut = quickReplyShortcut;
|
||||||
|
sendMessageParams.effect_id = effectId;
|
||||||
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
prepareSendingDocumentInternal(accountInstance, videoPath, videoPath, null, null, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, entities, editingMessageObject, null, false, caption, notify, scheduleDate, null, forceDocument, quickReplyShortcut, quickReplyShortcutId);
|
prepareSendingDocumentInternal(accountInstance, videoPath, videoPath, null, null, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, entities, editingMessageObject, null, false, caption, notify, scheduleDate, null, forceDocument, quickReplyShortcut, quickReplyShortcutId, 0, false);
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
@ -9010,6 +9099,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
public boolean invert_media;
|
public boolean invert_media;
|
||||||
public String quick_reply_shortcut;
|
public String quick_reply_shortcut;
|
||||||
public int quick_reply_shortcut_id;
|
public int quick_reply_shortcut_id;
|
||||||
|
public long effect_id;
|
||||||
|
|
||||||
public static SendMessageParams of(String string, long dialogId) {
|
public static SendMessageParams of(String string, long dialogId) {
|
||||||
return of(string, null, null, null, null, null, null, null, null, null, dialogId, null, null, null, null, true, null, null, null, null, false, 0, 0, null, null, false);
|
return of(string, null, null, null, null, null, null, null, null, null, dialogId, null, null, null, null, true, null, null, null, null, false, 0, 0, null, null, false);
|
||||||
|
|
|
@ -232,7 +232,8 @@ public class SharedConfig {
|
||||||
public static boolean allowScreenCapture;
|
public static boolean allowScreenCapture;
|
||||||
public static int lastPauseTime;
|
public static int lastPauseTime;
|
||||||
public static boolean isWaitingForPasscodeEnter;
|
public static boolean isWaitingForPasscodeEnter;
|
||||||
public static boolean useFingerprint = true;
|
public static boolean useFingerprintLock = true;
|
||||||
|
public static boolean useFaceLock = true;
|
||||||
public static int suggestStickers;
|
public static int suggestStickers;
|
||||||
public static boolean suggestAnimatedEmoji;
|
public static boolean suggestAnimatedEmoji;
|
||||||
public static int keepMedia = CacheByChatsController.KEEP_MEDIA_ONE_MONTH; //deprecated
|
public static int keepMedia = CacheByChatsController.KEEP_MEDIA_ONE_MONTH; //deprecated
|
||||||
|
@ -255,6 +256,7 @@ public class SharedConfig {
|
||||||
public static boolean updateStickersOrderOnSend = true;
|
public static boolean updateStickersOrderOnSend = true;
|
||||||
public static boolean bigCameraForRound;
|
public static boolean bigCameraForRound;
|
||||||
public static Boolean useCamera2Force;
|
public static Boolean useCamera2Force;
|
||||||
|
public static boolean useNewBlur;
|
||||||
public static boolean useSurfaceInStories;
|
public static boolean useSurfaceInStories;
|
||||||
public static boolean photoViewerBlur = true;
|
public static boolean photoViewerBlur = true;
|
||||||
public static boolean payByInvoice;
|
public static boolean payByInvoice;
|
||||||
|
@ -430,7 +432,7 @@ public class SharedConfig {
|
||||||
editor.putInt("badPasscodeTries", badPasscodeTries);
|
editor.putInt("badPasscodeTries", badPasscodeTries);
|
||||||
editor.putInt("autoLockIn", autoLockIn);
|
editor.putInt("autoLockIn", autoLockIn);
|
||||||
editor.putInt("lastPauseTime", lastPauseTime);
|
editor.putInt("lastPauseTime", lastPauseTime);
|
||||||
editor.putBoolean("useFingerprint", useFingerprint);
|
editor.putBoolean("useFingerprint", useFingerprintLock);
|
||||||
editor.putBoolean("allowScreenCapture", allowScreenCapture);
|
editor.putBoolean("allowScreenCapture", allowScreenCapture);
|
||||||
editor.putString("pushString2", pushString);
|
editor.putString("pushString2", pushString);
|
||||||
editor.putInt("pushType", pushType);
|
editor.putInt("pushType", pushType);
|
||||||
|
@ -508,7 +510,7 @@ public class SharedConfig {
|
||||||
badPasscodeTries = preferences.getInt("badPasscodeTries", 0);
|
badPasscodeTries = preferences.getInt("badPasscodeTries", 0);
|
||||||
autoLockIn = preferences.getInt("autoLockIn", 60 * 60);
|
autoLockIn = preferences.getInt("autoLockIn", 60 * 60);
|
||||||
lastPauseTime = preferences.getInt("lastPauseTime", 0);
|
lastPauseTime = preferences.getInt("lastPauseTime", 0);
|
||||||
useFingerprint = preferences.getBoolean("useFingerprint", true);
|
useFingerprintLock = preferences.getBoolean("useFingerprint", true);
|
||||||
allowScreenCapture = preferences.getBoolean("allowScreenCapture", false);
|
allowScreenCapture = preferences.getBoolean("allowScreenCapture", false);
|
||||||
lastLocalId = preferences.getInt("lastLocalId", -210000);
|
lastLocalId = preferences.getInt("lastLocalId", -210000);
|
||||||
pushString = preferences.getString("pushString2", "");
|
pushString = preferences.getString("pushString2", "");
|
||||||
|
@ -643,6 +645,7 @@ public class SharedConfig {
|
||||||
updateStickersOrderOnSend = preferences.getBoolean("updateStickersOrderOnSend", true);
|
updateStickersOrderOnSend = preferences.getBoolean("updateStickersOrderOnSend", true);
|
||||||
dayNightWallpaperSwitchHint = preferences.getInt("dayNightWallpaperSwitchHint", 0);
|
dayNightWallpaperSwitchHint = preferences.getInt("dayNightWallpaperSwitchHint", 0);
|
||||||
bigCameraForRound = preferences.getBoolean("bigCameraForRound", false);
|
bigCameraForRound = preferences.getBoolean("bigCameraForRound", false);
|
||||||
|
useNewBlur = preferences.getBoolean("useNewBlur", true);
|
||||||
useCamera2Force = !preferences.contains("useCamera2Force") ? null : preferences.getBoolean("useCamera2Force", false);
|
useCamera2Force = !preferences.contains("useCamera2Force") ? null : preferences.getBoolean("useCamera2Force", false);
|
||||||
useSurfaceInStories = preferences.getBoolean("useSurfaceInStories", Build.VERSION.SDK_INT >= 30);
|
useSurfaceInStories = preferences.getBoolean("useSurfaceInStories", Build.VERSION.SDK_INT >= 30);
|
||||||
payByInvoice = preferences.getBoolean("payByInvoice", false);
|
payByInvoice = preferences.getBoolean("payByInvoice", false);
|
||||||
|
@ -851,7 +854,7 @@ public class SharedConfig {
|
||||||
passcodeSalt = new byte[0];
|
passcodeSalt = new byte[0];
|
||||||
autoLockIn = 60 * 60;
|
autoLockIn = 60 * 60;
|
||||||
lastPauseTime = 0;
|
lastPauseTime = 0;
|
||||||
useFingerprint = true;
|
useFingerprintLock = true;
|
||||||
isWaitingForPasscodeEnter = false;
|
isWaitingForPasscodeEnter = false;
|
||||||
allowScreenCapture = false;
|
allowScreenCapture = false;
|
||||||
textSelectionHintShows = 0;
|
textSelectionHintShows = 0;
|
||||||
|
@ -1671,7 +1674,7 @@ public class SharedConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canBlurChat() {
|
public static boolean canBlurChat() {
|
||||||
return getDevicePerformanceClass() == PERFORMANCE_CLASS_HIGH;
|
return getDevicePerformanceClass() >= (Build.VERSION.SDK_INT >= 31 ? PERFORMANCE_CLASS_AVERAGE : PERFORMANCE_CLASS_HIGH) || BuildVars.DEBUG_PRIVATE_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean chatBlurEnabled() {
|
public static boolean chatBlurEnabled() {
|
||||||
|
@ -1739,6 +1742,14 @@ public class SharedConfig {
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void toggleUseNewBlur() {
|
||||||
|
useNewBlur = !useNewBlur;
|
||||||
|
ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE)
|
||||||
|
.edit()
|
||||||
|
.putBoolean("useNewBlur", useNewBlur)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isUsingCamera2(int currentAccount) {
|
public static boolean isUsingCamera2(int currentAccount) {
|
||||||
return useCamera2Force == null ? !MessagesController.getInstance(currentAccount).androidDisableRoundCamera2 : useCamera2Force;
|
return useCamera2Force == null ? !MessagesController.getInstance(currentAccount).androidDisableRoundCamera2 : useCamera2Force;
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,6 +267,7 @@ public class UnconfirmedAuthController {
|
||||||
public String device;
|
public String device;
|
||||||
public String location;
|
public String location;
|
||||||
|
|
||||||
|
|
||||||
public UnconfirmedAuth(AbstractSerializedData stream) {
|
public UnconfirmedAuth(AbstractSerializedData stream) {
|
||||||
int magic = stream.readInt32(true);
|
int magic = stream.readInt32(true);
|
||||||
if (magic != 0x7ab6618c) {
|
if (magic != 0x7ab6618c) {
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class UserObject {
|
||||||
|
|
||||||
public static String getForcedFirstName(TLRPC.User user) {
|
public static String getForcedFirstName(TLRPC.User user) {
|
||||||
if (user == null || isDeleted(user)) {
|
if (user == null || isDeleted(user)) {
|
||||||
return "DELETED";
|
return LocaleController.getString(R.string.HiddenName);
|
||||||
}
|
}
|
||||||
String name = user.first_name;
|
String name = user.first_name;
|
||||||
if (TextUtils.isEmpty(name)) {
|
if (TextUtils.isEmpty(name)) {
|
||||||
|
|
|
@ -17,6 +17,8 @@ import android.graphics.Rect;
|
||||||
|
|
||||||
import com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom;
|
import com.carrotsearch.randomizedtesting.Xoroshiro128PlusRandom;
|
||||||
|
|
||||||
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
@ -254,53 +256,7 @@ public class Utilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isGoodPrime(byte[] prime, int g) {
|
public static boolean isGoodPrime(byte[] prime, int g) {
|
||||||
if (!(g >= 2 && g <= 7)) {
|
return ConnectionsManager.native_isGoodPrime(prime, g);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prime.length != 256 || prime[0] >= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BigInteger dhBI = new BigInteger(1, prime);
|
|
||||||
|
|
||||||
if (g == 2) { // p mod 8 = 7 for g = 2;
|
|
||||||
BigInteger res = dhBI.mod(BigInteger.valueOf(8));
|
|
||||||
if (res.intValue() != 7) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (g == 3) { // p mod 3 = 2 for g = 3;
|
|
||||||
BigInteger res = dhBI.mod(BigInteger.valueOf(3));
|
|
||||||
if (res.intValue() != 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (g == 5) { // p mod 5 = 1 or 4 for g = 5;
|
|
||||||
BigInteger res = dhBI.mod(BigInteger.valueOf(5));
|
|
||||||
int val = res.intValue();
|
|
||||||
if (val != 1 && val != 4) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (g == 6) { // p mod 24 = 19 or 23 for g = 6;
|
|
||||||
BigInteger res = dhBI.mod(BigInteger.valueOf(24));
|
|
||||||
int val = res.intValue();
|
|
||||||
if (val != 19 && val != 23) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (g == 7) { // p mod 7 = 3, 5 or 6 for g = 7.
|
|
||||||
BigInteger res = dhBI.mod(BigInteger.valueOf(7));
|
|
||||||
int val = res.intValue();
|
|
||||||
if (val != 3 && val != 5 && val != 6) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String hex = bytesToHex(prime);
|
|
||||||
if (hex.equals("C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B")) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BigInteger dhBI2 = dhBI.subtract(BigInteger.valueOf(1)).divide(BigInteger.valueOf(2));
|
|
||||||
return !(!dhBI.isProbablePrime(30) || !dhBI2.isProbablePrime(30));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isGoodGaAndGb(BigInteger g_a, BigInteger p) {
|
public static boolean isGoodGaAndGb(BigInteger g_a, BigInteger p) {
|
||||||
|
@ -481,6 +437,24 @@ public class Utilities {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String SHA256(String x) {
|
||||||
|
if (x == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] array = md.digest(AndroidUtilities.getStringBytes(x));
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int a = 0; a < array.length; a++) {
|
||||||
|
sb.append(Integer.toHexString((array[a] & 0xFF) | 0x100).substring(1, 3));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
} catch (java.security.NoSuchAlgorithmException e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static int clamp(int value, int maxValue, int minValue) {
|
public static int clamp(int value, int maxValue, int minValue) {
|
||||||
return Math.max(Math.min(value, maxValue), minValue);
|
return Math.max(Math.min(value, maxValue), minValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -768,10 +768,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
||||||
cameraThread.postRunnable(() -> this.cameraThread = null);
|
cameraThread.postRunnable(() -> this.cameraThread = null);
|
||||||
}
|
}
|
||||||
if (cameraSession[0] != null) {
|
if (cameraSession[0] != null) {
|
||||||
cameraSession[0].destroy(false, null, null);
|
cameraSession[0].destroy(true, null, null);
|
||||||
}
|
}
|
||||||
if (cameraSession[1] != null) {
|
if (cameraSession[1] != null) {
|
||||||
cameraSession[1].destroy(false, null, null);
|
cameraSession[1].destroy(true, null, null);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,11 @@ public class BillingUtilities {
|
||||||
paymentPurpose.serializeToStream(serializedData);
|
paymentPurpose.serializeToStream(serializedData);
|
||||||
String obfuscatedData = Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT);
|
String obfuscatedData = Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT);
|
||||||
serializedData.cleanup();
|
serializedData.cleanup();
|
||||||
if (paymentPurpose instanceof TLRPC.TL_inputStorePaymentPremiumGiftCode || paymentPurpose instanceof TLRPC.TL_inputStorePaymentPremiumGiveaway) {
|
if (
|
||||||
|
paymentPurpose instanceof TLRPC.TL_inputStorePaymentPremiumGiftCode ||
|
||||||
|
paymentPurpose instanceof TLRPC.TL_inputStorePaymentStars ||
|
||||||
|
paymentPurpose instanceof TLRPC.TL_inputStorePaymentPremiumGiveaway
|
||||||
|
) {
|
||||||
remPaymentPurpose = paymentPurpose;
|
remPaymentPurpose = paymentPurpose;
|
||||||
return Pair.create(obfuscatedAccountId, obfuscatedAccountId);
|
return Pair.create(obfuscatedAccountId, obfuscatedAccountId);
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,10 +101,15 @@ public class BillingUtilities {
|
||||||
try {
|
try {
|
||||||
TLRPC.InputStorePaymentPurpose purpose;
|
TLRPC.InputStorePaymentPurpose purpose;
|
||||||
if (remPaymentPurpose == null) {
|
if (remPaymentPurpose == null) {
|
||||||
byte[] obfuscatedDataBytes = Base64.decode(obfuscatedData, Base64.DEFAULT);
|
try {
|
||||||
SerializedData data = new SerializedData(obfuscatedDataBytes);
|
byte[] obfuscatedDataBytes = Base64.decode(obfuscatedData, Base64.DEFAULT);
|
||||||
purpose = TLRPC.InputStorePaymentPurpose.TLdeserialize(data, data.readInt32(true), true);
|
SerializedData data = new SerializedData(obfuscatedDataBytes);
|
||||||
data.cleanup();
|
purpose = TLRPC.InputStorePaymentPurpose.TLdeserialize(data, data.readInt32(true), true);
|
||||||
|
data.cleanup();
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
purpose = null;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
purpose = remPaymentPurpose;
|
purpose = remPaymentPurpose;
|
||||||
remPaymentPurpose = null;
|
remPaymentPurpose = null;
|
||||||
|
|
|
@ -4,6 +4,8 @@ import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.AtomicDouble;
|
||||||
|
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.BuildVars;
|
import org.telegram.messenger.BuildVars;
|
||||||
import org.telegram.messenger.DispatchQueuePoolBackground;
|
import org.telegram.messenger.DispatchQueuePoolBackground;
|
||||||
|
@ -27,6 +29,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class BitmapsCache {
|
public class BitmapsCache {
|
||||||
|
|
||||||
|
@ -38,6 +41,7 @@ public class BitmapsCache {
|
||||||
String fileName;
|
String fileName;
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
|
public final AtomicInteger framesProcessed = new AtomicInteger(0);
|
||||||
|
|
||||||
ArrayList<FrameOffset> frameOffsets = new ArrayList<>();
|
ArrayList<FrameOffset> frameOffsets = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -111,6 +115,7 @@ public class BitmapsCache {
|
||||||
if (frameOffsets.size() == 0) {
|
if (frameOffsets.size() == 0) {
|
||||||
cacheCreated = false;
|
cacheCreated = false;
|
||||||
fileExist = false;
|
fileExist = false;
|
||||||
|
checked = true;
|
||||||
file.delete();
|
file.delete();
|
||||||
} else {
|
} else {
|
||||||
if (cachedFile != randomAccessFile) {
|
if (cachedFile != randomAccessFile) {
|
||||||
|
@ -123,6 +128,7 @@ public class BitmapsCache {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
file.delete();
|
file.delete();
|
||||||
fileExist = false;
|
fileExist = false;
|
||||||
|
checked = true;
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (cachedFile != randomAccessFile && randomAccessFile != null) {
|
if (cachedFile != randomAccessFile && randomAccessFile != null) {
|
||||||
|
@ -133,12 +139,14 @@ public class BitmapsCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checked = true;
|
||||||
} else {
|
} else {
|
||||||
fileExist = false;
|
fileExist = false;
|
||||||
cacheCreated = false;
|
cacheCreated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public volatile boolean checked;
|
||||||
volatile boolean checkCache;
|
volatile boolean checkCache;
|
||||||
volatile boolean cacheCreated;
|
volatile boolean cacheCreated;
|
||||||
volatile boolean recycled;
|
volatile boolean recycled;
|
||||||
|
@ -189,10 +197,12 @@ public class BitmapsCache {
|
||||||
}
|
}
|
||||||
cachedFile = randomAccessFile;
|
cachedFile = randomAccessFile;
|
||||||
fileExist = true;
|
fileExist = true;
|
||||||
|
checked = true;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
fileExist = false;
|
fileExist = false;
|
||||||
cacheCreated = false;
|
cacheCreated = false;
|
||||||
|
checked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cacheCreated) {
|
if (!cacheCreated) {
|
||||||
|
@ -322,6 +332,7 @@ public class BitmapsCache {
|
||||||
if (index >= N) {
|
if (index >= N) {
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
framesProcessed.set(framePosition);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
if (countDownLatch[i] != null) {
|
if (countDownLatch[i] != null) {
|
||||||
|
@ -357,6 +368,7 @@ public class BitmapsCache {
|
||||||
cachedFile = new RandomAccessFile(file, "r");
|
cachedFile = new RandomAccessFile(file, "r");
|
||||||
cacheCreated = true;
|
cacheCreated = true;
|
||||||
fileExist = true;
|
fileExist = true;
|
||||||
|
checked = true;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -411,6 +423,7 @@ public class BitmapsCache {
|
||||||
framesCount = randomAccessFile.readInt();
|
framesCount = randomAccessFile.readInt();
|
||||||
if (framesCount <= 0) {
|
if (framesCount <= 0) {
|
||||||
cacheCreated = false;
|
cacheCreated = false;
|
||||||
|
checked = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -449,6 +462,7 @@ public class BitmapsCache {
|
||||||
}
|
}
|
||||||
if (frameOffsets.size() == 0) {
|
if (frameOffsets.size() == 0) {
|
||||||
cacheCreated = false;
|
cacheCreated = false;
|
||||||
|
checked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cacheCreated) {
|
if (!cacheCreated) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import android.text.Editable;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.style.StrikethroughSpan;
|
import android.text.style.StrikethroughSpan;
|
||||||
|
@ -34,6 +35,7 @@ public class CopyUtilities {
|
||||||
private final static int TYPE_SPOILER = 0;
|
private final static int TYPE_SPOILER = 0;
|
||||||
private final static int TYPE_MONO = 1;
|
private final static int TYPE_MONO = 1;
|
||||||
private final static int TYPE_QUOTE = 2;
|
private final static int TYPE_QUOTE = 2;
|
||||||
|
private final static int TYPE_COLLAPSE = 3;
|
||||||
|
|
||||||
public static Spannable fromHTML(String html) {
|
public static Spannable fromHTML(String html) {
|
||||||
Spanned spanned;
|
Spanned spanned;
|
||||||
|
@ -81,7 +83,7 @@ public class CopyUtilities {
|
||||||
} else {
|
} else {
|
||||||
entities.add(setEntityStartEnd(new TLRPC.TL_messageEntityPre(), start, end));
|
entities.add(setEntityStartEnd(new TLRPC.TL_messageEntityPre(), start, end));
|
||||||
}
|
}
|
||||||
} else if (parsedSpan.type == TYPE_QUOTE) {
|
} else if (parsedSpan.type == TYPE_QUOTE || parsedSpan.type == TYPE_COLLAPSE) {
|
||||||
quotes.add(parsedSpan);
|
quotes.add(parsedSpan);
|
||||||
}
|
}
|
||||||
} else if (span instanceof AnimatedEmojiSpan) {
|
} else if (span instanceof AnimatedEmojiSpan) {
|
||||||
|
@ -92,7 +94,7 @@ public class CopyUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SpannableString spannable = new SpannableString(spanned.toString());
|
SpannableStringBuilder spannable = new SpannableStringBuilder(spanned.toString());
|
||||||
MediaDataController.addTextStyleRuns(entities, spannable, spannable);
|
MediaDataController.addTextStyleRuns(entities, spannable, spannable);
|
||||||
for (int i = 0; i < spans.length; ++i) {
|
for (int i = 0; i < spans.length; ++i) {
|
||||||
Object span = spans[i];
|
Object span = spans[i];
|
||||||
|
@ -126,7 +128,7 @@ public class CopyUtilities {
|
||||||
}
|
}
|
||||||
for (int i = 0; i < quotes.size(); ++i) {
|
for (int i = 0; i < quotes.size(); ++i) {
|
||||||
ParsedSpan span = quotes.get(i);
|
ParsedSpan span = quotes.get(i);
|
||||||
QuoteSpan.putQuote(spannable, spanned.getSpanStart(span), spanned.getSpanEnd(span));
|
QuoteSpan.putQuoteToEditable(spannable, spanned.getSpanStart(span), spanned.getSpanEnd(span), span.type == TYPE_COLLAPSE);
|
||||||
}
|
}
|
||||||
return spannable;
|
return spannable;
|
||||||
}
|
}
|
||||||
|
@ -302,6 +304,21 @@ public class CopyUtilities {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (tag.equals("details")) {
|
||||||
|
if (opening) {
|
||||||
|
output.setSpan(new ParsedSpan(TYPE_COLLAPSE), output.length(), output.length(), Spanned.SPAN_MARK_MARK);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
ParsedSpan obj = getLast(output, ParsedSpan.class, TYPE_COLLAPSE);
|
||||||
|
if (obj != null) {
|
||||||
|
int where = output.getSpanStart(obj);
|
||||||
|
output.removeSpan(obj);
|
||||||
|
if (where != output.length()) {
|
||||||
|
output.setSpan(obj, where, output.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,36 @@ public class CustomHtml {
|
||||||
|
|
||||||
public static String toHtml(Spanned text) {
|
public static String toHtml(Spanned text) {
|
||||||
StringBuilder out = new StringBuilder();
|
StringBuilder out = new StringBuilder();
|
||||||
toHTML_1_wrapTextStyle(out, text, 0, text.length());
|
toHTML_0_wrapQuote(out, text, 0, text.length());
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void toHTML_0_wrapQuote(StringBuilder out, Spanned text, int start, int end) {
|
||||||
|
|
||||||
|
int next;
|
||||||
|
for (int i = start; i < end; i = next) {
|
||||||
|
next = text.nextSpanTransition(i, end, QuoteSpan.class);
|
||||||
|
if (next < 0) {
|
||||||
|
next = end;
|
||||||
|
}
|
||||||
|
QuoteSpan[] spans = text.getSpans(i, next, QuoteSpan.class);
|
||||||
|
|
||||||
|
if (spans != null) {
|
||||||
|
for (int j = 0; j < spans.length; ++j) {
|
||||||
|
out.append(spans[j].isCollapsing ? "<details>" : "<blockquote>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toHTML_1_wrapTextStyle(out, text, i, next);
|
||||||
|
|
||||||
|
if (spans != null) {
|
||||||
|
for (int j = spans.length - 1; j >= 0; --j) {
|
||||||
|
out.append(spans[j].isCollapsing ? "</details>" : "</blockquote>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void toHTML_1_wrapTextStyle(StringBuilder out, Spanned text, int start, int end) {
|
private static void toHTML_1_wrapTextStyle(StringBuilder out, Spanned text, int start, int end) {
|
||||||
int next;
|
int next;
|
||||||
for (int i = start; i < end; i = next) {
|
for (int i = start; i < end; i = next) {
|
||||||
|
@ -174,7 +200,7 @@ public class CustomHtml {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toHTML_5_wrapQuote(out, text, i, next);
|
toHTML_6_wrapAnimatedEmoji(out, text, i, next);
|
||||||
|
|
||||||
if (spans != null) {
|
if (spans != null) {
|
||||||
for (int j = 0; j < spans.length; ++j) {
|
for (int j = 0; j < spans.length; ++j) {
|
||||||
|
@ -187,32 +213,6 @@ public class CustomHtml {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void toHTML_5_wrapQuote(StringBuilder out, Spanned text, int start, int end) {
|
|
||||||
|
|
||||||
int next;
|
|
||||||
for (int i = start; i < end; i = next) {
|
|
||||||
next = text.nextSpanTransition(i, end, QuoteSpan.class);
|
|
||||||
if (next < 0) {
|
|
||||||
next = end;
|
|
||||||
}
|
|
||||||
QuoteSpan[] spans = text.getSpans(i, next, QuoteSpan.class);
|
|
||||||
|
|
||||||
if (spans != null) {
|
|
||||||
for (int j = 0; j < spans.length; ++j) {
|
|
||||||
out.append("<blockquote>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toHTML_6_wrapAnimatedEmoji(out, text, i, next);
|
|
||||||
|
|
||||||
if (spans != null) {
|
|
||||||
for (int j = 0; j < spans.length; ++j) {
|
|
||||||
out.append("</blockquote>");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void toHTML_6_wrapAnimatedEmoji(StringBuilder out, Spanned text, int start, int end) {
|
private static void toHTML_6_wrapAnimatedEmoji(StringBuilder out, Spanned text, int start, int end) {
|
||||||
int next;
|
int next;
|
||||||
for (int i = start; i < end; i = next) {
|
for (int i = start; i < end; i = next) {
|
||||||
|
|
|
@ -15,6 +15,11 @@ import android.util.LongSparseArray;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.util.Log;
|
import com.google.android.exoplayer2.util.Log;
|
||||||
|
import com.google.android.gms.tasks.Task;
|
||||||
|
import com.google.android.play.core.integrity.IntegrityManager;
|
||||||
|
import com.google.android.play.core.integrity.IntegrityManagerFactory;
|
||||||
|
import com.google.android.play.core.integrity.IntegrityTokenRequest;
|
||||||
|
import com.google.android.play.core.integrity.IntegrityTokenResponse;
|
||||||
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
|
import com.google.firebase.remoteconfig.FirebaseRemoteConfig;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
|
@ -46,6 +51,7 @@ import org.telegram.ui.Components.BulletinFactory;
|
||||||
import org.telegram.ui.Components.TypefaceSpan;
|
import org.telegram.ui.Components.TypefaceSpan;
|
||||||
import org.telegram.ui.DialogsActivity;
|
import org.telegram.ui.DialogsActivity;
|
||||||
import org.telegram.ui.LaunchActivity;
|
import org.telegram.ui.LaunchActivity;
|
||||||
|
import org.telegram.ui.LoginActivity;
|
||||||
import org.telegram.ui.PremiumPreviewFragment;
|
import org.telegram.ui.PremiumPreviewFragment;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
@ -100,6 +106,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
public final static int RequestFlagNeedQuickAck = 128;
|
public final static int RequestFlagNeedQuickAck = 128;
|
||||||
public final static int RequestFlagDoNotWaitFloodWait = 1024;
|
public final static int RequestFlagDoNotWaitFloodWait = 1024;
|
||||||
public final static int RequestFlagListenAfterCancel = 2048;
|
public final static int RequestFlagListenAfterCancel = 2048;
|
||||||
|
public final static int RequestFlagFailOnServerErrorsExceptFloodWait = 65536;
|
||||||
|
|
||||||
public final static int ConnectionStateConnecting = 1;
|
public final static int ConnectionStateConnecting = 1;
|
||||||
public final static int ConnectionStateWaitingForNetwork = 2;
|
public final static int ConnectionStateWaitingForNetwork = 2;
|
||||||
|
@ -786,6 +793,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
Utilities.globalQueue.postRunnable(() -> {
|
Utilities.globalQueue.postRunnable(() -> {
|
||||||
boolean networkOnline = ApplicationLoader.isNetworkOnline();
|
boolean networkOnline = ApplicationLoader.isNetworkOnline();
|
||||||
Utilities.stageQueue.postRunnable(() -> {
|
Utilities.stageQueue.postRunnable(() -> {
|
||||||
|
FileLog.d("13. currentTask == " + currentTask);
|
||||||
if (currentTask != null || second == 0 && Math.abs(lastDnsRequestTime - System.currentTimeMillis()) < 10000 || !networkOnline) {
|
if (currentTask != null || second == 0 && Math.abs(lastDnsRequestTime - System.currentTimeMillis()) < 10000 || !networkOnline) {
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
FileLog.d("don't start task, current task = " + currentTask + " next task = " + second + " time diff = " + Math.abs(lastDnsRequestTime - System.currentTimeMillis()) + " network = " + ApplicationLoader.isNetworkOnline());
|
FileLog.d("don't start task, current task = " + currentTask + " next task = " + second + " time diff = " + Math.abs(lastDnsRequestTime - System.currentTimeMillis()) + " network = " + ApplicationLoader.isNetworkOnline());
|
||||||
|
@ -793,26 +801,21 @@ public class ConnectionsManager extends BaseController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastDnsRequestTime = System.currentTimeMillis();
|
lastDnsRequestTime = System.currentTimeMillis();
|
||||||
if (second == 3) {
|
if (second == 2) {
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
FileLog.d("start mozilla txt task");
|
FileLog.d("start mozilla txt task");
|
||||||
}
|
}
|
||||||
MozillaDnsLoadTask task = new MozillaDnsLoadTask(currentAccount);
|
MozillaDnsLoadTask task = new MozillaDnsLoadTask(currentAccount);
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||||
|
FileLog.d("9. currentTask = mozilla");
|
||||||
currentTask = task;
|
currentTask = task;
|
||||||
} else if (second == 2) {
|
} else if (second == 1) {
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
FileLog.d("start google txt task");
|
FileLog.d("start google txt task");
|
||||||
}
|
}
|
||||||
GoogleDnsLoadTask task = new GoogleDnsLoadTask(currentAccount);
|
GoogleDnsLoadTask task = new GoogleDnsLoadTask(currentAccount);
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||||
currentTask = task;
|
FileLog.d("11. currentTask = dnstxt");
|
||||||
} else if (second == 1) {
|
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
|
||||||
FileLog.d("start dns txt task");
|
|
||||||
}
|
|
||||||
DnsTxtLoadTask task = new DnsTxtLoadTask(currentAccount);
|
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
|
||||||
currentTask = task;
|
currentTask = task;
|
||||||
} else {
|
} else {
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
|
@ -820,6 +823,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
}
|
}
|
||||||
FirebaseTask task = new FirebaseTask(currentAccount);
|
FirebaseTask task = new FirebaseTask(currentAccount);
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||||
|
FileLog.d("12. currentTask = firebase");
|
||||||
currentTask = task;
|
currentTask = task;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -937,6 +941,9 @@ public class ConnectionsManager extends BaseController {
|
||||||
public static native void native_onHostNameResolved(String host, long address, String ip);
|
public static native void native_onHostNameResolved(String host, long address, String ip);
|
||||||
public static native void native_discardConnection(int currentAccount, int datacenterId, int connectionType);
|
public static native void native_discardConnection(int currentAccount, int datacenterId, int connectionType);
|
||||||
public static native void native_failNotRunningRequest(int currentAccount, int token);
|
public static native void native_failNotRunningRequest(int currentAccount, int token);
|
||||||
|
public static native void native_receivedIntegrityCheckClassic(int currentAccount, int requestToken, String nonce, String token);
|
||||||
|
|
||||||
|
public static native boolean native_isGoodPrime(byte[] prime, int g);
|
||||||
|
|
||||||
public static int generateClassGuid() {
|
public static int generateClassGuid() {
|
||||||
return lastClassGuid++;
|
return lastClassGuid++;
|
||||||
|
@ -1143,135 +1150,6 @@ public class ConnectionsManager extends BaseController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DnsTxtLoadTask extends AsyncTask<Void, Void, NativeByteBuffer> {
|
|
||||||
|
|
||||||
private int currentAccount;
|
|
||||||
private int responseDate;
|
|
||||||
|
|
||||||
public DnsTxtLoadTask(int instance) {
|
|
||||||
super();
|
|
||||||
currentAccount = instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected NativeByteBuffer doInBackground(Void... voids) {
|
|
||||||
ByteArrayOutputStream outbuf = null;
|
|
||||||
InputStream httpConnectionStream = null;
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
try {
|
|
||||||
String googleDomain;
|
|
||||||
if (i == 0) {
|
|
||||||
googleDomain = "www.google.com";
|
|
||||||
} else if (i == 1) {
|
|
||||||
googleDomain = "www.google.ru";
|
|
||||||
} else {
|
|
||||||
googleDomain = "google.com";
|
|
||||||
}
|
|
||||||
String domain = native_isTestBackend(currentAccount) != 0 ? "tapv3.stel.com" : AccountInstance.getInstance(currentAccount).getMessagesController().dcDomainName;
|
|
||||||
int len = Utilities.random.nextInt(116) + 13;
|
|
||||||
final String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
||||||
|
|
||||||
StringBuilder padding = new StringBuilder(len);
|
|
||||||
for (int a = 0; a < len; a++) {
|
|
||||||
padding.append(characters.charAt(Utilities.random.nextInt(characters.length())));
|
|
||||||
}
|
|
||||||
URL downloadUrl = new URL("https://" + googleDomain + "/resolve?name=" + domain + "&type=ANY&random_padding=" + padding);
|
|
||||||
URLConnection httpConnection = downloadUrl.openConnection();
|
|
||||||
httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1");
|
|
||||||
httpConnection.addRequestProperty("Host", "dns.google.com");
|
|
||||||
httpConnection.setConnectTimeout(5000);
|
|
||||||
httpConnection.setReadTimeout(5000);
|
|
||||||
httpConnection.connect();
|
|
||||||
httpConnectionStream = httpConnection.getInputStream();
|
|
||||||
responseDate = (int) (httpConnection.getDate() / 1000);
|
|
||||||
|
|
||||||
outbuf = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
byte[] data = new byte[1024 * 32];
|
|
||||||
while (true) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int read = httpConnectionStream.read(data);
|
|
||||||
if (read > 0) {
|
|
||||||
outbuf.write(data, 0, read);
|
|
||||||
} else if (read == -1) {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JSONObject jsonObject = new JSONObject(new String(outbuf.toByteArray()));
|
|
||||||
JSONArray array = jsonObject.getJSONArray("Answer");
|
|
||||||
len = array.length();
|
|
||||||
ArrayList<String> arrayList = new ArrayList<>(len);
|
|
||||||
for (int a = 0; a < len; a++) {
|
|
||||||
JSONObject object = array.getJSONObject(a);
|
|
||||||
int type = object.getInt("type");
|
|
||||||
if (type != 16) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
arrayList.add(object.getString("data"));
|
|
||||||
}
|
|
||||||
Collections.sort(arrayList, (o1, o2) -> {
|
|
||||||
int l1 = o1.length();
|
|
||||||
int l2 = o2.length();
|
|
||||||
if (l1 > l2) {
|
|
||||||
return -1;
|
|
||||||
} else if (l1 < l2) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
for (int a = 0; a < arrayList.size(); a++) {
|
|
||||||
builder.append(arrayList.get(a).replace("\"", ""));
|
|
||||||
}
|
|
||||||
byte[] bytes = Base64.decode(builder.toString(), Base64.DEFAULT);
|
|
||||||
NativeByteBuffer buffer = new NativeByteBuffer(bytes.length);
|
|
||||||
buffer.writeBytes(bytes);
|
|
||||||
return buffer;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
FileLog.e(e, false);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (httpConnectionStream != null) {
|
|
||||||
httpConnectionStream.close();
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
FileLog.e(e, false);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (outbuf != null) {
|
|
||||||
outbuf.close();
|
|
||||||
}
|
|
||||||
} catch (Exception ignore) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(final NativeByteBuffer result) {
|
|
||||||
Utilities.stageQueue.postRunnable(() -> {
|
|
||||||
currentTask = null;
|
|
||||||
if (result != null) {
|
|
||||||
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone(), responseDate);
|
|
||||||
} else {
|
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
|
||||||
FileLog.d("failed to get dns txt result");
|
|
||||||
FileLog.d("start google task");
|
|
||||||
}
|
|
||||||
GoogleDnsLoadTask task = new GoogleDnsLoadTask(currentAccount);
|
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
|
||||||
currentTask = task;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class GoogleDnsLoadTask extends AsyncTask<Void, Void, NativeByteBuffer> {
|
private static class GoogleDnsLoadTask extends AsyncTask<Void, Void, NativeByteBuffer> {
|
||||||
|
|
||||||
private int currentAccount;
|
private int currentAccount;
|
||||||
|
@ -1374,6 +1252,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(final NativeByteBuffer result) {
|
protected void onPostExecute(final NativeByteBuffer result) {
|
||||||
Utilities.stageQueue.postRunnable(() -> {
|
Utilities.stageQueue.postRunnable(() -> {
|
||||||
|
FileLog.d("3. currentTask = null, result = " + result);
|
||||||
currentTask = null;
|
currentTask = null;
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone(), responseDate);
|
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone(), responseDate);
|
||||||
|
@ -1384,6 +1263,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
}
|
}
|
||||||
MozillaDnsLoadTask task = new MozillaDnsLoadTask(currentAccount);
|
MozillaDnsLoadTask task = new MozillaDnsLoadTask(currentAccount);
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||||
|
FileLog.d("4. currentTask = mozilla");
|
||||||
currentTask = task;
|
currentTask = task;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1493,6 +1373,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(final NativeByteBuffer result) {
|
protected void onPostExecute(final NativeByteBuffer result) {
|
||||||
Utilities.stageQueue.postRunnable(() -> {
|
Utilities.stageQueue.postRunnable(() -> {
|
||||||
|
FileLog.d("5. currentTask = null");
|
||||||
currentTask = null;
|
currentTask = null;
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone(), responseDate);
|
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone(), responseDate);
|
||||||
|
@ -1531,6 +1412,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
Utilities.stageQueue.postRunnable(() -> {
|
Utilities.stageQueue.postRunnable(() -> {
|
||||||
if (success) {
|
if (success) {
|
||||||
firebaseRemoteConfig.activate().addOnCompleteListener(finishedTask2 -> {
|
firebaseRemoteConfig.activate().addOnCompleteListener(finishedTask2 -> {
|
||||||
|
FileLog.d("6. currentTask = null");
|
||||||
currentTask = null;
|
currentTask = null;
|
||||||
String config = firebaseRemoteConfig.getString("ipconfigv3");
|
String config = firebaseRemoteConfig.getString("ipconfigv3");
|
||||||
if (!TextUtils.isEmpty(config)) {
|
if (!TextUtils.isEmpty(config)) {
|
||||||
|
@ -1548,11 +1430,21 @@ public class ConnectionsManager extends BaseController {
|
||||||
FileLog.d("failed to get firebase result");
|
FileLog.d("failed to get firebase result");
|
||||||
FileLog.d("start dns txt task");
|
FileLog.d("start dns txt task");
|
||||||
}
|
}
|
||||||
DnsTxtLoadTask task = new DnsTxtLoadTask(currentAccount);
|
GoogleDnsLoadTask task = new GoogleDnsLoadTask(currentAccount);
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||||
|
FileLog.d("7. currentTask = GoogleDnsLoadTask");
|
||||||
currentTask = task;
|
currentTask = task;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
|
FileLog.d("failed to get firebase result 2");
|
||||||
|
FileLog.d("start dns txt task");
|
||||||
|
}
|
||||||
|
GoogleDnsLoadTask task = new GoogleDnsLoadTask(currentAccount);
|
||||||
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||||
|
FileLog.d("7. currentTask = GoogleDnsLoadTask");
|
||||||
|
currentTask = task;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1562,8 +1454,9 @@ public class ConnectionsManager extends BaseController {
|
||||||
FileLog.d("failed to get firebase result");
|
FileLog.d("failed to get firebase result");
|
||||||
FileLog.d("start dns txt task");
|
FileLog.d("start dns txt task");
|
||||||
}
|
}
|
||||||
DnsTxtLoadTask task = new DnsTxtLoadTask(currentAccount);
|
GoogleDnsLoadTask task = new GoogleDnsLoadTask(currentAccount);
|
||||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||||
|
FileLog.d("8. currentTask = GoogleDnsLoadTask");
|
||||||
currentTask = task;
|
currentTask = task;
|
||||||
});
|
});
|
||||||
FileLog.e(e, false);
|
FileLog.e(e, false);
|
||||||
|
@ -1604,4 +1497,34 @@ public class ConnectionsManager extends BaseController {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void onIntegrityCheckClassic(final int currentAccount, final int requestToken, final String nonce) {
|
||||||
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
FileLog.d("account"+currentAccount+": server requests integrity classic check with nonce = " + nonce);
|
||||||
|
IntegrityManager integrityManager = IntegrityManagerFactory.create(ApplicationLoader.applicationContext);
|
||||||
|
Task<IntegrityTokenResponse> integrityTokenResponse = integrityManager.requestIntegrityToken(IntegrityTokenRequest.builder().setNonce(nonce).setCloudProjectNumber(760348033671L).build());
|
||||||
|
integrityTokenResponse
|
||||||
|
.addOnSuccessListener(r -> {
|
||||||
|
final String token = r.token();
|
||||||
|
|
||||||
|
if (token == null) {
|
||||||
|
FileLog.e("account"+currentAccount+": integrity check gave null token in " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
native_receivedIntegrityCheckClassic(currentAccount, requestToken, nonce, "PLAYINTEGRITY_FAILED_EXCEPTION_NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileLog.d("account"+currentAccount+": integrity check successfully gave token: " + token + " in " + (System.currentTimeMillis() - start) + "ms");
|
||||||
|
try {
|
||||||
|
native_receivedIntegrityCheckClassic(currentAccount, requestToken, nonce, token);
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e("receivedIntegrityCheckClassic failed", e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.addOnFailureListener(e -> {
|
||||||
|
FileLog.e("account"+currentAccount+": integrity check failed to give a token in " + (System.currentTimeMillis() - start) + "ms", e);
|
||||||
|
native_receivedIntegrityCheckClassic(currentAccount, requestToken, nonce, "PLAYINTEGRITY_FAILED_EXCEPTION_" + LoginActivity.errorString(e));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -187,6 +187,7 @@ public class TL_stories {
|
||||||
public TLRPC.Peer peer;
|
public TLRPC.Peer peer;
|
||||||
public int max_read_id;
|
public int max_read_id;
|
||||||
public ArrayList<StoryItem> stories = new ArrayList<>();
|
public ArrayList<StoryItem> stories = new ArrayList<>();
|
||||||
|
public boolean checkedExpired; //custom
|
||||||
|
|
||||||
public static PeerStories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
|
public static PeerStories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
|
||||||
PeerStories result = null;
|
PeerStories result = null;
|
||||||
|
|
|
@ -420,7 +420,7 @@ public class ActionBar extends FrameLayout {
|
||||||
} else {
|
} else {
|
||||||
titleTextView[i].setTextColor(getThemedColor(Theme.key_actionBarDefaultTitle));
|
titleTextView[i].setTextColor(getThemedColor(Theme.key_actionBarDefaultTitle));
|
||||||
}
|
}
|
||||||
titleTextView[i].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
titleTextView[i].setTypeface(AndroidUtilities.bold());
|
||||||
titleTextView[i].setDrawablePadding(dp(4));
|
titleTextView[i].setDrawablePadding(dp(4));
|
||||||
titleTextView[i].setPadding(0, dp(8), 0, dp(8));
|
titleTextView[i].setPadding(0, dp(8), 0, dp(8));
|
||||||
titleTextView[i].setRightDrawableTopPadding(-dp(1));
|
titleTextView[i].setRightDrawableTopPadding(-dp(1));
|
||||||
|
|
|
@ -32,7 +32,6 @@ import android.transition.TransitionManager;
|
||||||
import android.transition.TransitionSet;
|
import android.transition.TransitionSet;
|
||||||
import android.transition.TransitionValues;
|
import android.transition.TransitionValues;
|
||||||
import android.transition.Visibility;
|
import android.transition.Visibility;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
@ -52,7 +51,6 @@ import android.widget.FrameLayout;
|
||||||
import android.widget.HorizontalScrollView;
|
import android.widget.HorizontalScrollView;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.PopupWindow;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
@ -62,7 +60,6 @@ import androidx.core.graphics.ColorUtils;
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.AnimationNotificationsLocker;
|
import org.telegram.messenger.AnimationNotificationsLocker;
|
||||||
import org.telegram.messenger.LocaleController;
|
import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.NotificationCenter;
|
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.UserConfig;
|
import org.telegram.messenger.UserConfig;
|
||||||
import org.telegram.messenger.Utilities;
|
import org.telegram.messenger.Utilities;
|
||||||
|
@ -126,6 +123,10 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
public void onSearchPressed(EditText editText) {
|
public void onSearchPressed(EditText editText) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canClearCaption() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void onCaptionCleared() {
|
public void onCaptionCleared() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +134,10 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean showClearForCaption() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public Animator getCustomToggleTransition() {
|
public Animator getCustomToggleTransition() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -238,7 +243,7 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
if (text) {
|
if (text) {
|
||||||
textView = new TextView(context);
|
textView = new TextView(context);
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setGravity(Gravity.CENTER);
|
textView.setGravity(Gravity.CENTER);
|
||||||
textView.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0);
|
textView.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0);
|
||||||
textView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
textView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||||
|
@ -591,7 +596,30 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionBarMenuSubItem addSwipeBackItem(int icon, Drawable iconDrawable, String text, View viewToSwipeBack) {
|
public View addSubItem(int id, View cell) {
|
||||||
|
createPopupLayout();
|
||||||
|
|
||||||
|
cell.setMinimumWidth(AndroidUtilities.dp(196));
|
||||||
|
cell.setTag(id);
|
||||||
|
popupLayout.addView(cell);
|
||||||
|
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) cell.getLayoutParams();
|
||||||
|
if (LocaleController.isRTL) {
|
||||||
|
layoutParams.gravity = Gravity.RIGHT;
|
||||||
|
}
|
||||||
|
layoutParams.width = LayoutHelper.MATCH_PARENT;
|
||||||
|
layoutParams.height = AndroidUtilities.dp(48);
|
||||||
|
cell.setLayoutParams(layoutParams);
|
||||||
|
cell.setOnClickListener(view -> {
|
||||||
|
if (parentMenu != null) {
|
||||||
|
parentMenu.onItemClick((Integer) view.getTag());
|
||||||
|
} else if (delegate != null) {
|
||||||
|
delegate.onItemClick((Integer) view.getTag());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionBarMenuSubItem addSwipeBackItem(int icon, Drawable iconDrawable, String text, View viewToSwipeBack) {
|
||||||
createPopupLayout();
|
createPopupLayout();
|
||||||
|
|
||||||
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext(), false, false, false, resourcesProvider);
|
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext(), false, false, false, resourcesProvider);
|
||||||
|
@ -1580,7 +1608,7 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clearSearchFilters();
|
clearSearchFilters();
|
||||||
} else if (searchFieldCaption != null && searchFieldCaption.getVisibility() == VISIBLE) {
|
} else if (searchFieldCaption != null && searchFieldCaption.getVisibility() == VISIBLE && (listener == null || listener.canClearCaption())) {
|
||||||
searchFieldCaption.setVisibility(GONE);
|
searchFieldCaption.setVisibility(GONE);
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onCaptionCleared();
|
listener.onCaptionCleared();
|
||||||
|
@ -1611,7 +1639,7 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
if (clearButton != null) {
|
if (clearButton != null) {
|
||||||
if (!hasRemovableFilters() && TextUtils.isEmpty(searchField.getText()) &&
|
if (!hasRemovableFilters() && TextUtils.isEmpty(searchField.getText()) &&
|
||||||
(listener == null || !listener.forceShowClear()) &&
|
(listener == null || !listener.forceShowClear()) &&
|
||||||
(searchFieldCaption == null || searchFieldCaption.getVisibility() != VISIBLE)) {
|
(searchFieldCaption == null || searchFieldCaption.getVisibility() != VISIBLE || listener != null && !listener.showClearForCaption())) {
|
||||||
if (clearButton.getTag() != null) {
|
if (clearButton.getTag() != null) {
|
||||||
clearButton.setTag(null);
|
clearButton.setTag(null);
|
||||||
if (clearButtonAnimator != null) {
|
if (clearButtonAnimator != null) {
|
||||||
|
|
|
@ -33,7 +33,6 @@ import android.view.ViewConfiguration;
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
import androidx.core.math.MathUtils;
|
import androidx.core.math.MathUtils;
|
||||||
|
|
||||||
|
@ -47,10 +46,8 @@ import org.telegram.ui.Components.AnimatedFloat;
|
||||||
import org.telegram.ui.Components.AnimatedTextView;
|
import org.telegram.ui.Components.AnimatedTextView;
|
||||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||||
import org.telegram.ui.Components.FloatSeekBarAccessibilityDelegate;
|
import org.telegram.ui.Components.FloatSeekBarAccessibilityDelegate;
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
|
||||||
import org.telegram.ui.Components.MotionBackgroundDrawable;
|
import org.telegram.ui.Components.MotionBackgroundDrawable;
|
||||||
import org.telegram.ui.Components.SeekBarAccessibilityDelegate;
|
import org.telegram.ui.Components.SeekBarAccessibilityDelegate;
|
||||||
import org.telegram.ui.Components.SeekBarView;
|
|
||||||
import org.telegram.ui.Components.SpeedIconDrawable;
|
import org.telegram.ui.Components.SpeedIconDrawable;
|
||||||
|
|
||||||
public class ActionBarMenuSlider extends FrameLayout {
|
public class ActionBarMenuSlider extends FrameLayout {
|
||||||
|
@ -111,7 +108,7 @@ public class ActionBarMenuSlider extends FrameLayout {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
textDrawable.setCallback(this);
|
textDrawable.setCallback(this);
|
||||||
textDrawable.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
textDrawable.setTypeface(AndroidUtilities.bold());
|
||||||
textDrawable.setAnimationProperties(.3f, 0, 165, CubicBezierInterpolator.EASE_OUT_QUINT);
|
textDrawable.setAnimationProperties(.3f, 0, 165, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||||
textDrawable.setTextSize(AndroidUtilities.dpf2(14));
|
textDrawable.setTextSize(AndroidUtilities.dpf2(14));
|
||||||
textDrawable.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
|
textDrawable.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);
|
||||||
|
|
|
@ -27,6 +27,7 @@ public class ActionBarMenuSubItem extends FrameLayout {
|
||||||
private TextView textView;
|
private TextView textView;
|
||||||
private TextView subtextView;
|
private TextView subtextView;
|
||||||
public RLottieImageView imageView;
|
public RLottieImageView imageView;
|
||||||
|
private boolean checkViewLeft;
|
||||||
private CheckBox2 checkView;
|
private CheckBox2 checkView;
|
||||||
private ImageView rightIcon;
|
private ImageView rightIcon;
|
||||||
|
|
||||||
|
@ -86,13 +87,16 @@ public class ActionBarMenuSubItem extends FrameLayout {
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL));
|
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL));
|
||||||
|
|
||||||
|
checkViewLeft = LocaleController.isRTL;
|
||||||
if (needCheck > 0) {
|
if (needCheck > 0) {
|
||||||
checkView = new CheckBox2(context, 26, resourcesProvider);
|
checkView = new CheckBox2(context, 26, resourcesProvider);
|
||||||
checkView.setDrawUnchecked(false);
|
checkView.setDrawUnchecked(false);
|
||||||
checkView.setColor(-1, -1, Theme.key_radioBackgroundChecked);
|
checkView.setColor(-1, -1, Theme.key_radioBackgroundChecked);
|
||||||
checkView.setDrawBackgroundAsArc(-1);
|
checkView.setDrawBackgroundAsArc(-1);
|
||||||
if (needCheck == 1) {
|
if (needCheck == 1) {
|
||||||
|
checkViewLeft = !LocaleController.isRTL;
|
||||||
addView(checkView, LayoutHelper.createFrame(26, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)));
|
addView(checkView, LayoutHelper.createFrame(26, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)));
|
||||||
|
textView.setPadding(!LocaleController.isRTL ? dp(34) : 0, 0, !LocaleController.isRTL ? 0 : dp(34), 0);
|
||||||
} else {
|
} else {
|
||||||
addView(checkView, LayoutHelper.createFrame(26, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT)));
|
addView(checkView, LayoutHelper.createFrame(26, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT)));
|
||||||
textView.setPadding(LocaleController.isRTL ? dp(34) : 0, 0, LocaleController.isRTL ? 0 : dp(34), 0);
|
textView.setPadding(LocaleController.isRTL ? dp(34) : 0, 0, LocaleController.isRTL ? 0 : dp(34), 0);
|
||||||
|
@ -185,7 +189,7 @@ public class ActionBarMenuSubItem extends FrameLayout {
|
||||||
imageView.setImageResource(icon);
|
imageView.setImageResource(icon);
|
||||||
}
|
}
|
||||||
imageView.setVisibility(VISIBLE);
|
imageView.setVisibility(VISIBLE);
|
||||||
textView.setPadding(LocaleController.isRTL ? (checkView != null ? dp(34) : 0) : dp(43), 0, LocaleController.isRTL ? dp(43) : (checkView != null ? dp(34) : 0), 0);
|
textView.setPadding(checkViewLeft ? (checkView != null ? dp(43) : 0) : dp(icon != 0 || iconDrawable != null ? 43 : 0), 0, checkViewLeft ? dp(icon != 0 || iconDrawable != null ? 43 : 0) : (checkView != null ? dp(43) : 0), 0);
|
||||||
} else {
|
} else {
|
||||||
imageView.setVisibility(INVISIBLE);
|
imageView.setVisibility(INVISIBLE);
|
||||||
textView.setPadding(0, 0, 0, 0);
|
textView.setPadding(0, 0, 0, 0);
|
||||||
|
|
|
@ -97,7 +97,9 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
public final static int FLAG_USE_SWIPEBACK = 1;
|
public final static int FLAG_USE_SWIPEBACK = 1;
|
||||||
public final static int FLAG_SHOWN_FROM_BOTTOM = 2;
|
public final static int FLAG_SHOWN_FROM_BOTTOM = 2;
|
||||||
public boolean updateAnimation;
|
public boolean updateAnimation;
|
||||||
|
public boolean clipChildren;
|
||||||
public boolean swipeBackGravityRight;
|
public boolean swipeBackGravityRight;
|
||||||
|
public boolean swipeBackGravityBottom;
|
||||||
|
|
||||||
private OnDispatchKeyEventListener mOnDispatchKeyEventListener;
|
private OnDispatchKeyEventListener mOnDispatchKeyEventListener;
|
||||||
private float backScaleX = 1;
|
private float backScaleX = 1;
|
||||||
|
@ -281,6 +283,9 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
public void setBackAlpha(int value) {
|
public void setBackAlpha(int value) {
|
||||||
|
if (backAlpha != value) {
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
backAlpha = value;
|
backAlpha = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,6 +445,9 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
setTranslationY(yOffset);
|
setTranslationY(yOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (swipeBackGravityBottom) {
|
||||||
|
setTranslationY(getMeasuredHeight() * (1f - backScaleY));
|
||||||
|
}
|
||||||
if (backgroundDrawable != null) {
|
if (backgroundDrawable != null) {
|
||||||
int start = gapStartY - scrollView.getScrollY();
|
int start = gapStartY - scrollView.getScrollY();
|
||||||
int end = gapEndY - scrollView.getScrollY();
|
int end = gapEndY - scrollView.getScrollY();
|
||||||
|
@ -454,14 +462,12 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
if (a == 1 && start < -AndroidUtilities.dp(16)) {
|
if (a == 1 && start < -AndroidUtilities.dp(16)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
boolean needRestore = false;
|
int saveCount = canvas.getSaveCount();
|
||||||
boolean applyAlpha = true;
|
boolean applyAlpha = true;
|
||||||
if (hasGap && backAlpha != 255) {
|
if (hasGap && backAlpha != 255) {
|
||||||
canvas.saveLayerAlpha(0, bgPaddings.top, getMeasuredWidth(), getMeasuredHeight(), backAlpha, Canvas.ALL_SAVE_FLAG);
|
canvas.saveLayerAlpha(0, bgPaddings.top, getMeasuredWidth(), getMeasuredHeight(), backAlpha, Canvas.ALL_SAVE_FLAG);
|
||||||
needRestore = true;
|
|
||||||
applyAlpha = false;
|
applyAlpha = false;
|
||||||
} else if (gapStartY != -1000000) {
|
} else if (gapStartY != -1000000) {
|
||||||
needRestore = true;
|
|
||||||
canvas.save();
|
canvas.save();
|
||||||
canvas.clipRect(0, bgPaddings.top, getMeasuredWidth(), getMeasuredHeight());
|
canvas.clipRect(0, bgPaddings.top, getMeasuredWidth(), getMeasuredHeight());
|
||||||
}
|
}
|
||||||
|
@ -508,6 +514,13 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
}
|
}
|
||||||
backgroundDrawable.setBounds(AndroidUtilities.rectTmp2);
|
backgroundDrawable.setBounds(AndroidUtilities.rectTmp2);
|
||||||
backgroundDrawable.draw(canvas);
|
backgroundDrawable.draw(canvas);
|
||||||
|
if (clipChildren) {
|
||||||
|
AndroidUtilities.rectTmp2.left += bgPaddings.left;
|
||||||
|
AndroidUtilities.rectTmp2.top += bgPaddings.top;
|
||||||
|
AndroidUtilities.rectTmp2.right -= bgPaddings.right;
|
||||||
|
AndroidUtilities.rectTmp2.bottom -= bgPaddings.bottom;
|
||||||
|
canvas.clipRect(AndroidUtilities.rectTmp2);
|
||||||
|
}
|
||||||
if (hasGap) {
|
if (hasGap) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
AndroidUtilities.rectTmp.set(backgroundDrawable.getBounds());
|
AndroidUtilities.rectTmp.set(backgroundDrawable.getBounds());
|
||||||
|
@ -540,9 +553,7 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
}
|
}
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
}
|
}
|
||||||
if (needRestore) {
|
canvas.restoreToCount(saveCount);
|
||||||
canvas.restore();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reactionsEnterProgress != 1f) {
|
if (reactionsEnterProgress != 1f) {
|
||||||
|
@ -845,10 +856,11 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
}
|
}
|
||||||
float at = AndroidUtilities.cascade(t, content.shownFromBottom ? count2 - 1 - a : a, count2, 4);
|
float at = AndroidUtilities.cascade(t, content.shownFromBottom ? count2 - 1 - a : a, count2, 4);
|
||||||
child.setTranslationY((1f - at) * AndroidUtilities.dp(-6));
|
child.setTranslationY((1f - at) * AndroidUtilities.dp(-6));
|
||||||
// child.setAlpha(at * (child.isEnabled() ? 1f : 0.5f));
|
child.setAlpha(at * (child.isEnabled() ? 1f : 0.5f));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
content.updateAnimation = true;
|
content.updateAnimation = false;
|
||||||
|
content.clipChildren = true;
|
||||||
windowAnimatorSet.playTogether(
|
windowAnimatorSet.playTogether(
|
||||||
ObjectAnimator.ofFloat(content, "backScaleY", 0.0f, finalScaleY),
|
ObjectAnimator.ofFloat(content, "backScaleY", 0.0f, finalScaleY),
|
||||||
ObjectAnimator.ofInt(content, "backAlpha", 0, 255),
|
ObjectAnimator.ofInt(content, "backAlpha", 0, 255),
|
||||||
|
@ -865,6 +877,7 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
if (child instanceof GapView) {
|
if (child instanceof GapView) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
child.setTranslationY(0);
|
||||||
child.setAlpha(child.isEnabled() ? 1f : 0.5f);
|
child.setAlpha(child.isEnabled() ? 1f : 0.5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.ValueAnimator;
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
@ -20,7 +20,6 @@ import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapShader;
|
import android.graphics.BitmapShader;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.ColorFilter;
|
import android.graphics.ColorFilter;
|
||||||
import android.graphics.CornerPathEffect;
|
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
|
@ -55,10 +54,7 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.util.Log;
|
|
||||||
|
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.Emoji;
|
|
||||||
import org.telegram.messenger.FileLog;
|
import org.telegram.messenger.FileLog;
|
||||||
import org.telegram.messenger.LiteMode;
|
import org.telegram.messenger.LiteMode;
|
||||||
import org.telegram.messenger.LocaleController;
|
import org.telegram.messenger.LocaleController;
|
||||||
|
@ -71,12 +67,10 @@ import org.telegram.ui.Components.AnimatedFloat;
|
||||||
import org.telegram.ui.Components.EffectsTextView;
|
import org.telegram.ui.Components.EffectsTextView;
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
import org.telegram.ui.Components.LineProgressView;
|
import org.telegram.ui.Components.LineProgressView;
|
||||||
import org.telegram.ui.Components.LinkSpanDrawable;
|
|
||||||
import org.telegram.ui.Components.RLottieDrawable;
|
import org.telegram.ui.Components.RLottieDrawable;
|
||||||
import org.telegram.ui.Components.RLottieImageView;
|
import org.telegram.ui.Components.RLottieImageView;
|
||||||
import org.telegram.ui.Components.RadialProgressView;
|
import org.telegram.ui.Components.RadialProgressView;
|
||||||
import org.telegram.ui.Components.spoilers.SpoilersTextView;
|
import org.telegram.ui.Components.spoilers.SpoilersTextView;
|
||||||
import org.telegram.ui.LaunchActivity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -88,6 +82,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
|
||||||
public static final int ALERT_TYPE_SPINNER = 3;
|
public static final int ALERT_TYPE_SPINNER = 3;
|
||||||
|
|
||||||
private int customWidth = -1;
|
private int customWidth = -1;
|
||||||
|
private boolean customMaxHeight;
|
||||||
private View customView;
|
private View customView;
|
||||||
private View bottomView;
|
private View bottomView;
|
||||||
private View aboveMessageView;
|
private View aboveMessageView;
|
||||||
|
@ -302,6 +297,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void show() {
|
public void show() {
|
||||||
|
if (!AndroidUtilities.isSafeToShow(getContext())) return;
|
||||||
super.show();
|
super.show();
|
||||||
if (progressViewContainer != null && progressViewStyle == ALERT_TYPE_SPINNER) {
|
if (progressViewContainer != null && progressViewStyle == ALERT_TYPE_SPINNER) {
|
||||||
progressViewContainer.setScaleX(0);
|
progressViewContainer.setScaleX(0);
|
||||||
|
@ -690,7 +686,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
|
||||||
titleTextView.setText(title);
|
titleTextView.setText(title);
|
||||||
titleTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
titleTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
||||||
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
|
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
|
||||||
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
titleTextView.setTypeface(AndroidUtilities.bold());
|
||||||
titleTextView.setGravity((topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
titleTextView.setGravity((topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
||||||
titleContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 0, 19, 0, topAnimationIsNew ? 4 : (subtitle != null ? 2 : (items != null ? 14 : 10))));
|
titleContainer.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 0, 19, 0, topAnimationIsNew ? 4 : (subtitle != null ? 2 : (items != null ? 14 : 10))));
|
||||||
}
|
}
|
||||||
|
@ -766,7 +762,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
|
||||||
containerView.addView(lineProgressView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 4, Gravity.LEFT | Gravity.CENTER_VERTICAL, 24, 0, 24, 0));
|
containerView.addView(lineProgressView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 4, Gravity.LEFT | Gravity.CENTER_VERTICAL, 24, 0, 24, 0));
|
||||||
|
|
||||||
lineProgressViewPercent = new TextView(getContext());
|
lineProgressViewPercent = new TextView(getContext());
|
||||||
lineProgressViewPercent.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
lineProgressViewPercent.setTypeface(AndroidUtilities.bold());
|
||||||
lineProgressViewPercent.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
lineProgressViewPercent.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
||||||
lineProgressViewPercent.setTextColor(getThemedColor(Theme.key_dialogTextGray2));
|
lineProgressViewPercent.setTextColor(getThemedColor(Theme.key_dialogTextGray2));
|
||||||
lineProgressViewPercent.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
lineProgressViewPercent.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
|
@ -962,7 +958,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
||||||
textView.setGravity(Gravity.CENTER);
|
textView.setGravity(Gravity.CENTER);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
// textView.setLines(1);
|
// textView.setLines(1);
|
||||||
// textView.setSingleLine(true); //TODO
|
// textView.setSingleLine(true); //TODO
|
||||||
textView.setText(positiveButtonText.toString());
|
textView.setText(positiveButtonText.toString());
|
||||||
|
@ -1002,7 +998,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
||||||
textView.setGravity(Gravity.CENTER);
|
textView.setGravity(Gravity.CENTER);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
textView.setSingleLine(true);
|
textView.setSingleLine(true);
|
||||||
textView.setText(negativeButtonText.toString());
|
textView.setText(negativeButtonText.toString());
|
||||||
|
@ -1042,7 +1038,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
textView.setTextColor(getThemedColor(dialogButtonColorKey));
|
||||||
textView.setGravity(Gravity.CENTER);
|
textView.setGravity(Gravity.CENTER);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
textView.setSingleLine(true);
|
textView.setSingleLine(true);
|
||||||
textView.setText(neutralButtonText.toString());
|
textView.setText(neutralButtonText.toString());
|
||||||
|
@ -1741,5 +1737,10 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
|
||||||
alertDialog.additioanalHorizontalPadding = padding;
|
alertDialog.additioanalHorizontalPadding = padding;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder makeCustomMaxHeight() {
|
||||||
|
alertDialog.customMaxHeight = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.telegram.ui.ActionBar;
|
package org.telegram.ui.ActionBar;
|
||||||
|
|
||||||
|
import static org.telegram.messenger.AndroidUtilities.dp;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
@ -118,7 +120,7 @@ public class AlertDialogDecor extends AlertDialog {
|
||||||
} else {
|
} else {
|
||||||
rect.set(insets.getStableInsetLeft(), insets.getStableInsetTop(), insets.getStableInsetRight(), insets.getStableInsetBottom());
|
rect.set(insets.getStableInsetLeft(), insets.getStableInsetTop(), insets.getStableInsetRight(), insets.getStableInsetBottom());
|
||||||
}
|
}
|
||||||
contentWrapper.setPadding(rect.left, rect.top, rect.right, rect.bottom);
|
contentWrapper.setPadding(rect.left, rect.top, rect.right, rect.bottom + AndroidUtilities.navigationBarHeight);
|
||||||
contentWrapper.requestLayout();
|
contentWrapper.requestLayout();
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,6 +13,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
@ -29,7 +30,6 @@ import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
@ -75,6 +75,7 @@ public class BottomSheet extends Dialog {
|
||||||
protected ViewGroup containerView;
|
protected ViewGroup containerView;
|
||||||
public ContainerView container;
|
public ContainerView container;
|
||||||
protected boolean keyboardVisible;
|
protected boolean keyboardVisible;
|
||||||
|
private int lastKeyboardHeight;
|
||||||
protected int keyboardHeight;
|
protected int keyboardHeight;
|
||||||
private WindowInsets lastInsets;
|
private WindowInsets lastInsets;
|
||||||
public boolean drawNavigationBar;
|
public boolean drawNavigationBar;
|
||||||
|
@ -502,6 +503,8 @@ public class BottomSheet extends Dialog {
|
||||||
keyboardHeight = Math.max(0, usableViewHeight - (rect.bottom - rect.top));
|
keyboardHeight = Math.max(0, usableViewHeight - (rect.bottom - rect.top));
|
||||||
if (keyboardHeight < AndroidUtilities.dp(20)) {
|
if (keyboardHeight < AndroidUtilities.dp(20)) {
|
||||||
keyboardHeight = 0;
|
keyboardHeight = 0;
|
||||||
|
} else {
|
||||||
|
lastKeyboardHeight = keyboardHeight;
|
||||||
}
|
}
|
||||||
bottomInset -= keyboardHeight;
|
bottomInset -= keyboardHeight;
|
||||||
} else {
|
} else {
|
||||||
|
@ -933,13 +936,13 @@ public class BottomSheet extends Dialog {
|
||||||
textView.setGravity(Gravity.CENTER);
|
textView.setGravity(Gravity.CENTER);
|
||||||
textView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
textView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||||
} else if (type == 2) {
|
} else if (type == 2) {
|
||||||
textView.setGravity(Gravity.CENTER);
|
textView.setGravity(Gravity.CENTER);
|
||||||
textView.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText));
|
textView.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText));
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 6));
|
textView.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 6));
|
||||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 16, 16, 16));
|
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 16, 16, 16));
|
||||||
}
|
}
|
||||||
|
@ -1178,6 +1181,9 @@ public class BottomSheet extends Dialog {
|
||||||
@Override
|
@Override
|
||||||
public void setTranslationY(float translationY) {
|
public void setTranslationY(float translationY) {
|
||||||
super.setTranslationY(translationY);
|
super.setTranslationY(translationY);
|
||||||
|
if (topBulletinContainer != null) {
|
||||||
|
topBulletinContainer.setTranslationY(-getHeight() + translationY - getPaddingTop() - AndroidUtilities.statusBarHeight + backgroundPaddingTop);
|
||||||
|
}
|
||||||
onContainerTranslationYChanged(translationY);
|
onContainerTranslationYChanged(translationY);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1187,6 +1193,11 @@ public class BottomSheet extends Dialog {
|
||||||
containerView.setVisibility(View.INVISIBLE);
|
containerView.setVisibility(View.INVISIBLE);
|
||||||
container.addView(containerView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
|
container.addView(containerView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
|
||||||
|
|
||||||
|
if (topBulletinContainer == null) {
|
||||||
|
topBulletinContainer = new FrameLayout(getContext());
|
||||||
|
container.addView(topBulletinContainer, container.indexOfChild(containerView) + 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
|
||||||
|
}
|
||||||
|
|
||||||
int topOffset = 0;
|
int topOffset = 0;
|
||||||
if (title != null) {
|
if (title != null) {
|
||||||
titleView = new TextView(getContext()) {
|
titleView = new TextView(getContext()) {
|
||||||
|
@ -1214,7 +1225,7 @@ public class BottomSheet extends Dialog {
|
||||||
if (bigTitle) {
|
if (bigTitle) {
|
||||||
titleView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
titleView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
||||||
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
|
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
|
||||||
titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
titleView.setTypeface(AndroidUtilities.bold());
|
||||||
titleView.setPadding(AndroidUtilities.dp(21), AndroidUtilities.dp(multipleLinesTitle ? 14 : 6), AndroidUtilities.dp(21), AndroidUtilities.dp(8));
|
titleView.setPadding(AndroidUtilities.dp(21), AndroidUtilities.dp(multipleLinesTitle ? 14 : 6), AndroidUtilities.dp(21), AndroidUtilities.dp(8));
|
||||||
} else {
|
} else {
|
||||||
titleView.setTextColor(getThemedColor(Theme.key_dialogTextGray2));
|
titleView.setTextColor(getThemedColor(Theme.key_dialogTextGray2));
|
||||||
|
@ -1345,6 +1356,7 @@ public class BottomSheet extends Dialog {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void show() {
|
public void show() {
|
||||||
|
if (!AndroidUtilities.isSafeToShow(getContext())) return;
|
||||||
super.show();
|
super.show();
|
||||||
setShowing(true);
|
setShowing(true);
|
||||||
if (focusable) {
|
if (focusable) {
|
||||||
|
@ -1720,6 +1732,11 @@ public class BottomSheet extends Dialog {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean forceKeyboardOnDismiss;
|
||||||
|
public void forceKeyboardOnDismiss() {
|
||||||
|
forceKeyboardOnDismiss = true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dismiss() {
|
public void dismiss() {
|
||||||
if (delegate != null && !delegate.canDismiss()) {
|
if (delegate != null && !delegate.canDismiss()) {
|
||||||
|
@ -1763,7 +1780,7 @@ public class BottomSheet extends Dialog {
|
||||||
animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_X, AndroidUtilities.dp(48)));
|
animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_X, AndroidUtilities.dp(48)));
|
||||||
animators.add(ObjectAnimator.ofFloat(containerView, View.ALPHA, 0));
|
animators.add(ObjectAnimator.ofFloat(containerView, View.ALPHA, 0));
|
||||||
} else {
|
} else {
|
||||||
animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)));
|
animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + (forceKeyboardOnDismiss ? lastKeyboardHeight : keyboardHeight) + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
animators.add(ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0));
|
animators.add(ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0));
|
||||||
|
|
|
@ -46,6 +46,7 @@ import org.telegram.messenger.BuildVars;
|
||||||
import org.telegram.messenger.FileLog;
|
import org.telegram.messenger.FileLog;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.Utilities;
|
import org.telegram.messenger.Utilities;
|
||||||
|
import org.telegram.ui.Components.PasscodeView;
|
||||||
|
|
||||||
public class DrawerLayoutContainer extends FrameLayout {
|
public class DrawerLayoutContainer extends FrameLayout {
|
||||||
|
|
||||||
|
|
|
@ -590,6 +590,7 @@ public class EmojiThemes {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getOrDefault(SparseIntArray colorsMap, int key) {
|
private int getOrDefault(SparseIntArray colorsMap, int key) {
|
||||||
|
if (colorsMap == null) return Theme.getDefaultColor(key);
|
||||||
int index = colorsMap.indexOfKey(key);
|
int index = colorsMap.indexOfKey(key);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
return colorsMap.valueAt(index);
|
return colorsMap.valueAt(index);
|
||||||
|
|
|
@ -34,7 +34,6 @@ import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.GradientDrawable;
|
import android.graphics.drawable.GradientDrawable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.Size;
|
import android.util.Size;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
@ -70,7 +69,6 @@ import org.telegram.messenger.NotificationCenter;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.UserConfig;
|
import org.telegram.messenger.UserConfig;
|
||||||
import org.telegram.messenger.Utilities;
|
import org.telegram.messenger.Utilities;
|
||||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -1315,7 +1313,7 @@ public final class FloatingToolbar {
|
||||||
textView.setGravity(Gravity.CENTER);
|
textView.setGravity(Gravity.CENTER);
|
||||||
textView.setSingleLine(true);
|
textView.setSingleLine(true);
|
||||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
textView.setFocusable(false);
|
textView.setFocusable(false);
|
||||||
textView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
textView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||||
|
|
|
@ -152,6 +152,17 @@ public interface INavigationLayout {
|
||||||
return getFragmentStack().isEmpty() ? null : getFragmentStack().get(getFragmentStack().size() - 1);
|
return getFragmentStack().isEmpty() ? null : getFragmentStack().get(getFragmentStack().size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default BaseFragment getSafeLastFragment() {
|
||||||
|
if (getFragmentStack().isEmpty()) return null;
|
||||||
|
for (int i = getFragmentStack().size() - 1; i >= 0; --i) {
|
||||||
|
BaseFragment fragment = getFragmentStack().get(i);
|
||||||
|
if (fragment == null || fragment.isFinishing() || fragment.isRemovingFromStack())
|
||||||
|
continue;
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
default void animateThemedValues(Theme.ThemeInfo theme, int accentId, boolean nightTheme, boolean instant) {
|
default void animateThemedValues(Theme.ThemeInfo theme, int accentId, boolean nightTheme, boolean instant) {
|
||||||
animateThemedValues(new ThemeAnimationSettings(theme, accentId, nightTheme, instant), null);
|
animateThemedValues(new ThemeAnimationSettings(theme, accentId, nightTheme, instant), null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,11 +103,11 @@ public class OKLCH {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double[] oklch2rgb(double[] lch) {
|
public static double[] oklch2rgb(double[] lch) {
|
||||||
return srgbLinear2rgb(xyz2rgbLinear(oklab2xyz(oklch2oklab(lch))));
|
return xyz2rgbLinear(oklab2xyz(oklch2oklab(lch)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double[] rgb2oklch(double[] rgb) {
|
public static double[] rgb2oklch(double[] rgb) {
|
||||||
return oklab2oklch(xyz2oklab(rgbLinear2xyz(rgb2srgbLinear(rgb))));
|
return oklab2oklch(xyz2oklab(rgbLinear2xyz(rgb)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double[] rgb(int color) {
|
public static double[] rgb(int color) {
|
||||||
|
|
|
@ -101,6 +101,7 @@ import org.telegram.tgnet.ConnectionsManager;
|
||||||
import org.telegram.tgnet.SerializedData;
|
import org.telegram.tgnet.SerializedData;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.BlurSettingsBottomSheet;
|
import org.telegram.ui.BlurSettingsBottomSheet;
|
||||||
|
import org.telegram.ui.Cells.BaseCell;
|
||||||
import org.telegram.ui.ChatActivity;
|
import org.telegram.ui.ChatActivity;
|
||||||
import org.telegram.ui.Components.AudioVisualizerDrawable;
|
import org.telegram.ui.Components.AudioVisualizerDrawable;
|
||||||
import org.telegram.ui.Components.BackgroundGradientDrawable;
|
import org.telegram.ui.Components.BackgroundGradientDrawable;
|
||||||
|
@ -3912,6 +3913,7 @@ public class Theme {
|
||||||
public static final int key_chat_TextSelectionCursor = colorsCount++;
|
public static final int key_chat_TextSelectionCursor = colorsCount++;
|
||||||
public static final int key_chat_inBubbleLocationPlaceholder = colorsCount++;
|
public static final int key_chat_inBubbleLocationPlaceholder = colorsCount++;
|
||||||
public static final int key_chat_BlurAlpha = colorsCount++;
|
public static final int key_chat_BlurAlpha = colorsCount++;
|
||||||
|
public static final int key_chat_BlurAlphaSlow = colorsCount++;
|
||||||
public static final int key_chat_editMediaButton = colorsCount++;
|
public static final int key_chat_editMediaButton = colorsCount++;
|
||||||
|
|
||||||
public static final int key_voipgroup_listSelector = colorsCount++;
|
public static final int key_voipgroup_listSelector = colorsCount++;
|
||||||
|
@ -3977,6 +3979,9 @@ public class Theme {
|
||||||
public static final int key_voipgroup_windowBackgroundWhiteInputField = colorsCount++;
|
public static final int key_voipgroup_windowBackgroundWhiteInputField = colorsCount++;
|
||||||
public static final int key_voipgroup_windowBackgroundWhiteInputFieldActivated = colorsCount++;
|
public static final int key_voipgroup_windowBackgroundWhiteInputFieldActivated = colorsCount++;
|
||||||
|
|
||||||
|
public static final int key_table_background = colorsCount++;
|
||||||
|
public static final int key_table_border = colorsCount++;
|
||||||
|
|
||||||
public static final int key_passport_authorizeBackground = colorsCount++;
|
public static final int key_passport_authorizeBackground = colorsCount++;
|
||||||
public static final int key_passport_authorizeBackgroundSelected = colorsCount++;
|
public static final int key_passport_authorizeBackgroundSelected = colorsCount++;
|
||||||
public static final int key_passport_authorizeText = colorsCount++;
|
public static final int key_passport_authorizeText = colorsCount++;
|
||||||
|
@ -4135,6 +4140,8 @@ public class Theme {
|
||||||
public static final int key_premiumGradientBottomSheet3 = colorsCount++;
|
public static final int key_premiumGradientBottomSheet3 = colorsCount++;
|
||||||
public static final int key_topics_unreadCounter = colorsCount++;
|
public static final int key_topics_unreadCounter = colorsCount++;
|
||||||
public static final int key_topics_unreadCounterMuted = colorsCount++;
|
public static final int key_topics_unreadCounterMuted = colorsCount++;
|
||||||
|
public static final int key_starsGradient1 = colorsCount++;
|
||||||
|
public static final int key_starsGradient2 = colorsCount++;
|
||||||
|
|
||||||
public static final int key_stories_circle1 = colorsCount++;
|
public static final int key_stories_circle1 = colorsCount++;
|
||||||
public static final int key_stories_circle2 = colorsCount++;
|
public static final int key_stories_circle2 = colorsCount++;
|
||||||
|
@ -4406,6 +4413,9 @@ public class Theme {
|
||||||
fallbackKeys.put(key_actionBarActionModeReaction, key_windowBackgroundGray);
|
fallbackKeys.put(key_actionBarActionModeReaction, key_windowBackgroundGray);
|
||||||
fallbackKeys.put(key_actionBarActionModeReactionText, key_chat_inReactionButtonText);
|
fallbackKeys.put(key_actionBarActionModeReactionText, key_chat_inReactionButtonText);
|
||||||
|
|
||||||
|
fallbackKeys.put(key_table_background, key_graySection);
|
||||||
|
fallbackKeys.put(key_table_border, key_divider);
|
||||||
|
|
||||||
for (int i = 0; i < keys_avatar_background.length; i++) {
|
for (int i = 0; i < keys_avatar_background.length; i++) {
|
||||||
themeAccentExclusionKeys.add(keys_avatar_background[i]);
|
themeAccentExclusionKeys.add(keys_avatar_background[i]);
|
||||||
}
|
}
|
||||||
|
@ -5293,7 +5303,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{pressedColor}
|
new int[]{pressedColor}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, defaultDrawable, pressedDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, defaultDrawable, pressedDrawable);
|
||||||
} else {
|
} else {
|
||||||
pressedDrawable.getPaint().setColor(pressedColor);
|
pressedDrawable.getPaint().setColor(pressedColor);
|
||||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
|
@ -5375,7 +5385,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{pressedColor}
|
new int[]{pressedColor}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, defaultDrawable, pressedDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, defaultDrawable, pressedDrawable);
|
||||||
} else {
|
} else {
|
||||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);
|
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);
|
||||||
|
@ -5404,7 +5414,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{(color & 0x00ffffff) | 0x19000000}
|
new int[]{(color & 0x00ffffff) | 0x19000000}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, null, maskDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, null, maskDrawable);
|
||||||
} else {
|
} else {
|
||||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, createRoundRectDrawable(corners, (color & 0x00ffffff) | 0x19000000));
|
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, createRoundRectDrawable(corners, (color & 0x00ffffff) | 0x19000000));
|
||||||
|
@ -5421,7 +5431,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{color}
|
new int[]{color}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, new ColorDrawable(backgroundColor), maskDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, new ColorDrawable(backgroundColor), maskDrawable);
|
||||||
} else {
|
} else {
|
||||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
||||||
|
@ -5454,7 +5464,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{color}
|
new int[]{color}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, new ColorDrawable(getColor(backgroundColor)), maskDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, new ColorDrawable(getColor(backgroundColor)), maskDrawable);
|
||||||
} else {
|
} else {
|
||||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
||||||
|
@ -5547,7 +5557,7 @@ public class Theme {
|
||||||
new int[][]{ StateSet.WILD_CARD },
|
new int[][]{ StateSet.WILD_CARD },
|
||||||
new int[]{ color }
|
new int[]{ color }
|
||||||
);
|
);
|
||||||
RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, null, maskDrawable);
|
RippleDrawable rippleDrawable = new BaseCell.RippleDrawableSafe(colorStateList, null, maskDrawable);
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
if (maskType == RIPPLE_MASK_CIRCLE_20DP) {
|
if (maskType == RIPPLE_MASK_CIRCLE_20DP) {
|
||||||
rippleDrawable.setRadius(radius <= 0 ? dp(20) : radius);
|
rippleDrawable.setRadius(radius <= 0 ? dp(20) : radius);
|
||||||
|
@ -5594,7 +5604,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{color}
|
new int[]{color}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, null, maskDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, null, maskDrawable);
|
||||||
} else {
|
} else {
|
||||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
||||||
|
@ -5760,7 +5770,7 @@ public class Theme {
|
||||||
maskDrawable = new ShapeDrawable(new RectShape());
|
maskDrawable = new ShapeDrawable(new RectShape());
|
||||||
((ShapeDrawable) maskDrawable).getPaint().setColor(0xffffffff);
|
((ShapeDrawable) maskDrawable).getPaint().setColor(0xffffffff);
|
||||||
}
|
}
|
||||||
return new RippleDrawable(
|
return new BaseCell.RippleDrawableSafe(
|
||||||
new ColorStateList(
|
new ColorStateList(
|
||||||
new int[][]{ StateSet.WILD_CARD },
|
new int[][]{ StateSet.WILD_CARD },
|
||||||
new int[]{ rippleColor }
|
new int[]{ rippleColor }
|
||||||
|
@ -5801,7 +5811,7 @@ public class Theme {
|
||||||
}
|
}
|
||||||
private static Drawable createCircle(Drawable background, int rippleColor, float radius) {
|
private static Drawable createCircle(Drawable background, int rippleColor, float radius) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
return new RippleDrawable(
|
return new BaseCell.RippleDrawableSafe(
|
||||||
new ColorStateList(
|
new ColorStateList(
|
||||||
new int[][]{ StateSet.WILD_CARD },
|
new int[][]{ StateSet.WILD_CARD },
|
||||||
new int[]{ rippleColor }
|
new int[]{ rippleColor }
|
||||||
|
@ -6004,7 +6014,6 @@ public class Theme {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Drawable createRadSelectorDrawable(int color, int topRad, int bottomRad) {
|
public static Drawable createRadSelectorDrawable(int color, int topRad, int bottomRad) {
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
maskPaint.setColor(0xffffffff);
|
maskPaint.setColor(0xffffffff);
|
||||||
|
@ -6013,7 +6022,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{color}
|
new int[]{color}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, null, maskDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, null, maskDrawable);
|
||||||
} else {
|
} else {
|
||||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
||||||
|
@ -6031,7 +6040,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{rippleColor}
|
new int[]{rippleColor}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, createRoundRectDrawable(dp(topRad), dp(bottomRad), color), maskDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, createRoundRectDrawable(dp(topRad), dp(bottomRad), color), maskDrawable);
|
||||||
} else {
|
} else {
|
||||||
Drawable backgroundDrawable = createRoundRectDrawable(dp(topRad), dp(bottomRad), color);
|
Drawable backgroundDrawable = createRoundRectDrawable(dp(topRad), dp(bottomRad), color);
|
||||||
Drawable pressedDrawable = new LayerDrawable(new Drawable[]{backgroundDrawable, createRoundRectDrawable(dp(topRad), dp(bottomRad), rippleColor)});
|
Drawable pressedDrawable = new LayerDrawable(new Drawable[]{backgroundDrawable, createRoundRectDrawable(dp(topRad), dp(bottomRad), rippleColor)});
|
||||||
|
@ -6051,7 +6060,7 @@ public class Theme {
|
||||||
new int[][]{StateSet.WILD_CARD},
|
new int[][]{StateSet.WILD_CARD},
|
||||||
new int[]{color}
|
new int[]{color}
|
||||||
);
|
);
|
||||||
return new RippleDrawable(colorStateList, null, maskDrawable);
|
return new BaseCell.RippleDrawableSafe(colorStateList, null, maskDrawable);
|
||||||
} else {
|
} else {
|
||||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(color));
|
||||||
|
@ -8283,7 +8292,7 @@ public class Theme {
|
||||||
public static void createCommonDialogResources(Context context) {
|
public static void createCommonDialogResources(Context context) {
|
||||||
if (dialogs_countTextPaint == null) {
|
if (dialogs_countTextPaint == null) {
|
||||||
dialogs_countTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_countTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_countTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_countTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
dialogs_countPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
dialogs_countPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_reactionsCountPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
dialogs_reactionsCountPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_onlineCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
dialogs_onlineCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
@ -8305,27 +8314,27 @@ public class Theme {
|
||||||
dialogs_messagePrintingPaint = new TextPaint[2];
|
dialogs_messagePrintingPaint = new TextPaint[2];
|
||||||
for (int a = 0; a < 2; a++) {
|
for (int a = 0; a < 2; a++) {
|
||||||
dialogs_namePaint[a] = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_namePaint[a] = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_namePaint[a].setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_namePaint[a].setTypeface(AndroidUtilities.bold());
|
||||||
dialogs_nameEncryptedPaint[a] = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_nameEncryptedPaint[a] = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_nameEncryptedPaint[a].setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_nameEncryptedPaint[a].setTypeface(AndroidUtilities.bold());
|
||||||
dialogs_messagePaint[a] = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_messagePaint[a] = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_messagePrintingPaint[a] = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_messagePrintingPaint[a] = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
}
|
}
|
||||||
dialogs_searchNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_searchNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_searchNamePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_searchNamePaint.setTypeface(AndroidUtilities.bold());
|
||||||
dialogs_searchNameEncryptedPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_searchNameEncryptedPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_searchNameEncryptedPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_searchNameEncryptedPaint.setTypeface(AndroidUtilities.bold());
|
||||||
dialogs_messageNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_messageNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_messageNamePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_messageNamePaint.setTypeface(AndroidUtilities.bold());
|
||||||
dialogs_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_archiveTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_archiveTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_archiveTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_archiveTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
dialogs_archiveTextPaintSmall = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_archiveTextPaintSmall = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_archiveTextPaintSmall.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_archiveTextPaintSmall.setTypeface(AndroidUtilities.bold());
|
||||||
dialogs_onlinePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_onlinePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_offlinePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_offlinePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_tagTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
dialogs_tagTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
dialogs_tagTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
dialogs_tagTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
|
|
||||||
dialogs_tabletSeletedPaint = new Paint();
|
dialogs_tabletSeletedPaint = new Paint();
|
||||||
dialogs_pinnedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
dialogs_pinnedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
@ -8466,16 +8475,16 @@ public class Theme {
|
||||||
chat_msgTextPaintTwoEmoji = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_msgTextPaintTwoEmoji = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_msgTextPaintThreeEmoji = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_msgTextPaintThreeEmoji = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_msgBotButtonPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_msgBotButtonPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_msgBotButtonPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_msgBotButtonPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_namePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_namePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_replyNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_replyNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_replyNamePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_replyNamePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_replyTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_replyTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_quoteTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_quoteTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_titleLabelTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_titleLabelTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_topicTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_topicTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_topicTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_topicTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_adminPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_adminPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
|
@ -8520,17 +8529,17 @@ public class Theme {
|
||||||
if (chat_infoPaint == null) {
|
if (chat_infoPaint == null) {
|
||||||
chat_infoPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_infoPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_infoBoldPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_infoBoldPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_infoBoldPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_infoBoldPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_stickerCommentCountPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_stickerCommentCountPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_stickerCommentCountPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_stickerCommentCountPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_docNamePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_docNamePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_docNamePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_docNamePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_docBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
chat_docBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_deleteProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
chat_deleteProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_deleteProgressPaint.setStyle(Paint.Style.STROKE);
|
chat_deleteProgressPaint.setStyle(Paint.Style.STROKE);
|
||||||
chat_deleteProgressPaint.setStrokeCap(Paint.Cap.ROUND);
|
chat_deleteProgressPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
chat_locationTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_locationTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_locationTitlePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_locationTitlePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_locationAddressPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_locationAddressPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_urlPaint = new Paint();
|
chat_urlPaint = new Paint();
|
||||||
chat_urlPaint.setPathEffect(LinkPath.getRoundedEffect());
|
chat_urlPaint.setPathEffect(LinkPath.getRoundedEffect());
|
||||||
|
@ -8549,31 +8558,31 @@ public class Theme {
|
||||||
chat_livePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_livePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_livePaint.setTypeface(Typeface.DEFAULT_BOLD);
|
chat_livePaint.setTypeface(Typeface.DEFAULT_BOLD);
|
||||||
chat_audioTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_audioTitlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_audioTitlePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_audioTitlePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_audioPerformerPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_audioPerformerPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_botButtonPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_botButtonPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_botButtonPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_botButtonPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_contactNamePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_contactNamePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_contactNamePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_contactNamePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_contactPhonePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_contactPhonePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_durationPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_durationPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_gamePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_gamePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_gamePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_gamePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_shipmentPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_shipmentPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_adminPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_adminPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_namePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_namePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_replyNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_replyNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_replyNamePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_replyNamePaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_replyTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_replyTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_topicTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_topicTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_topicTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_topicTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_titleLabelTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_titleLabelTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_commentTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
chat_commentTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
|
||||||
chat_instantViewPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_instantViewPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_instantViewPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_instantViewPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_instantViewRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
chat_instantViewRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_instantViewRectPaint.setStyle(Paint.Style.STROKE);
|
chat_instantViewRectPaint.setStyle(Paint.Style.STROKE);
|
||||||
chat_instantViewRectPaint.setStrokeCap(Paint.Cap.ROUND);
|
chat_instantViewRectPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
|
@ -8589,14 +8598,14 @@ public class Theme {
|
||||||
chat_statusRecordPaint.setStrokeCap(Paint.Cap.ROUND);
|
chat_statusRecordPaint.setStrokeCap(Paint.Cap.ROUND);
|
||||||
chat_actionTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_actionTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_actionTextPaint2 = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_actionTextPaint2 = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_actionTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_actionTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_unlockExtendedMediaTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_unlockExtendedMediaTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_unlockExtendedMediaTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_unlockExtendedMediaTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_actionBackgroundGradientDarkenPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
chat_actionBackgroundGradientDarkenPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_actionBackgroundGradientDarkenPaint.setColor(0x15000000);
|
chat_actionBackgroundGradientDarkenPaint.setColor(0x15000000);
|
||||||
chat_timeBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
chat_timeBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_contextResult_titleTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_contextResult_titleTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_contextResult_titleTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_contextResult_titleTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
chat_contextResult_descriptionTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
chat_contextResult_descriptionTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
chat_composeBackgroundPaint = new Paint();
|
chat_composeBackgroundPaint = new Paint();
|
||||||
chat_radialProgressPausedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
chat_radialProgressPausedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
@ -8880,7 +8889,7 @@ public class Theme {
|
||||||
chat_radialProgressPaint.setStrokeWidth(dp(3));
|
chat_radialProgressPaint.setStrokeWidth(dp(3));
|
||||||
chat_radialProgress2Paint.setStrokeWidth(dp(2.33f));
|
chat_radialProgress2Paint.setStrokeWidth(dp(2.33f));
|
||||||
chat_commentTextPaint.setTextSize(dp(14));
|
chat_commentTextPaint.setTextSize(dp(14));
|
||||||
chat_commentTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
chat_commentTextPaint.setTypeface(AndroidUtilities.bold());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -195,9 +195,11 @@ public class ThemeColors {
|
||||||
defaultColors[key_actionBarTabUnactiveText] = 0xffd5e8f7;
|
defaultColors[key_actionBarTabUnactiveText] = 0xffd5e8f7;
|
||||||
defaultColors[key_actionBarTabLine] = 0xffffffff;
|
defaultColors[key_actionBarTabLine] = 0xffffffff;
|
||||||
defaultColors[key_actionBarTabSelector] = 0xff406d94;
|
defaultColors[key_actionBarTabSelector] = 0xff406d94;
|
||||||
|
|
||||||
defaultColors[key_actionBarBrowser] = 0xffffffff;
|
defaultColors[key_actionBarBrowser] = 0xffffffff;
|
||||||
|
|
||||||
|
defaultColors[key_table_background] = 0xfff7f7f7;
|
||||||
|
defaultColors[key_table_border] = 0xffE0E0E0;
|
||||||
|
|
||||||
defaultColors[key_actionBarDefaultArchived] = 0xff6f7a87;
|
defaultColors[key_actionBarDefaultArchived] = 0xff6f7a87;
|
||||||
defaultColors[key_actionBarDefaultArchivedSelector] = 0xff5e6772;
|
defaultColors[key_actionBarDefaultArchivedSelector] = 0xff5e6772;
|
||||||
defaultColors[key_actionBarDefaultArchivedIcon] = 0xffffffff;
|
defaultColors[key_actionBarDefaultArchivedIcon] = 0xffffffff;
|
||||||
|
@ -768,6 +770,8 @@ public class ThemeColors {
|
||||||
defaultColors[key_premiumGradientBottomSheet3] = 0xffE794BE;
|
defaultColors[key_premiumGradientBottomSheet3] = 0xffE794BE;
|
||||||
defaultColors[key_topics_unreadCounter] = 0xff4ecc5e;
|
defaultColors[key_topics_unreadCounter] = 0xff4ecc5e;
|
||||||
defaultColors[key_topics_unreadCounterMuted] = 0xff8b8d8f;
|
defaultColors[key_topics_unreadCounterMuted] = 0xff8b8d8f;
|
||||||
|
defaultColors[key_starsGradient1] = 0xffFEC846;
|
||||||
|
defaultColors[key_starsGradient2] = 0xffEC920A;
|
||||||
|
|
||||||
defaultColors[key_stories_circle1] = 0xFF39DF3C;
|
defaultColors[key_stories_circle1] = 0xFF39DF3C;
|
||||||
defaultColors[key_stories_circle2] = 0xFF4DBBFF;
|
defaultColors[key_stories_circle2] = 0xFF4DBBFF;
|
||||||
|
@ -974,6 +978,8 @@ public class ThemeColors {
|
||||||
colorKeysMap.put(key_actionBarTabUnactiveText, "actionBarTabUnactiveText");
|
colorKeysMap.put(key_actionBarTabUnactiveText, "actionBarTabUnactiveText");
|
||||||
colorKeysMap.put(key_actionBarTabLine, "actionBarTabLine");
|
colorKeysMap.put(key_actionBarTabLine, "actionBarTabLine");
|
||||||
colorKeysMap.put(key_actionBarTabSelector, "actionBarTabSelector");
|
colorKeysMap.put(key_actionBarTabSelector, "actionBarTabSelector");
|
||||||
|
colorKeysMap.put(key_table_background, "table_background");
|
||||||
|
colorKeysMap.put(key_table_border, "table_border");
|
||||||
colorKeysMap.put(key_actionBarDefaultArchived, "actionBarDefaultArchived");
|
colorKeysMap.put(key_actionBarDefaultArchived, "actionBarDefaultArchived");
|
||||||
colorKeysMap.put(key_actionBarDefaultArchivedSelector, "actionBarDefaultArchivedSelector");
|
colorKeysMap.put(key_actionBarDefaultArchivedSelector, "actionBarDefaultArchivedSelector");
|
||||||
colorKeysMap.put(key_actionBarDefaultArchivedIcon, "actionBarDefaultArchivedIcon");
|
colorKeysMap.put(key_actionBarDefaultArchivedIcon, "actionBarDefaultArchivedIcon");
|
||||||
|
@ -1316,6 +1322,7 @@ public class ThemeColors {
|
||||||
colorKeysMap.put(key_chat_inBubbleLocationPlaceholder, "chat_inBubbleLocationPlaceholder");
|
colorKeysMap.put(key_chat_inBubbleLocationPlaceholder, "chat_inBubbleLocationPlaceholder");
|
||||||
colorKeysMap.put(key_chat_outBubbleLocationPlaceholder, "chat_outBubbleLocationPlaceholder");
|
colorKeysMap.put(key_chat_outBubbleLocationPlaceholder, "chat_outBubbleLocationPlaceholder");
|
||||||
colorKeysMap.put(key_chat_BlurAlpha, "chat_BlurAlpha");
|
colorKeysMap.put(key_chat_BlurAlpha, "chat_BlurAlpha");
|
||||||
|
colorKeysMap.put(key_chat_BlurAlphaSlow, "chat_BlurAlphaSlow");
|
||||||
colorKeysMap.put(key_chat_editMediaButton, "chat_editMediaButton");
|
colorKeysMap.put(key_chat_editMediaButton, "chat_editMediaButton");
|
||||||
|
|
||||||
colorKeysMap.put(key_voipgroup_listSelector, "voipgroup_listSelector");
|
colorKeysMap.put(key_voipgroup_listSelector, "voipgroup_listSelector");
|
||||||
|
|
|
@ -526,7 +526,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl
|
||||||
descriptionLines[a * 2].setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
descriptionLines[a * 2].setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||||
descriptionLines[a * 2].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
descriptionLines[a * 2].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
||||||
descriptionLines[a * 2].setText(String.format(LocaleController.isRTL ? ".%d" : "%d.", a + 1));
|
descriptionLines[a * 2].setText(String.format(LocaleController.isRTL ? ".%d" : "%d.", a + 1));
|
||||||
descriptionLines[a * 2].setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
descriptionLines[a * 2].setTypeface(AndroidUtilities.bold());
|
||||||
|
|
||||||
descriptionLines[a * 2 + 1] = new TextView(context);
|
descriptionLines[a * 2 + 1] = new TextView(context);
|
||||||
descriptionLines[a * 2 + 1].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
descriptionLines[a * 2 + 1].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||||
|
@ -601,7 +601,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl
|
||||||
buttonTextView.setGravity(Gravity.CENTER);
|
buttonTextView.setGravity(Gravity.CENTER);
|
||||||
buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
||||||
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
buttonTextView.setTypeface(AndroidUtilities.bold());
|
||||||
int buttonRadiusDp = currentType == ACTION_TYPE_SET_PASSCODE || currentType == ACTION_TYPE_CHANGE_PHONE_NUMBER || currentType == ACTION_TYPE_CHANNEL_CREATE ? 6 : 4;
|
int buttonRadiusDp = currentType == ACTION_TYPE_SET_PASSCODE || currentType == ACTION_TYPE_CHANGE_PHONE_NUMBER || currentType == ACTION_TYPE_CHANNEL_CREATE ? 6 : 4;
|
||||||
buttonTextView.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, buttonRadiusDp));
|
buttonTextView.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, buttonRadiusDp));
|
||||||
viewGroup.addView(buttonTextView);
|
viewGroup.addView(buttonTextView);
|
||||||
|
|
|
@ -603,7 +603,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
|
||||||
|
|
||||||
TextView textView = new TextView(mContext);
|
TextView textView = new TextView(mContext);
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader));
|
||||||
textView.setText(LocaleController.getString("RecentlyViewedHide", R.string.RecentlyViewedHide));
|
textView.setText(LocaleController.getString("RecentlyViewedHide", R.string.RecentlyViewedHide));
|
||||||
textView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL);
|
textView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL);
|
||||||
|
@ -734,7 +734,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VIEW_TYPE_FOLDER_UPDATE_HINT:
|
case VIEW_TYPE_FOLDER_UPDATE_HINT:
|
||||||
view = new DialogsHintCell(mContext);
|
view = new DialogsHintCell(mContext, null);
|
||||||
break;
|
break;
|
||||||
case VIEW_TYPE_STORIES: {
|
case VIEW_TYPE_STORIES: {
|
||||||
view = new View(mContext) {
|
view = new View(mContext) {
|
||||||
|
|
|
@ -719,7 +719,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
MessagesStorage.getInstance(currentAccount).getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
MessagesStorage.getInstance(currentAccount).getUsersInternal(usersToLoad, users);
|
||||||
for (int a = 0; a < users.size(); a++) {
|
for (int a = 0; a < users.size(); a++) {
|
||||||
TLRPC.User user = users.get(a);
|
TLRPC.User user = users.get(a);
|
||||||
RecentSearchObject recentSearchObject = hashMap.get(user.id);
|
RecentSearchObject recentSearchObject = hashMap.get(user.id);
|
||||||
|
|
|
@ -14,12 +14,14 @@ import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import org.telegram.messenger.HashtagSearchController;
|
||||||
import org.telegram.messenger.MediaDataController;
|
import org.telegram.messenger.MediaDataController;
|
||||||
import org.telegram.messenger.MessageObject;
|
import org.telegram.messenger.MessageObject;
|
||||||
import org.telegram.messenger.UserConfig;
|
import org.telegram.messenger.UserConfig;
|
||||||
|
import org.telegram.messenger.Utilities;
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Cells.DialogCell;
|
import org.telegram.ui.Cells.DialogCell;
|
||||||
import org.telegram.ui.Cells.LoadingCell;
|
import org.telegram.ui.Components.FlickerLoadingView;
|
||||||
import org.telegram.ui.Components.RecyclerListView;
|
import org.telegram.ui.Components.RecyclerListView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -31,20 +33,28 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||||
private HashSet<Integer> messageIds = new HashSet<>();
|
private HashSet<Integer> messageIds = new HashSet<>();
|
||||||
private ArrayList<MessageObject> searchResultMessages = new ArrayList<>();
|
private ArrayList<MessageObject> searchResultMessages = new ArrayList<>();
|
||||||
public int loadedCount;
|
public int loadedCount;
|
||||||
|
public int flickerCount;
|
||||||
|
|
||||||
private int currentAccount = UserConfig.selectedAccount;
|
private int currentAccount = UserConfig.selectedAccount;
|
||||||
private final Theme.ResourcesProvider resourcesProvider;
|
private final Theme.ResourcesProvider resourcesProvider;
|
||||||
|
private int searchType;
|
||||||
|
|
||||||
public MessagesSearchAdapter(Context context, Theme.ResourcesProvider resourcesProvider) {
|
private boolean isSavedMessages;
|
||||||
|
|
||||||
|
public MessagesSearchAdapter(Context context, Theme.ResourcesProvider resourcesProvider, int searchType, boolean isSavedMessages) {
|
||||||
this.resourcesProvider = resourcesProvider;
|
this.resourcesProvider = resourcesProvider;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
this.searchType = searchType;
|
||||||
|
this.isSavedMessages = isSavedMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyDataSetChanged() {
|
public void notifyDataSetChanged() {
|
||||||
|
final int oldItemsCount = getItemCount();
|
||||||
|
|
||||||
searchResultMessages.clear();
|
searchResultMessages.clear();
|
||||||
messageIds.clear();
|
messageIds.clear();
|
||||||
ArrayList<MessageObject> searchResults = MediaDataController.getInstance(currentAccount).getFoundMessageObjects();
|
ArrayList<MessageObject> searchResults = searchType == 0 ? MediaDataController.getInstance(currentAccount).getFoundMessageObjects() : HashtagSearchController.getInstance(currentAccount).getMessages(searchType);
|
||||||
for (int i = 0; i < searchResults.size(); ++i) {
|
for (int i = 0; i < searchResults.size(); ++i) {
|
||||||
MessageObject m = searchResults.get(i);
|
MessageObject m = searchResults.get(i);
|
||||||
if ((!m.hasValidGroupId() || m.isPrimaryGroupMessage) && !messageIds.contains(m.getId())) {
|
if ((!m.hasValidGroupId() || m.isPrimaryGroupMessage) && !messageIds.contains(m.getId())) {
|
||||||
|
@ -52,13 +62,32 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||||
messageIds.add(m.getId());
|
messageIds.add(m.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int oldLoadedCount = loadedCount;
|
||||||
|
final int oldFlickerCount = flickerCount;
|
||||||
|
|
||||||
loadedCount = searchResultMessages.size();
|
loadedCount = searchResultMessages.size();
|
||||||
super.notifyDataSetChanged();
|
if (searchType != 0) {
|
||||||
|
boolean hasMore = !HashtagSearchController.getInstance(currentAccount).isEndReached(searchType);
|
||||||
|
flickerCount = hasMore && loadedCount != 0 ? Utilities.clamp(HashtagSearchController.getInstance(currentAccount).getCount(searchType) - loadedCount, 3, 0) : 0;
|
||||||
|
} else {
|
||||||
|
boolean hasMore = !MediaDataController.getInstance(currentAccount).searchEndReached();
|
||||||
|
flickerCount = hasMore && loadedCount != 0 ? Utilities.clamp(MediaDataController.getInstance(currentAccount).getSearchCount() - loadedCount, 3, 0) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int newItemsCount = getItemCount();
|
||||||
|
|
||||||
|
if (oldItemsCount < newItemsCount) {
|
||||||
|
notifyItemRangeChanged(oldItemsCount - oldFlickerCount, oldFlickerCount);
|
||||||
|
notifyItemRangeInserted(oldItemsCount, newItemsCount - oldItemsCount);
|
||||||
|
} else {
|
||||||
|
super.notifyDataSetChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return searchResultMessages.size();
|
return searchResultMessages.size() + flickerCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getItem(int i) {
|
public Object getItem(int i) {
|
||||||
|
@ -68,11 +97,6 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||||
return searchResultMessages.get(i);
|
return searchResultMessages.get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getItemId(int i) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabled(RecyclerView.ViewHolder holder) {
|
public boolean isEnabled(RecyclerView.ViewHolder holder) {
|
||||||
return holder.getItemViewType() == 0;
|
return holder.getItemViewType() == 0;
|
||||||
|
@ -86,7 +110,10 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||||
view = new DialogCell(null, mContext, false, true, currentAccount, resourcesProvider);
|
view = new DialogCell(null, mContext, false, true, currentAccount, resourcesProvider);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
view = new LoadingCell(mContext);
|
FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext, resourcesProvider);
|
||||||
|
flickerLoadingView.setIsSingleCell(true);
|
||||||
|
flickerLoadingView.setViewType(FlickerLoadingView.DIALOG_CELL_TYPE);
|
||||||
|
view = flickerLoadingView;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
|
view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT));
|
||||||
|
@ -98,12 +125,14 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||||
if (holder.getItemViewType() == 0) {
|
if (holder.getItemViewType() == 0) {
|
||||||
DialogCell cell = (DialogCell) holder.itemView;
|
DialogCell cell = (DialogCell) holder.itemView;
|
||||||
cell.useSeparator = true;
|
cell.useSeparator = true;
|
||||||
cell.isSavedDialog = true;
|
|
||||||
MessageObject messageObject = (MessageObject) getItem(position);
|
MessageObject messageObject = (MessageObject) getItem(position);
|
||||||
int date;
|
int date;
|
||||||
boolean useMe = false;
|
|
||||||
long did;
|
long did;
|
||||||
if (messageObject.getDialogId() == UserConfig.getInstance(currentAccount).getClientUserId()) {
|
boolean useMe = false;
|
||||||
|
did = messageObject.getDialogId();
|
||||||
|
date = messageObject.messageOwner.date;
|
||||||
|
if (isSavedMessages) {
|
||||||
|
cell.isSavedDialog = true;
|
||||||
did = messageObject.getSavedDialogId();
|
did = messageObject.getSavedDialogId();
|
||||||
if (messageObject.messageOwner.fwd_from != null && (messageObject.messageOwner.fwd_from.date != 0 || messageObject.messageOwner.fwd_from.saved_date != 0)) {
|
if (messageObject.messageOwner.fwd_from != null && (messageObject.messageOwner.fwd_from.date != 0 || messageObject.messageOwner.fwd_from.saved_date != 0)) {
|
||||||
date = messageObject.messageOwner.fwd_from.date;
|
date = messageObject.messageOwner.fwd_from.date;
|
||||||
|
@ -114,8 +143,10 @@ public class MessagesSearchAdapter extends RecyclerListView.SelectionAdapter {
|
||||||
date = messageObject.messageOwner.date;
|
date = messageObject.messageOwner.date;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
did = messageObject.getDialogId();
|
if (messageObject.isOutOwner()) {
|
||||||
date = messageObject.messageOwner.date;
|
did = messageObject.getFromChatId();
|
||||||
|
}
|
||||||
|
useMe = true;
|
||||||
}
|
}
|
||||||
cell.setDialog(did, messageObject, date, useMe, false);
|
cell.setDialog(did, messageObject, date, useMe, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
package org.telegram.ui;
|
package org.telegram.ui;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
@ -36,6 +37,7 @@ import org.telegram.ui.Components.RecyclerListView;
|
||||||
import org.telegram.ui.Components.StickersAlert;
|
import org.telegram.ui.Components.StickersAlert;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ArchivedStickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
public class ArchivedStickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||||
|
@ -47,6 +49,7 @@ public class ArchivedStickersActivity extends BaseFragment implements Notificati
|
||||||
private LinearLayoutManager layoutManager;
|
private LinearLayoutManager layoutManager;
|
||||||
private RecyclerListView listView;
|
private RecyclerListView listView;
|
||||||
|
|
||||||
|
private HashSet<Long> loadedSets = new HashSet<>();
|
||||||
private ArrayList<TLRPC.StickerSetCovered> sets = new ArrayList<>();
|
private ArrayList<TLRPC.StickerSetCovered> sets = new ArrayList<>();
|
||||||
private boolean firstLoaded;
|
private boolean firstLoaded;
|
||||||
private boolean endReached;
|
private boolean endReached;
|
||||||
|
@ -221,8 +224,14 @@ public class ArchivedStickersActivity extends BaseFragment implements Notificati
|
||||||
|
|
||||||
private void processResponse(TLRPC.TL_messages_archivedStickers res) {
|
private void processResponse(TLRPC.TL_messages_archivedStickers res) {
|
||||||
if (!isInTransition) {
|
if (!isInTransition) {
|
||||||
sets.addAll(res.sets);
|
int added = 0;
|
||||||
endReached = res.sets.size() != 15;
|
for (TLRPC.StickerSetCovered s : res.sets) {
|
||||||
|
if (loadedSets.contains(s.set.id)) continue;
|
||||||
|
loadedSets.add(s.set.id);
|
||||||
|
sets.add(s);
|
||||||
|
added++;
|
||||||
|
}
|
||||||
|
endReached = added <= 0;
|
||||||
loadingStickers = false;
|
loadingStickers = false;
|
||||||
firstLoaded = true;
|
firstLoaded = true;
|
||||||
if (emptyView != null) {
|
if (emptyView != null) {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
package org.telegram.ui;
|
package org.telegram.ui;
|
||||||
|
|
||||||
|
import static org.telegram.messenger.LocaleController.getString;
|
||||||
import static org.telegram.messenger.MessageObject.POSITION_FLAG_BOTTOM;
|
import static org.telegram.messenger.MessageObject.POSITION_FLAG_BOTTOM;
|
||||||
import static org.telegram.messenger.MessageObject.POSITION_FLAG_LEFT;
|
import static org.telegram.messenger.MessageObject.POSITION_FLAG_LEFT;
|
||||||
import static org.telegram.messenger.MessageObject.POSITION_FLAG_RIGHT;
|
import static org.telegram.messenger.MessageObject.POSITION_FLAG_RIGHT;
|
||||||
|
@ -81,6 +82,7 @@ import android.view.animation.DecelerateInterpolator;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.webkit.CookieManager;
|
import android.webkit.CookieManager;
|
||||||
import android.webkit.JavascriptInterface;
|
import android.webkit.JavascriptInterface;
|
||||||
|
import android.webkit.RenderProcessGoneDetail;
|
||||||
import android.webkit.WebChromeClient;
|
import android.webkit.WebChromeClient;
|
||||||
import android.webkit.WebSettings;
|
import android.webkit.WebSettings;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
@ -138,6 +140,7 @@ import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.ActionBar;
|
import org.telegram.ui.ActionBar.ActionBar;
|
||||||
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||||
import org.telegram.ui.ActionBar.ActionBarPopupWindow;
|
import org.telegram.ui.ActionBar.ActionBarPopupWindow;
|
||||||
|
import org.telegram.ui.ActionBar.AlertDialog;
|
||||||
import org.telegram.ui.ActionBar.BackDrawable;
|
import org.telegram.ui.ActionBar.BackDrawable;
|
||||||
import org.telegram.ui.ActionBar.BaseFragment;
|
import org.telegram.ui.ActionBar.BaseFragment;
|
||||||
import org.telegram.ui.ActionBar.BottomSheet;
|
import org.telegram.ui.ActionBar.BottomSheet;
|
||||||
|
@ -1325,7 +1328,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
deleteView.setGravity(Gravity.CENTER_VERTICAL);
|
deleteView.setGravity(Gravity.CENTER_VERTICAL);
|
||||||
deleteView.setPadding(AndroidUtilities.dp(20), 0, AndroidUtilities.dp(20), 0);
|
deleteView.setPadding(AndroidUtilities.dp(20), 0, AndroidUtilities.dp(20), 0);
|
||||||
deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
deleteView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
|
||||||
deleteView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
deleteView.setTypeface(AndroidUtilities.bold());
|
||||||
deleteView.setText(LocaleController.getString("Copy", R.string.Copy).toUpperCase());
|
deleteView.setText(LocaleController.getString("Copy", R.string.Copy).toUpperCase());
|
||||||
deleteView.setOnClickListener(v -> {
|
deleteView.setOnClickListener(v -> {
|
||||||
if (pressedLinkOwnerLayout != null) {
|
if (pressedLinkOwnerLayout != null) {
|
||||||
|
@ -1728,7 +1731,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setText(LocaleController.getString("InstantViewReference", R.string.InstantViewReference));
|
textView.setText(LocaleController.getString("InstantViewReference", R.string.InstantViewReference));
|
||||||
textView.setGravity((adapter[0].isRtl ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
textView.setGravity((adapter[0].isRtl ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
|
||||||
textView.setTextColor(getTextColor());
|
textView.setTextColor(getTextColor());
|
||||||
|
@ -2391,7 +2394,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
paint.setTypeface(AndroidUtilities.getTypeface("fonts/rmono.ttf"));
|
paint.setTypeface(AndroidUtilities.getTypeface("fonts/rmono.ttf"));
|
||||||
} else {
|
} else {
|
||||||
if (parentBlock instanceof TLRPC.TL_pageBlockRelatedArticles) {
|
if (parentBlock instanceof TLRPC.TL_pageBlockRelatedArticles) {
|
||||||
paint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
paint.setTypeface(AndroidUtilities.bold());
|
||||||
} else if (selectedFont == 1 || parentBlock instanceof TLRPC.TL_pageBlockTitle || parentBlock instanceof TLRPC.TL_pageBlockKicker || parentBlock instanceof TLRPC.TL_pageBlockHeader || parentBlock instanceof TLRPC.TL_pageBlockSubtitle || parentBlock instanceof TLRPC.TL_pageBlockSubheader) {
|
} else if (selectedFont == 1 || parentBlock instanceof TLRPC.TL_pageBlockTitle || parentBlock instanceof TLRPC.TL_pageBlockKicker || parentBlock instanceof TLRPC.TL_pageBlockHeader || parentBlock instanceof TLRPC.TL_pageBlockSubtitle || parentBlock instanceof TLRPC.TL_pageBlockSubheader) {
|
||||||
if (parentBlock instanceof TLRPC.TL_pageBlockTitle || parentBlock instanceof TLRPC.TL_pageBlockHeader || parentBlock instanceof TLRPC.TL_pageBlockSubtitle || parentBlock instanceof TLRPC.TL_pageBlockSubheader) {
|
if (parentBlock instanceof TLRPC.TL_pageBlockTitle || parentBlock instanceof TLRPC.TL_pageBlockHeader || parentBlock instanceof TLRPC.TL_pageBlockSubtitle || parentBlock instanceof TLRPC.TL_pageBlockSubheader) {
|
||||||
paint.setTypeface(AndroidUtilities.getTypeface("fonts/mw_bold.ttf"));
|
paint.setTypeface(AndroidUtilities.getTypeface("fonts/mw_bold.ttf"));
|
||||||
|
@ -2410,7 +2413,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
if ((flags & TEXT_FLAG_MEDIUM) != 0 && (flags & TEXT_FLAG_ITALIC) != 0) {
|
if ((flags & TEXT_FLAG_MEDIUM) != 0 && (flags & TEXT_FLAG_ITALIC) != 0) {
|
||||||
paint.setTypeface(AndroidUtilities.getTypeface("fonts/rmediumitalic.ttf"));
|
paint.setTypeface(AndroidUtilities.getTypeface("fonts/rmediumitalic.ttf"));
|
||||||
} else if ((flags & TEXT_FLAG_MEDIUM) != 0) {
|
} else if ((flags & TEXT_FLAG_MEDIUM) != 0) {
|
||||||
paint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
paint.setTypeface(AndroidUtilities.bold());
|
||||||
} else if ((flags & TEXT_FLAG_ITALIC) != 0) {
|
} else if ((flags & TEXT_FLAG_ITALIC) != 0) {
|
||||||
paint.setTypeface(AndroidUtilities.getTypeface("fonts/ritalic.ttf"));
|
paint.setTypeface(AndroidUtilities.getTypeface("fonts/ritalic.ttf"));
|
||||||
}
|
}
|
||||||
|
@ -2487,10 +2490,10 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
} else if (parentBlock instanceof TLRPC.TL_pageBlockChannel) {
|
} else if (parentBlock instanceof TLRPC.TL_pageBlockChannel) {
|
||||||
if (channelNamePaint == null) {
|
if (channelNamePaint == null) {
|
||||||
channelNamePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
channelNamePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
channelNamePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
channelNamePaint.setTypeface(AndroidUtilities.bold());
|
||||||
|
|
||||||
channelNamePhotoPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
channelNamePhotoPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
channelNamePhotoPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
channelNamePhotoPaint.setTypeface(AndroidUtilities.bold());
|
||||||
}
|
}
|
||||||
channelNamePaint.setColor(getTextColor());
|
channelNamePaint.setColor(getTextColor());
|
||||||
channelNamePaint.setTextSize(AndroidUtilities.dp(15));
|
channelNamePaint.setTextSize(AndroidUtilities.dp(15));
|
||||||
|
@ -2504,7 +2507,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
if (plainText == pageBlockRelatedArticlesChild.parent.articles.get(pageBlockRelatedArticlesChild.num).title) {
|
if (plainText == pageBlockRelatedArticlesChild.parent.articles.get(pageBlockRelatedArticlesChild.num).title) {
|
||||||
if (relatedArticleHeaderPaint == null) {
|
if (relatedArticleHeaderPaint == null) {
|
||||||
relatedArticleHeaderPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
relatedArticleHeaderPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||||
relatedArticleHeaderPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
relatedArticleHeaderPaint.setTypeface(AndroidUtilities.bold());
|
||||||
}
|
}
|
||||||
relatedArticleHeaderPaint.setColor(getTextColor());
|
relatedArticleHeaderPaint.setColor(getTextColor());
|
||||||
relatedArticleHeaderPaint.setTextSize(AndroidUtilities.dp(15) + additionalSize);
|
relatedArticleHeaderPaint.setTextSize(AndroidUtilities.dp(15) + additionalSize);
|
||||||
|
@ -2901,7 +2904,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
ApplicationLoader.applicationContext.getSharedPreferences("articles", Activity.MODE_PRIVATE).edit().putInt("font_type", selectedFont).commit();
|
ApplicationLoader.applicationContext.getSharedPreferences("articles", Activity.MODE_PRIVATE).edit().putInt("font_type", selectedFont).commit();
|
||||||
Typeface typefaceNormal = selectedFont == 0 ? Typeface.DEFAULT : Typeface.SERIF;
|
Typeface typefaceNormal = selectedFont == 0 ? Typeface.DEFAULT : Typeface.SERIF;
|
||||||
Typeface typefaceItalic = selectedFont == 0 ? AndroidUtilities.getTypeface("fonts/ritalic.ttf") : Typeface.create("serif", Typeface.ITALIC);
|
Typeface typefaceItalic = selectedFont == 0 ? AndroidUtilities.getTypeface("fonts/ritalic.ttf") : Typeface.create("serif", Typeface.ITALIC);
|
||||||
Typeface typefaceBold = selectedFont == 0 ? AndroidUtilities.getTypeface("fonts/rmedium.ttf") : Typeface.create("serif", Typeface.BOLD);
|
Typeface typefaceBold = selectedFont == 0 ? AndroidUtilities.bold() : Typeface.create("serif", Typeface.BOLD);
|
||||||
Typeface typefaceBoldItalic = selectedFont == 0 ? AndroidUtilities.getTypeface("fonts/rmediumitalic.ttf") : Typeface.create("serif", Typeface.BOLD_ITALIC);
|
Typeface typefaceBoldItalic = selectedFont == 0 ? AndroidUtilities.getTypeface("fonts/rmediumitalic.ttf") : Typeface.create("serif", Typeface.BOLD_ITALIC);
|
||||||
|
|
||||||
for (int a = 0; a < quoteTextPaints.size(); a++) {
|
for (int a = 0; a < quoteTextPaints.size(); a++) {
|
||||||
|
@ -3371,7 +3374,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
titleTextView = new SimpleTextView(activity);
|
titleTextView = new SimpleTextView(activity);
|
||||||
titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
|
titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
|
||||||
titleTextView.setTextSize(20);
|
titleTextView.setTextSize(20);
|
||||||
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
titleTextView.setTypeface(AndroidUtilities.bold());
|
||||||
titleTextView.setTextColor(0xffb3b3b3);
|
titleTextView.setTextColor(0xffb3b3b3);
|
||||||
titleTextView.setPivotX(0.0f);
|
titleTextView.setPivotX(0.0f);
|
||||||
titleTextView.setPivotY(AndroidUtilities.dp(28));
|
titleTextView.setPivotY(AndroidUtilities.dp(28));
|
||||||
|
@ -3710,7 +3713,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
searchCountText = new SimpleTextView(parentActivity);
|
searchCountText = new SimpleTextView(parentActivity);
|
||||||
searchCountText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
searchCountText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||||
searchCountText.setTextSize(15);
|
searchCountText.setTextSize(15);
|
||||||
searchCountText.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
searchCountText.setTypeface(AndroidUtilities.bold());
|
||||||
searchCountText.setGravity(Gravity.LEFT);
|
searchCountText.setGravity(Gravity.LEFT);
|
||||||
searchPanel.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 18, 0, 108, 0));
|
searchPanel.addView(searchCountText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 18, 0, 108, 0));
|
||||||
|
|
||||||
|
@ -6796,7 +6799,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
stringBuilder = new SpannableStringBuilder(author);
|
stringBuilder = new SpannableStringBuilder(author);
|
||||||
}
|
}
|
||||||
if (!TextUtils.isEmpty(author)) {
|
if (!TextUtils.isEmpty(author)) {
|
||||||
TypefaceSpan span = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
TypefaceSpan span = new TypefaceSpan(AndroidUtilities.bold());
|
||||||
stringBuilder.setSpan(span, 0, author.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
stringBuilder.setSpan(span, 0, author.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||||
}
|
}
|
||||||
CharSequence stringFinal = TextUtils.ellipsize(stringBuilder, Theme.chat_audioTitlePaint, w, TextUtils.TruncateAt.END);
|
CharSequence stringFinal = TextUtils.ellipsize(stringBuilder, Theme.chat_audioTitlePaint, w, TextUtils.TruncateAt.END);
|
||||||
|
@ -7520,6 +7523,19 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
});
|
});
|
||||||
|
|
||||||
webView.setWebViewClient(new WebViewClient() {
|
webView.setWebViewClient(new WebViewClient() {
|
||||||
|
@Override
|
||||||
|
public boolean onRenderProcessGone(WebView view, RenderProcessGoneDetail detail) {
|
||||||
|
if (LaunchActivity.instance != null && LaunchActivity.instance.isFinishing()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
new AlertDialog.Builder(getContext(), null)
|
||||||
|
.setTitle(getString(R.string.ChromeCrashTitle))
|
||||||
|
.setMessage(AndroidUtilities.replaceSingleTag(getString(R.string.ChromeCrashMessage), () -> Browser.openUrl(getContext(), "https://play.google.com/store/apps/details?id=com.google.android.webview")))
|
||||||
|
.setPositiveButton(getString(R.string.OK), null)
|
||||||
|
.show();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoadResource(WebView view, String url) {
|
public void onLoadResource(WebView view, String url) {
|
||||||
super.onLoadResource(view, url);
|
super.onLoadResource(view, url);
|
||||||
|
@ -10728,7 +10744,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
|
|
||||||
textView = new TextView(context);
|
textView = new TextView(context);
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setText(LocaleController.getString("ChannelJoin", R.string.ChannelJoin));
|
textView.setText(LocaleController.getString("ChannelJoin", R.string.ChannelJoin));
|
||||||
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
|
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
|
||||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 39, Gravity.RIGHT | Gravity.TOP));
|
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 39, Gravity.RIGHT | Gravity.TOP));
|
||||||
|
@ -11691,7 +11707,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
object.parentView = listView[0];
|
object.parentView = listView[0];
|
||||||
object.imageReceiver = imageReceiver;
|
object.imageReceiver = imageReceiver;
|
||||||
object.thumb = imageReceiver.getBitmapSafe();
|
object.thumb = imageReceiver.getBitmapSafe();
|
||||||
object.radius = imageReceiver.getRoundRadius();
|
object.radius = imageReceiver.getRoundRadius(true);
|
||||||
object.clipTopAddition = currentHeaderHeight;
|
object.clipTopAddition = currentHeaderHeight;
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,63 @@
|
||||||
package org.telegram.ui;
|
package org.telegram.ui;
|
||||||
|
|
||||||
|
import static org.telegram.messenger.AndroidUtilities.dp;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.HapticFeedbackConstants;
|
import android.view.Gravity;
|
||||||
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.WindowInsets;
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
|
||||||
import android.view.animation.AnimationUtils;
|
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
|
import android.view.animation.OvershootInterpolator;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.core.math.MathUtils;
|
||||||
import androidx.core.util.Consumer;
|
import androidx.core.util.Consumer;
|
||||||
import androidx.core.util.Preconditions;
|
|
||||||
|
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.FileLoader;
|
import org.telegram.messenger.FileLoader;
|
||||||
import org.telegram.messenger.ImageLoader;
|
import org.telegram.messenger.ImageLoader;
|
||||||
import org.telegram.messenger.ImageLocation;
|
import org.telegram.messenger.ImageLocation;
|
||||||
import org.telegram.messenger.ImageReceiver;
|
|
||||||
import org.telegram.messenger.LocaleController;
|
import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.MessagesController;
|
import org.telegram.messenger.MessagesController;
|
||||||
import org.telegram.messenger.NotificationCenter;
|
import org.telegram.messenger.NotificationCenter;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.UserConfig;
|
import org.telegram.messenger.UserConfig;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.BottomSheet;
|
import org.telegram.ui.ActionBar.ActionBarMenuItem;
|
||||||
|
import org.telegram.ui.ActionBar.ActionBarMenuSubItem;
|
||||||
|
import org.telegram.ui.ActionBar.ActionBarPopupWindow;
|
||||||
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.AnimatedFileDrawable;
|
import org.telegram.ui.Components.AnimatedFileDrawable;
|
||||||
|
import org.telegram.ui.Components.BackupImageView;
|
||||||
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||||
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
import org.telegram.ui.Components.MediaActionDrawable;
|
import org.telegram.ui.Components.MediaActionDrawable;
|
||||||
import org.telegram.ui.Components.RadialProgress2;
|
import org.telegram.ui.Components.RadialProgress2;
|
||||||
|
import org.telegram.ui.Stories.RoundRectOutlineProvider;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class AvatarPreviewer {
|
public class AvatarPreviewer {
|
||||||
|
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
private static AvatarPreviewer INSTANCE;
|
private static AvatarPreviewer INSTANCE;
|
||||||
|
|
||||||
public static AvatarPreviewer getInstance() {
|
public static AvatarPreviewer getInstance() {
|
||||||
|
@ -63,28 +76,35 @@ public class AvatarPreviewer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ViewGroup view;
|
private ViewGroup view;
|
||||||
private Context context;
|
|
||||||
private WindowManager windowManager;
|
private WindowManager windowManager;
|
||||||
private Callback callback;
|
|
||||||
private Layout layout;
|
private Layout layout;
|
||||||
private boolean visible;
|
private boolean visible;
|
||||||
|
|
||||||
public void show(ViewGroup parentContainer, Data data, Callback callback) {
|
public void show(ViewGroup parentContainer, Theme.ResourcesProvider resourcesProvider, Data data, Callback callback) {
|
||||||
Preconditions.checkNotNull(parentContainer);
|
Objects.requireNonNull(parentContainer);
|
||||||
Preconditions.checkNotNull(data);
|
Objects.requireNonNull(data);
|
||||||
Preconditions.checkNotNull(callback);
|
Objects.requireNonNull(callback);
|
||||||
|
|
||||||
final Context context = parentContainer.getContext();
|
final Context context = parentContainer.getContext();
|
||||||
|
|
||||||
if (this.view != parentContainer) {
|
if (this.view != parentContainer) {
|
||||||
close();
|
close();
|
||||||
this.view = parentContainer;
|
this.view = parentContainer;
|
||||||
this.context = context;
|
|
||||||
this.windowManager = ContextCompat.getSystemService(context, WindowManager.class);
|
this.windowManager = ContextCompat.getSystemService(context, WindowManager.class);
|
||||||
this.layout = new Layout(context, callback) {
|
this.layout = new Layout(context, resourcesProvider, callback) {
|
||||||
@Override
|
@Override
|
||||||
protected void onHide() {
|
protected void onHideFinish() {
|
||||||
close();
|
if (visible) {
|
||||||
|
visible = false;
|
||||||
|
if (layout.getParent() != null) {
|
||||||
|
windowManager.removeView(layout);
|
||||||
|
}
|
||||||
|
layout.recycle();
|
||||||
|
layout = null;
|
||||||
|
view.requestDisallowInterceptTouchEvent(false);
|
||||||
|
view = null;
|
||||||
|
windowManager = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -97,12 +117,11 @@ public class AvatarPreviewer {
|
||||||
}
|
}
|
||||||
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
|
final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
WindowManager.LayoutParams.LAST_APPLICATION_WINDOW,
|
WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
|
||||||
0, PixelFormat.TRANSLUCENT
|
0, PixelFormat.TRANSLUCENT
|
||||||
);
|
);
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
layoutParams.flags = WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS |
|
layoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
|
||||||
WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR |
|
|
||||||
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
|
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
|
||||||
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||||
}
|
}
|
||||||
|
@ -114,17 +133,7 @@ public class AvatarPreviewer {
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
visible = false;
|
this.layout.setShowing(false);
|
||||||
if (layout.getParent() != null) {
|
|
||||||
windowManager.removeView(layout);
|
|
||||||
}
|
|
||||||
layout.recycle();
|
|
||||||
layout = null;
|
|
||||||
view.requestDisallowInterceptTouchEvent(false);
|
|
||||||
view = null;
|
|
||||||
context = null;
|
|
||||||
windowManager = null;
|
|
||||||
callback = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,12 +151,13 @@ public class AvatarPreviewer {
|
||||||
void onMenuClick(MenuItem item);
|
void onMenuClick(MenuItem item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static enum MenuItem {
|
public enum MenuItem {
|
||||||
OPEN_PROFILE("OpenProfile", R.string.OpenProfile, R.drawable.msg_openprofile),
|
OPEN_PROFILE("OpenProfile", R.string.OpenProfile, R.drawable.msg_openprofile),
|
||||||
OPEN_CHANNEL("OpenChannel2", R.string.OpenChannel2, R.drawable.msg_channel),
|
OPEN_CHANNEL("OpenChannel2", R.string.OpenChannel2, R.drawable.msg_channel),
|
||||||
OPEN_GROUP("OpenGroup2", R.string.OpenGroup2, R.drawable.msg_discussion),
|
OPEN_GROUP("OpenGroup2", R.string.OpenGroup2, R.drawable.msg_discussion),
|
||||||
SEND_MESSAGE("SendMessage", R.string.SendMessage, R.drawable.msg_discussion),
|
SEND_MESSAGE("SendMessage", R.string.SendMessage, R.drawable.msg_discussion),
|
||||||
MENTION("Mention", R.string.Mention, R.drawable.msg_mention);
|
MENTION("Mention", R.string.Mention, R.drawable.msg_mention),
|
||||||
|
SEARCH_MESSAGES("AvatarPreviewSearchMessages", R.string.AvatarPreviewSearchMessages, R.drawable.msg_search);
|
||||||
|
|
||||||
private final String labelKey;
|
private final String labelKey;
|
||||||
private final int labelResId;
|
private final int labelResId;
|
||||||
|
@ -166,17 +176,22 @@ public class AvatarPreviewer {
|
||||||
final ImageLocation imageLocation = ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_BIG);
|
final ImageLocation imageLocation = ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_BIG);
|
||||||
final ImageLocation thumbImageLocation = ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_SMALL);
|
final ImageLocation thumbImageLocation = ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_SMALL);
|
||||||
final String thumbFilter = thumbImageLocation != null && thumbImageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null;
|
final String thumbFilter = thumbImageLocation != null && thumbImageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null;
|
||||||
return new Data(imageLocation, thumbImageLocation, null, null, thumbFilter, null, null, user, menuItems, new UserInfoLoadTask(user, classGuid));
|
final BitmapDrawable thumb = user != null && user.photo != null ? user.photo.strippedBitmap : null;
|
||||||
|
return new Data(imageLocation, thumbImageLocation, null, null, thumbFilter, null, null, thumb, user, menuItems, new UserInfoLoadTask(user, classGuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Data of(TLRPC.UserFull userFull, MenuItem... menuItems) {
|
public static Data of(TLRPC.User user, TLRPC.UserFull userFull, MenuItem... menuItems) {
|
||||||
final ImageLocation imageLocation = ImageLocation.getForUserOrChat(userFull.user, ImageLocation.TYPE_BIG);
|
ImageLocation imageLocation = ImageLocation.getForUserOrChat(userFull.user, ImageLocation.TYPE_BIG);
|
||||||
|
if (imageLocation == null && userFull.profile_photo != null) {
|
||||||
|
imageLocation = ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(userFull.profile_photo.sizes, 500), userFull.profile_photo);
|
||||||
|
}
|
||||||
final ImageLocation thumbImageLocation = ImageLocation.getForUserOrChat(userFull.user, ImageLocation.TYPE_SMALL);
|
final ImageLocation thumbImageLocation = ImageLocation.getForUserOrChat(userFull.user, ImageLocation.TYPE_SMALL);
|
||||||
final String thumbFilter = thumbImageLocation != null && thumbImageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null;
|
final String thumbFilter = thumbImageLocation != null && thumbImageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null;
|
||||||
final ImageLocation videoLocation;
|
final ImageLocation videoLocation;
|
||||||
final String videoFileName;
|
final String videoFileName;
|
||||||
|
final BitmapDrawable thumb = user != null && user.photo != null ? user.photo.strippedBitmap : null;
|
||||||
if (userFull.profile_photo != null && !userFull.profile_photo.video_sizes.isEmpty()) {
|
if (userFull.profile_photo != null && !userFull.profile_photo.video_sizes.isEmpty()) {
|
||||||
final TLRPC.VideoSize videoSize = userFull.profile_photo.video_sizes.get(0);
|
final TLRPC.VideoSize videoSize = FileLoader.getClosestVideoSizeWithSize(userFull.profile_photo.video_sizes, 1000);
|
||||||
videoLocation = ImageLocation.getForPhoto(videoSize, userFull.profile_photo);
|
videoLocation = ImageLocation.getForPhoto(videoSize, userFull.profile_photo);
|
||||||
videoFileName = FileLoader.getAttachFileName(videoSize);
|
videoFileName = FileLoader.getAttachFileName(videoSize);
|
||||||
} else {
|
} else {
|
||||||
|
@ -184,14 +199,15 @@ public class AvatarPreviewer {
|
||||||
videoFileName = null;
|
videoFileName = null;
|
||||||
}
|
}
|
||||||
final String videoFilter = videoLocation != null && videoLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION ? ImageLoader.AUTOPLAY_FILTER : null;
|
final String videoFilter = videoLocation != null && videoLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION ? ImageLoader.AUTOPLAY_FILTER : null;
|
||||||
return new Data(imageLocation, thumbImageLocation, videoLocation, null, thumbFilter, videoFilter, videoFileName, userFull.user, menuItems, null);
|
return new Data(imageLocation, thumbImageLocation, videoLocation, null, thumbFilter, videoFilter, videoFileName, thumb, userFull.user, menuItems, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Data of(TLRPC.Chat chat, int classGuid, MenuItem... menuItems) {
|
public static Data of(TLRPC.Chat chat, int classGuid, MenuItem... menuItems) {
|
||||||
final ImageLocation imageLocation = ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_BIG);
|
final ImageLocation imageLocation = ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_BIG);
|
||||||
final ImageLocation thumbImageLocation = ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_SMALL);
|
final ImageLocation thumbImageLocation = ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_SMALL);
|
||||||
final String thumbFilter = thumbImageLocation != null && thumbImageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null;
|
final String thumbFilter = thumbImageLocation != null && thumbImageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null;
|
||||||
return new Data(imageLocation, thumbImageLocation, null, null, thumbFilter, null, null, chat, menuItems, new ChatInfoLoadTask(chat, classGuid));
|
final BitmapDrawable thumb = chat != null && chat.photo != null ? chat.photo.strippedBitmap : null;
|
||||||
|
return new Data(imageLocation, thumbImageLocation, null, null, thumbFilter, null, null, thumb, chat, menuItems, new ChatInfoLoadTask(chat, classGuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Data of(TLRPC.Chat chat, TLRPC.ChatFull chatFull, MenuItem... menuItems) {
|
public static Data of(TLRPC.Chat chat, TLRPC.ChatFull chatFull, MenuItem... menuItems) {
|
||||||
|
@ -200,8 +216,9 @@ public class AvatarPreviewer {
|
||||||
final String thumbFilter = thumbImageLocation != null && thumbImageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null;
|
final String thumbFilter = thumbImageLocation != null && thumbImageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null;
|
||||||
final ImageLocation videoLocation;
|
final ImageLocation videoLocation;
|
||||||
final String videoFileName;
|
final String videoFileName;
|
||||||
|
final BitmapDrawable thumb = chat != null && chat.photo != null ? chat.photo.strippedBitmap : null;
|
||||||
if (chatFull.chat_photo != null && !chatFull.chat_photo.video_sizes.isEmpty()) {
|
if (chatFull.chat_photo != null && !chatFull.chat_photo.video_sizes.isEmpty()) {
|
||||||
final TLRPC.VideoSize videoSize = chatFull.chat_photo.video_sizes.get(0);
|
final TLRPC.VideoSize videoSize = FileLoader.getClosestVideoSizeWithSize(chatFull.chat_photo.video_sizes, 1000);
|
||||||
videoLocation = ImageLocation.getForPhoto(videoSize, chatFull.chat_photo);
|
videoLocation = ImageLocation.getForPhoto(videoSize, chatFull.chat_photo);
|
||||||
videoFileName = FileLoader.getAttachFileName(videoSize);
|
videoFileName = FileLoader.getAttachFileName(videoSize);
|
||||||
} else {
|
} else {
|
||||||
|
@ -209,7 +226,7 @@ public class AvatarPreviewer {
|
||||||
videoFileName = null;
|
videoFileName = null;
|
||||||
}
|
}
|
||||||
final String videoFilter = videoLocation != null && videoLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION ? ImageLoader.AUTOPLAY_FILTER : null;
|
final String videoFilter = videoLocation != null && videoLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION ? ImageLoader.AUTOPLAY_FILTER : null;
|
||||||
return new Data(imageLocation, thumbImageLocation, videoLocation, null, thumbFilter, videoFilter, videoFileName, chat, menuItems, null);
|
return new Data(imageLocation, thumbImageLocation, videoLocation, null, thumbFilter, videoFilter, videoFileName, thumb, chat, menuItems, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ImageLocation imageLocation;
|
private final ImageLocation imageLocation;
|
||||||
|
@ -219,11 +236,12 @@ public class AvatarPreviewer {
|
||||||
private final String thumbImageFilter;
|
private final String thumbImageFilter;
|
||||||
private final String videoFilter;
|
private final String videoFilter;
|
||||||
private final String videoFileName;
|
private final String videoFileName;
|
||||||
|
private final BitmapDrawable thumb;
|
||||||
private final Object parentObject;
|
private final Object parentObject;
|
||||||
private final MenuItem[] menuItems;
|
private final MenuItem[] menuItems;
|
||||||
private final InfoLoadTask<?, ?> infoLoadTask;
|
private final InfoLoadTask<?, ?> infoLoadTask;
|
||||||
|
|
||||||
private Data(ImageLocation imageLocation, ImageLocation thumbImageLocation, ImageLocation videoLocation, String imageFilter, String thumbImageFilter, String videoFilter, String videoFileName, Object parentObject, MenuItem[] menuItems, InfoLoadTask<?, ?> infoLoadTask) {
|
private Data(ImageLocation imageLocation, ImageLocation thumbImageLocation, ImageLocation videoLocation, String imageFilter, String thumbImageFilter, String videoFilter, String videoFileName, BitmapDrawable thumb, Object parentObject, MenuItem[] menuItems, InfoLoadTask<?, ?> infoLoadTask) {
|
||||||
this.imageLocation = imageLocation;
|
this.imageLocation = imageLocation;
|
||||||
this.thumbImageLocation = thumbImageLocation;
|
this.thumbImageLocation = thumbImageLocation;
|
||||||
this.videoLocation = videoLocation;
|
this.videoLocation = videoLocation;
|
||||||
|
@ -231,6 +249,7 @@ public class AvatarPreviewer {
|
||||||
this.thumbImageFilter = thumbImageFilter;
|
this.thumbImageFilter = thumbImageFilter;
|
||||||
this.videoFilter = videoFilter;
|
this.videoFilter = videoFilter;
|
||||||
this.videoFileName = videoFileName;
|
this.videoFileName = videoFileName;
|
||||||
|
this.thumb = thumb;
|
||||||
this.parentObject = parentObject;
|
this.parentObject = parentObject;
|
||||||
this.menuItems = menuItems;
|
this.menuItems = menuItems;
|
||||||
this.infoLoadTask = infoLoadTask;
|
this.infoLoadTask = infoLoadTask;
|
||||||
|
@ -334,56 +353,81 @@ public class AvatarPreviewer {
|
||||||
|
|
||||||
private static abstract class Layout extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
|
private static abstract class Layout extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
|
||||||
|
|
||||||
private static final float ANIM_DURATION = 150f;
|
private final Interpolator openInterpolator = new OvershootInterpolator(1.02f);
|
||||||
|
private final FrameLayout container;
|
||||||
private final int radialProgressSize = AndroidUtilities.dp(64f);
|
private final AvatarView avatarView;
|
||||||
private final int[] coords = new int[2];
|
private final ActionBarPopupWindow.ActionBarPopupWindowLayout menu;
|
||||||
private final Rect rect = new Rect();
|
|
||||||
|
|
||||||
private final Interpolator interpolator = new AccelerateDecelerateInterpolator();
|
|
||||||
private final ColorDrawable backgroundDrawable = new ColorDrawable(0x71000000);
|
|
||||||
private final ImageReceiver imageReceiver = new ImageReceiver();
|
|
||||||
private final RadialProgress2 radialProgress;
|
|
||||||
private final Drawable arrowDrawable;
|
|
||||||
private final Callback callback;
|
private final Callback callback;
|
||||||
|
private final Theme.ResourcesProvider resourcesProvider;
|
||||||
|
|
||||||
private float progress;
|
private AnimatorSet openAnimator;
|
||||||
private boolean showing;
|
private boolean showing;
|
||||||
private long lastUpdateTime;
|
|
||||||
private MenuItem[] menuItems;
|
private MenuItem[] menuItems;
|
||||||
private WindowInsets insets;
|
private View blurView;
|
||||||
private BottomSheet visibleSheet;
|
private boolean preparingBlur;
|
||||||
private ValueAnimator moveAnimator;
|
|
||||||
private float moveProgress; // [-1; 0]
|
|
||||||
private float downY = -1;
|
|
||||||
|
|
||||||
private String videoFileName;
|
private String videoFileName;
|
||||||
private InfoLoadTask<?, ?> infoLoadTask;
|
private InfoLoadTask<?, ?> infoLoadTask;
|
||||||
private ValueAnimator progressHideAnimator;
|
|
||||||
private ValueAnimator progressShowAnimator;
|
|
||||||
private boolean showProgress;
|
|
||||||
private boolean recycled;
|
private boolean recycled;
|
||||||
|
|
||||||
public Layout(@NonNull Context context, Callback callback) {
|
public Layout(@NonNull Context context, Theme.ResourcesProvider resourcesProvider, Callback callback) {
|
||||||
super(context);
|
super(context);
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
|
this.resourcesProvider = resourcesProvider;
|
||||||
setWillNotDraw(false);
|
setWillNotDraw(false);
|
||||||
setFitsSystemWindows(true);
|
|
||||||
imageReceiver.setAspectFit(true);
|
blurView = new View(context);
|
||||||
imageReceiver.setInvalidateAll(true);
|
blurView.setOnClickListener(v -> setShowing(false));
|
||||||
imageReceiver.setRoundRadius(AndroidUtilities.dp(6));
|
addView(blurView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||||
imageReceiver.setParentView(this);
|
|
||||||
radialProgress = new RadialProgress2(this);
|
container = new FrameLayout(context) {
|
||||||
radialProgress.setOverrideAlpha(0.0f);
|
@Override
|
||||||
radialProgress.setIcon(MediaActionDrawable.ICON_EMPTY, false, false);
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
radialProgress.setColors(0x42000000, 0x42000000, Color.WHITE, Color.WHITE);
|
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
|
||||||
arrowDrawable = ContextCompat.getDrawable(context, R.drawable.preview_arrow);
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
|
int width = right - left - getPaddingLeft() - getPaddingRight();
|
||||||
|
int height = bottom - top - getPaddingTop() - getPaddingBottom();
|
||||||
|
|
||||||
|
int maxAvatarSize = Math.min(width, height) - dp(16);
|
||||||
|
int minAvatarSize = Math.min(dp(60), maxAvatarSize);
|
||||||
|
|
||||||
|
int maxMenuHeight = height - minAvatarSize - dp(16 + 24);
|
||||||
|
menu.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(maxMenuHeight, MeasureSpec.AT_MOST));
|
||||||
|
|
||||||
|
int avatarSize = MathUtils.clamp(height - menu.getMeasuredHeight() - dp(16 + 24), minAvatarSize, maxAvatarSize);
|
||||||
|
avatarView.measure(MeasureSpec.makeMeasureSpec(avatarSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(avatarSize, MeasureSpec.EXACTLY));
|
||||||
|
|
||||||
|
int verticalOffset = (height - avatarSize - menu.getMeasuredHeight() - dp(16 + 24)) / 2;
|
||||||
|
|
||||||
|
FrameLayout.LayoutParams avatarLayoutParams = (LayoutParams) avatarView.getLayoutParams();
|
||||||
|
FrameLayout.LayoutParams menuLayoutParams = (LayoutParams) menu.getLayoutParams();
|
||||||
|
|
||||||
|
avatarLayoutParams.topMargin = verticalOffset + dp(8);
|
||||||
|
menuLayoutParams.topMargin = verticalOffset + dp(8) + avatarSize;
|
||||||
|
|
||||||
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
container.setFitsSystemWindows(true);
|
||||||
|
addView(container, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||||
|
|
||||||
|
avatarView = new AvatarView(context, resourcesProvider);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
avatarView.setElevation(dp(4));
|
||||||
|
avatarView.setClipToOutline(true);
|
||||||
|
}
|
||||||
|
container.addView(avatarView, LayoutHelper.createFrame(0, 0, Gravity.CENTER_HORIZONTAL));
|
||||||
|
|
||||||
|
menu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, R.drawable.popup_fixed_alert, resourcesProvider, 0);
|
||||||
|
container.addView(menu, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAttachedToWindow() {
|
protected void onAttachedToWindow() {
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
imageReceiver.onAttachedToWindow();
|
|
||||||
NotificationCenter.getInstance(UserConfig.selectedAccount).addObserver(this, NotificationCenter.fileLoaded);
|
NotificationCenter.getInstance(UserConfig.selectedAccount).addObserver(this, NotificationCenter.fileLoaded);
|
||||||
NotificationCenter.getInstance(UserConfig.selectedAccount).addObserver(this, NotificationCenter.fileLoadProgressChanged);
|
NotificationCenter.getInstance(UserConfig.selectedAccount).addObserver(this, NotificationCenter.fileLoadProgressChanged);
|
||||||
}
|
}
|
||||||
|
@ -391,186 +435,241 @@ public class AvatarPreviewer {
|
||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow() {
|
protected void onDetachedFromWindow() {
|
||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
imageReceiver.onDetachedFromWindow();
|
|
||||||
NotificationCenter.getInstance(UserConfig.selectedAccount).removeObserver(this, NotificationCenter.fileLoaded);
|
NotificationCenter.getInstance(UserConfig.selectedAccount).removeObserver(this, NotificationCenter.fileLoaded);
|
||||||
NotificationCenter.getInstance(UserConfig.selectedAccount).removeObserver(this, NotificationCenter.fileLoadProgressChanged);
|
NotificationCenter.getInstance(UserConfig.selectedAccount).removeObserver(this, NotificationCenter.fileLoadProgressChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void didReceivedNotification(int id, int account, Object... args) {
|
public void didReceivedNotification(int id, int account, Object... args) {
|
||||||
if (!showProgress || TextUtils.isEmpty(videoFileName)) {
|
if (!avatarView.getShowProgress() || TextUtils.isEmpty(videoFileName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (id == NotificationCenter.fileLoaded) {
|
if (id == NotificationCenter.fileLoaded) {
|
||||||
final String fileName = (String) args[0];
|
final String fileName = (String) args[0];
|
||||||
if (TextUtils.equals(fileName, videoFileName)) {
|
if (TextUtils.equals(fileName, videoFileName)) {
|
||||||
radialProgress.setProgress(1f, true);
|
avatarView.setProgress(1f);
|
||||||
}
|
}
|
||||||
} else if (id == NotificationCenter.fileLoadProgressChanged) {
|
} else if (id == NotificationCenter.fileLoadProgressChanged) {
|
||||||
String fileName = (String) args[0];
|
String fileName = (String) args[0];
|
||||||
if (TextUtils.equals(fileName, videoFileName)) {
|
if (TextUtils.equals(fileName, videoFileName)) {
|
||||||
if (radialProgress != null) {
|
|
||||||
Long loadedSize = (Long) args[1];
|
Long loadedSize = (Long) args[1];
|
||||||
Long totalSize = (Long) args[2];
|
Long totalSize = (Long) args[2];
|
||||||
float progress = Math.min(1f, loadedSize / (float) totalSize);
|
float progress = Math.min(1f, loadedSize / (float) totalSize);
|
||||||
radialProgress.setProgress(progress, true);
|
avatarView.setProgress(progress);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
if (!showing) {
|
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK || event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE) {
|
||||||
return false;
|
if (getKeyDispatcherState() == null) {
|
||||||
}
|
return super.dispatchKeyEvent(event);
|
||||||
if (moveAnimator == null) {
|
|
||||||
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
|
|
||||||
downY = -1;
|
|
||||||
setShowing(false);
|
|
||||||
} else if (event.getActionMasked() == MotionEvent.ACTION_MOVE) {
|
|
||||||
if (downY < 0) {
|
|
||||||
downY = event.getY();
|
|
||||||
} else {
|
|
||||||
moveProgress = Math.max(-1, Math.min(0f, (event.getY() - downY) / AndroidUtilities.dp(56)));
|
|
||||||
if (moveProgress == -1) {
|
|
||||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
|
||||||
moveAnimator = ValueAnimator.ofFloat(moveProgress, 0);
|
|
||||||
moveAnimator.setDuration(200);
|
|
||||||
moveAnimator.addUpdateListener(a -> {
|
|
||||||
moveProgress = (float) a.getAnimatedValue();
|
|
||||||
invalidate();
|
|
||||||
});
|
|
||||||
moveAnimator.start();
|
|
||||||
showBottomSheet();
|
|
||||||
}
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showBottomSheet() {
|
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
|
||||||
final CharSequence[] labels = new CharSequence[menuItems.length];
|
final KeyEvent.DispatcherState state = getKeyDispatcherState();
|
||||||
final int[] icons = new int[menuItems.length];
|
if (state != null) {
|
||||||
for (int i = 0; i < menuItems.length; i++) {
|
state.startTracking(event, this);
|
||||||
labels[i] = LocaleController.getString(menuItems[i].labelKey, menuItems[i].labelResId);
|
}
|
||||||
icons[i] = menuItems[i].iconResId;
|
return true;
|
||||||
}
|
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
visibleSheet = new BottomSheet.Builder(getContext())
|
final KeyEvent.DispatcherState state = getKeyDispatcherState();
|
||||||
.setItems(labels, icons, (dialog, which) -> {
|
if (state != null && state.isTracking(event) && !event.isCanceled()) {
|
||||||
callback.onMenuClick(menuItems[which]);
|
|
||||||
setShowing(false);
|
setShowing(false);
|
||||||
})
|
return true;
|
||||||
.setDimBehind(false);
|
}
|
||||||
visibleSheet.setOnDismissListener(dialog -> {
|
}
|
||||||
visibleSheet = null;
|
return super.dispatchKeyEvent(event);
|
||||||
setShowing(false);
|
} else {
|
||||||
});
|
return super.dispatchKeyEvent(event);
|
||||||
visibleSheet.show();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
|
|
||||||
this.insets = insets;
|
|
||||||
invalidateSize();
|
|
||||||
return insets.consumeStableInsets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||||
invalidateSize();
|
if (w != 0 && h != 0 && showing) {
|
||||||
|
blurView.setBackground(null);
|
||||||
|
AndroidUtilities.runOnUIThread(this::prepareBlurBitmap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidateSize() {
|
private void prepareBlurBitmap() {
|
||||||
final int width = getWidth();
|
if (preparingBlur) {
|
||||||
final int height = getHeight();
|
return;
|
||||||
|
}
|
||||||
|
preparingBlur = true;
|
||||||
|
AndroidUtilities.makeGlobalBlurBitmap(bitmap -> {
|
||||||
|
//noinspection deprecation
|
||||||
|
blurView.setBackground(new BitmapDrawable(bitmap));
|
||||||
|
preparingBlur = false;
|
||||||
|
}, 6f, 7, this, Collections.singletonList(this));
|
||||||
|
}
|
||||||
|
|
||||||
if (width == 0 || height == 0) {
|
public void setData(Data data) {
|
||||||
|
menuItems = data.menuItems;
|
||||||
|
avatarView.setShowProgress(data.videoLocation != null);
|
||||||
|
videoFileName = data.videoFileName;
|
||||||
|
|
||||||
|
recycleInfoLoadTask();
|
||||||
|
if (data.infoLoadTask != null) {
|
||||||
|
infoLoadTask = data.infoLoadTask;
|
||||||
|
infoLoadTask.load(result -> {
|
||||||
|
if (!recycled) {
|
||||||
|
if (result instanceof TLRPC.UserFull) {
|
||||||
|
setData(Data.of((TLRPC.User) data.infoLoadTask.argument, (TLRPC.UserFull) result, data.menuItems));
|
||||||
|
} else if (result instanceof TLRPC.ChatFull) {
|
||||||
|
setData(Data.of((TLRPC.Chat) data.infoLoadTask.argument, (TLRPC.ChatFull) result, data.menuItems));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
avatarView.setImage(UserConfig.selectedAccount, data.videoLocation, data.videoFilter, data.imageLocation, data.imageFilter, data.thumbImageLocation, data.thumbImageFilter, data.thumb, data.parentObject);
|
||||||
|
|
||||||
|
menu.removeInnerViews();
|
||||||
|
for (int i = 0; i < menuItems.length; i++) {
|
||||||
|
final MenuItem menuItem = menuItems[i];
|
||||||
|
CharSequence label = LocaleController.getString(menuItem.labelKey, menuItem.labelResId);
|
||||||
|
ActionBarMenuSubItem item = ActionBarMenuItem.addItem(i == 0, i == menuItems.length - 1, menu, menuItem.iconResId, label, false, resourcesProvider);
|
||||||
|
item.setTag(i);
|
||||||
|
item.setOnClickListener(v -> {
|
||||||
|
setShowing(false);
|
||||||
|
callback.onMenuClick(menuItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setShowing(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setShowing(boolean showing) {
|
||||||
|
if (this.showing == showing) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
backgroundDrawable.setBounds(0, 0, width, height);
|
this.showing = showing;
|
||||||
|
|
||||||
final int padding = AndroidUtilities.dp(8);
|
ValueAnimator foregroundAnimator = ValueAnimator.ofFloat(0f, 1f);
|
||||||
|
foregroundAnimator.setInterpolator(showing ? openInterpolator : CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||||
|
foregroundAnimator.addUpdateListener(animation -> {
|
||||||
|
float value = (float) animation.getAnimatedValue();
|
||||||
|
if (!showing) {
|
||||||
|
value = 1f - value;
|
||||||
|
}
|
||||||
|
float clampedValue = MathUtils.clamp(value, 0f, 1f);
|
||||||
|
|
||||||
int lPadding = padding, rPadding = padding, vPadding = padding;
|
container.setScaleX(0.7f + 0.3f * value);
|
||||||
|
container.setScaleY(0.7f + 0.3f * value);
|
||||||
|
container.setAlpha(clampedValue);
|
||||||
|
avatarView.setTranslationY(dp(40) * (1f - value));
|
||||||
|
menu.setTranslationY(-dp(40 + 30) * (1f - value));
|
||||||
|
menu.setScaleX(0.95f + 0.05f * value);
|
||||||
|
menu.setScaleY(0.95f + 0.05f * value);
|
||||||
|
});
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
ValueAnimator blurAnimator = ValueAnimator.ofFloat(0f, 1f);
|
||||||
lPadding += insets.getStableInsetLeft();
|
blurAnimator.addUpdateListener(animation -> {
|
||||||
rPadding += insets.getStableInsetRight();
|
float value = (float) animation.getAnimatedValue();
|
||||||
vPadding += Math.max(insets.getStableInsetTop(), insets.getStableInsetBottom());
|
if (!showing) {
|
||||||
|
value = 1f - value;
|
||||||
|
}
|
||||||
|
blurView.setAlpha(value); // Linear value
|
||||||
|
invalidate();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (openAnimator != null) {
|
||||||
|
openAnimator.cancel();
|
||||||
|
}
|
||||||
|
openAnimator = new AnimatorSet();
|
||||||
|
openAnimator.setDuration(showing ? 190 : 150);
|
||||||
|
openAnimator.playTogether(foregroundAnimator, blurAnimator);
|
||||||
|
openAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
if (!showing) {
|
||||||
|
setVisibility(INVISIBLE);
|
||||||
|
onHideFinish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
openAnimator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void recycle() {
|
||||||
|
recycled = true;
|
||||||
|
recycleInfoLoadTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recycleInfoLoadTask() {
|
||||||
|
if (infoLoadTask != null) {
|
||||||
|
infoLoadTask.cancel();
|
||||||
|
infoLoadTask = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void onHideFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AvatarView extends FrameLayout {
|
||||||
|
private BackupImageView backupImageView;
|
||||||
|
|
||||||
|
private final RadialProgress2 radialProgress;
|
||||||
|
private boolean showProgress;
|
||||||
|
private ValueAnimator progressHideAnimator;
|
||||||
|
private ValueAnimator progressShowAnimator;
|
||||||
|
private final int radialProgressSize = dp(64f);
|
||||||
|
|
||||||
|
public AvatarView(Context context, Theme.ResourcesProvider resourcesProvider) {
|
||||||
|
super(context);
|
||||||
|
setWillNotDraw(false);
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
setOutlineProvider(new RoundRectOutlineProvider(6));
|
||||||
}
|
}
|
||||||
|
|
||||||
final int arrowWidth = arrowDrawable.getIntrinsicWidth();
|
backupImageView = new BackupImageView(context);
|
||||||
final int arrowHeight = arrowDrawable.getIntrinsicHeight();
|
backupImageView.setAspectFit(true);
|
||||||
final int arrowPadding = AndroidUtilities.dp(24);
|
backupImageView.setRoundRadius(dp(6));
|
||||||
|
addView(backupImageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||||
|
|
||||||
final int w = width - (lPadding + rPadding);
|
radialProgress = new RadialProgress2(this, resourcesProvider);
|
||||||
final int h = height - vPadding * 2;
|
radialProgress.setOverrideAlpha(0.0f);
|
||||||
|
radialProgress.setIcon(MediaActionDrawable.ICON_EMPTY, false, false);
|
||||||
|
radialProgress.setColors(0x42000000, 0x42000000, Color.WHITE, Color.WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
final int size = Math.min(w, h);
|
public void setImage(int currentAccount, ImageLocation mediaLocation, String mediaFilter, ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, BitmapDrawable thumb, Object parentObject) {
|
||||||
final int vOffset = arrowPadding + arrowHeight / 2;
|
backupImageView.getImageReceiver().setCurrentAccount(currentAccount);
|
||||||
final int x = (w - size) / 2 + lPadding;
|
backupImageView.getImageReceiver().setImage(mediaLocation, mediaFilter, imageLocation, imageFilter, thumbLocation, thumbFilter, thumb, 0, null, parentObject, 1);
|
||||||
final int y = (h - size) / 2 + vPadding + (w > h ? vOffset : 0);
|
backupImageView.onNewImageSet();
|
||||||
imageReceiver.setImageCoords(x, y, size, size - (w > h ? vOffset : 0));
|
}
|
||||||
|
|
||||||
final int cx = (int) imageReceiver.getCenterX();
|
public void setProgress(float progress) {
|
||||||
final int cy = (int) imageReceiver.getCenterY();
|
radialProgress.setProgress(progress, true);
|
||||||
radialProgress.setProgressRect(cx - radialProgressSize / 2, cy - radialProgressSize / 2, cx + radialProgressSize / 2, cy + radialProgressSize / 2);
|
}
|
||||||
|
|
||||||
final int arrowX = x + size / 2;
|
public boolean getShowProgress() {
|
||||||
final int arrowY = y - arrowPadding;
|
return showProgress;
|
||||||
arrowDrawable.setBounds(arrowX - arrowWidth / 2, arrowY - arrowHeight / 2, arrowX + arrowWidth / 2, arrowY + arrowHeight / 2);
|
}
|
||||||
|
|
||||||
|
public void setShowProgress(boolean showProgress) {
|
||||||
|
this.showProgress = showProgress;
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
long newTime = AnimationUtils.currentAnimationTimeMillis();
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
long dt = newTime - lastUpdateTime;
|
int cx = getWidth() / 2;
|
||||||
lastUpdateTime = newTime;
|
int cy = getHeight() / 2;
|
||||||
|
radialProgress.setProgressRect(cx - radialProgressSize, cy - radialProgressSize, cx + radialProgressSize, cy + radialProgressSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (showing && progress < 1f) {
|
@Override
|
||||||
progress += dt / ANIM_DURATION;
|
protected void dispatchDraw(Canvas canvas) {
|
||||||
if (progress < 1f) {
|
super.dispatchDraw(canvas);
|
||||||
postInvalidateOnAnimation();
|
|
||||||
} else {
|
|
||||||
progress = 1f;
|
|
||||||
}
|
|
||||||
} else if (!showing && progress > 0f) {
|
|
||||||
progress -= dt / ANIM_DURATION;
|
|
||||||
if (progress > 0f) {
|
|
||||||
postInvalidateOnAnimation();
|
|
||||||
} else {
|
|
||||||
progress = 0f;
|
|
||||||
onHide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final float interpolatedProgress = interpolator.getInterpolation(progress);
|
|
||||||
backgroundDrawable.setAlpha((int) (180 * interpolatedProgress));
|
|
||||||
backgroundDrawable.draw(canvas);
|
|
||||||
if (interpolatedProgress < 1.0f) {
|
|
||||||
canvas.scale(AndroidUtilities.lerp(0.95f, 1.0f, interpolatedProgress), AndroidUtilities.lerp(0.95f, 1.0f, interpolatedProgress), imageReceiver.getCenterX(), imageReceiver.getCenterY());
|
|
||||||
}
|
|
||||||
|
|
||||||
final int statusBarHeight = Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0;
|
|
||||||
final int navBarHeight = Build.VERSION.SDK_INT >= 21 ? insets.getStableInsetBottom() : 0;
|
|
||||||
final int sheetHeight = menuItems.length * AndroidUtilities.dp(48) + AndroidUtilities.dp(16);
|
|
||||||
final float maxBottom = getHeight() - (navBarHeight + sheetHeight + AndroidUtilities.dp(16));
|
|
||||||
final float translationY = Math.min(0, maxBottom - imageReceiver.getImageY2());
|
|
||||||
if (imageReceiver.getImageY() + translationY < statusBarHeight) {
|
|
||||||
canvas.translate(0, moveProgress * AndroidUtilities.dp(16));
|
|
||||||
} else {
|
|
||||||
canvas.translate(0, translationY + moveProgress * AndroidUtilities.dp(16));
|
|
||||||
}
|
|
||||||
|
|
||||||
imageReceiver.setAlpha(interpolatedProgress);
|
|
||||||
imageReceiver.draw(canvas);
|
|
||||||
|
|
||||||
if (showProgress) {
|
if (showProgress) {
|
||||||
final Drawable drawable = imageReceiver.getDrawable();
|
final Drawable drawable = backupImageView.getImageReceiver().getDrawable();
|
||||||
if (drawable instanceof AnimatedFileDrawable && ((AnimatedFileDrawable) drawable).getDurationMs() > 0) {
|
if (drawable instanceof AnimatedFileDrawable && ((AnimatedFileDrawable) drawable).getDurationMs() > 0) {
|
||||||
if (progressShowAnimator != null) {
|
if (progressShowAnimator != null) {
|
||||||
progressShowAnimator.cancel();
|
progressShowAnimator.cancel();
|
||||||
|
@ -606,64 +705,6 @@ public class AvatarPreviewer {
|
||||||
radialProgress.draw(canvas);
|
radialProgress.draw(canvas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (moveAnimator != null) {
|
|
||||||
arrowDrawable.setAlpha((int) ((1f - moveAnimator.getAnimatedFraction()) * 255));
|
|
||||||
} else {
|
|
||||||
arrowDrawable.setAlpha((int) (255 * interpolatedProgress));
|
|
||||||
}
|
|
||||||
arrowDrawable.draw(canvas);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(Data data) {
|
|
||||||
menuItems = data.menuItems;
|
|
||||||
showProgress = data.videoLocation != null;
|
|
||||||
videoFileName = data.videoFileName;
|
|
||||||
|
|
||||||
recycleInfoLoadTask();
|
|
||||||
if (data.infoLoadTask != null) {
|
|
||||||
infoLoadTask = data.infoLoadTask;
|
|
||||||
infoLoadTask.load(result -> {
|
|
||||||
if (!recycled) {
|
|
||||||
if (result instanceof TLRPC.UserFull) {
|
|
||||||
setData(Data.of((TLRPC.UserFull) result, data.menuItems));
|
|
||||||
} else if (result instanceof TLRPC.ChatFull) {
|
|
||||||
setData(Data.of((TLRPC.Chat) data.infoLoadTask.argument, (TLRPC.ChatFull) result, data.menuItems));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
imageReceiver.setCurrentAccount(UserConfig.selectedAccount);
|
|
||||||
imageReceiver.setImage(data.videoLocation, data.videoFilter, data.imageLocation, data.imageFilter, data.thumbImageLocation, data.thumbImageFilter, null, 0, null, data.parentObject, 1);
|
|
||||||
setShowing(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setShowing(boolean showing) {
|
|
||||||
if (this.showing != showing) {
|
|
||||||
this.showing = showing;
|
|
||||||
lastUpdateTime = AnimationUtils.currentAnimationTimeMillis();
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recycle() {
|
|
||||||
recycled = true;
|
|
||||||
if (moveAnimator != null) {
|
|
||||||
moveAnimator.cancel();
|
|
||||||
}
|
|
||||||
if (visibleSheet != null) {
|
|
||||||
visibleSheet.cancel();
|
|
||||||
}
|
|
||||||
recycleInfoLoadTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recycleInfoLoadTask() {
|
|
||||||
if (infoLoadTask != null) {
|
|
||||||
infoLoadTask.cancel();
|
|
||||||
infoLoadTask = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void onHide();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.telegram.ui.Charts.view_data.ChartHeaderView;
|
||||||
import org.telegram.ui.Components.Bulletin;
|
import org.telegram.ui.Components.Bulletin;
|
||||||
import org.telegram.ui.Components.CircularProgressDrawable;
|
import org.telegram.ui.Components.CircularProgressDrawable;
|
||||||
import org.telegram.ui.Components.CombinedDrawable;
|
import org.telegram.ui.Components.CombinedDrawable;
|
||||||
|
import org.telegram.ui.Components.FillLastLinearLayoutManager;
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
import org.telegram.ui.Components.LinkActionView;
|
import org.telegram.ui.Components.LinkActionView;
|
||||||
import org.telegram.ui.Components.ListView.AdapterWithDiffUtils;
|
import org.telegram.ui.Components.ListView.AdapterWithDiffUtils;
|
||||||
|
@ -133,8 +134,11 @@ public class BoostsActivity extends GradientHeaderActivity implements Notificati
|
||||||
view = new View(getContext()) {
|
view = new View(getContext()) {
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
int h = Math.max(0, layoutManager.getLastItemHeight()) ;
|
int lastItemHeight = 0;
|
||||||
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
|
if (layoutManager instanceof FillLastLinearLayoutManager) {
|
||||||
|
lastItemHeight = ((FillLastLinearLayoutManager) layoutManager).getLastItemHeight();
|
||||||
|
}
|
||||||
|
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Math.max(0, lastItemHeight), MeasureSpec.EXACTLY));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
|
view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
|
||||||
|
@ -765,7 +769,7 @@ public class BoostsActivity extends GradientHeaderActivity implements Notificati
|
||||||
imageView = new ImageView(context);
|
imageView = new ImageView(context);
|
||||||
textView = new TextView(context);
|
textView = new TextView(context);
|
||||||
textView.setTextColor(Color.WHITE);
|
textView.setTextColor(Color.WHITE);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
|
||||||
addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
|
addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
|
||||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 25, 0, 0));
|
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 25, 0, 0));
|
||||||
|
|
|
@ -16,7 +16,6 @@ import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.MessagesController;
|
import org.telegram.messenger.MessagesController;
|
||||||
import org.telegram.messenger.NotificationCenter;
|
import org.telegram.messenger.NotificationCenter;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.UserConfig;
|
|
||||||
import org.telegram.messenger.UserObject;
|
import org.telegram.messenger.UserObject;
|
||||||
import org.telegram.messenger.browser.Browser;
|
import org.telegram.messenger.browser.Browser;
|
||||||
import org.telegram.tgnet.ConnectionsManager;
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
|
@ -68,7 +67,7 @@ public class BusinessBotButton extends FrameLayout {
|
||||||
titleView = new AnimatedTextView(context);
|
titleView = new AnimatedTextView(context);
|
||||||
titleView.adaptWidth = false;
|
titleView.adaptWidth = false;
|
||||||
titleView.getDrawable().setHacks(true, true, false);
|
titleView.getDrawable().setHacks(true, true, false);
|
||||||
titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
titleView.setTypeface(AndroidUtilities.bold());
|
||||||
titleView.setTextSize(dp(14));
|
titleView.setTextSize(dp(14));
|
||||||
titleView.setText(UserObject.getUserName(user));
|
titleView.setText(UserObject.getUserName(user));
|
||||||
titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
|
titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
|
||||||
|
@ -90,7 +89,7 @@ public class BusinessBotButton extends FrameLayout {
|
||||||
pauseButton.getDrawable().setHacks(true, true, true);
|
pauseButton.getDrawable().setHacks(true, true, true);
|
||||||
pauseButton.setAnimationProperties(.75f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
|
pauseButton.setAnimationProperties(.75f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||||
pauseButton.setScaleProperty(.6f);
|
pauseButton.setScaleProperty(.6f);
|
||||||
pauseButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
pauseButton.setTypeface(AndroidUtilities.bold());
|
||||||
pauseButton.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(dp(14), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), Theme.blendOver(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), Theme.multAlpha(Color.WHITE, .12f))));
|
pauseButton.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(dp(14), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), Theme.blendOver(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), Theme.multAlpha(Color.WHITE, .12f))));
|
||||||
pauseButton.setTextSize(dp(14));
|
pauseButton.setTextSize(dp(14));
|
||||||
pauseButton.setGravity(Gravity.RIGHT);
|
pauseButton.setGravity(Gravity.RIGHT);
|
||||||
|
|
|
@ -543,7 +543,7 @@ public class BusinessIntroActivity extends UniversalFragment implements Notifica
|
||||||
};
|
};
|
||||||
chatAttachAlert.setDelegate(new ChatAttachAlert.ChatAttachViewDelegate() {
|
chatAttachAlert.setDelegate(new ChatAttachAlert.ChatAttachViewDelegate() {
|
||||||
@Override
|
@Override
|
||||||
public void didPressedButton(int button, boolean arg, boolean notify, int scheduleDate, boolean forceDocument) {
|
public void didPressedButton(int button, boolean arg, boolean notify, int scheduleDate, long effectId, boolean invertMedia, boolean forceDocument) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -116,7 +116,7 @@ public class BusinessLinksController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
storage.getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
storage.getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
if (!chatsToLoad.isEmpty()) {
|
if (!chatsToLoad.isEmpty()) {
|
||||||
storage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
storage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
|
|
|
@ -107,7 +107,7 @@ public class ChatAttachAlertQuickRepliesLayout extends ChatAttachAlert.AttachAle
|
||||||
};
|
};
|
||||||
NotificationCenter.listenEmojiLoading(nameTextView);
|
NotificationCenter.listenEmojiLoading(nameTextView);
|
||||||
nameTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
nameTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
|
||||||
nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
nameTextView.setTypeface(AndroidUtilities.bold());
|
||||||
nameTextView.setTextSize(16);
|
nameTextView.setTextSize(16);
|
||||||
nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
|
||||||
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 28 : 72, 12, LocaleController.isRTL ? 72 : 28, 0));
|
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 28 : 72, 12, LocaleController.isRTL ? 72 : 28, 0));
|
||||||
|
@ -446,7 +446,7 @@ public class ChatAttachAlertQuickRepliesLayout extends ChatAttachAlert.AttachAle
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendSelectedItems(boolean notify, int scheduleDate) {
|
public void sendSelectedItems(boolean notify, int scheduleDate, long effectId, boolean invertMedia) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputFilter;
|
import android.text.InputFilter;
|
||||||
import android.text.InputType;
|
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
@ -69,7 +68,6 @@ import org.telegram.ui.Components.AvatarDrawable;
|
||||||
import org.telegram.ui.Components.CheckBox2;
|
import org.telegram.ui.Components.CheckBox2;
|
||||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||||
import org.telegram.ui.Components.EditTextBoldCursor;
|
import org.telegram.ui.Components.EditTextBoldCursor;
|
||||||
import org.telegram.ui.Components.ForegroundColorSpanThemable;
|
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
import org.telegram.ui.Components.NumberTextView;
|
import org.telegram.ui.Components.NumberTextView;
|
||||||
import org.telegram.ui.Components.SizeNotifierFrameLayout;
|
import org.telegram.ui.Components.SizeNotifierFrameLayout;
|
||||||
|
@ -136,7 +134,7 @@ public class QuickRepliesActivity extends BaseFragment implements NotificationCe
|
||||||
ActionBarMenu actionModeMenu = actionBar.createActionMode();
|
ActionBarMenu actionModeMenu = actionBar.createActionMode();
|
||||||
countText = new NumberTextView(getContext());
|
countText = new NumberTextView(getContext());
|
||||||
countText.setTextSize(18);
|
countText.setTextSize(18);
|
||||||
countText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
countText.setTypeface(AndroidUtilities.bold());
|
||||||
countText.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon));
|
countText.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon));
|
||||||
actionModeMenu.addView(countText, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0));
|
actionModeMenu.addView(countText, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0));
|
||||||
countText.setOnTouchListener((v, event) -> true);
|
countText.setOnTouchListener((v, event) -> true);
|
||||||
|
@ -528,7 +526,7 @@ public class QuickRepliesActivity extends BaseFragment implements NotificationCe
|
||||||
private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
private final Text text;
|
private final Text text;
|
||||||
public MoreSpan(int count) {
|
public MoreSpan(int count) {
|
||||||
text = new Text(formatPluralString("BusinessRepliesMore", count), 9.33f, AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
text = new Text(formatPluralString("BusinessRepliesMore", count), 9.33f, AndroidUtilities.bold());
|
||||||
}
|
}
|
||||||
public static CharSequence of(int count, int[] width) {
|
public static CharSequence of(int count, int[] width) {
|
||||||
SpannableString ss = new SpannableString("+");
|
SpannableString ss = new SpannableString("+");
|
||||||
|
@ -623,7 +621,7 @@ public class QuickRepliesActivity extends BaseFragment implements NotificationCe
|
||||||
highlight = "/" + highlight;
|
highlight = "/" + highlight;
|
||||||
}
|
}
|
||||||
ssb.append("/").append(quickReply.name);
|
ssb.append("/").append(quickReply.name);
|
||||||
ssb.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
ssb.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
ssb.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)), 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
ssb.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)), 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
if (highlight != null) {
|
if (highlight != null) {
|
||||||
ssb.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider)), 0, Math.min(highlight.length() <= 0 ? 1 : highlight.length(), ssb.length()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
ssb.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider)), 0, Math.min(highlight.length() <= 0 ? 1 : highlight.length(), ssb.length()), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
@ -737,7 +735,7 @@ public class QuickRepliesActivity extends BaseFragment implements NotificationCe
|
||||||
titleView.setSingleLine();
|
titleView.setSingleLine();
|
||||||
titleView.setEllipsize(TextUtils.TruncateAt.END);
|
titleView.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
|
titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider));
|
||||||
titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
titleView.setTypeface(AndroidUtilities.bold());
|
||||||
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL, LocaleController.isRTL ? 40 : 78, 10.33f, LocaleController.isRTL ? 78 : 40, 0));
|
addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL_HORIZONTAL, LocaleController.isRTL ? 40 : 78, 10.33f, LocaleController.isRTL ? 78 : 40, 0));
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ public class QuickRepliesController {
|
||||||
storage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
storage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
storage.getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
storage.getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -531,7 +531,7 @@ public class QuickRepliesController {
|
||||||
storage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
storage.getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
}
|
}
|
||||||
if (!usersToLoad.isEmpty()) {
|
if (!usersToLoad.isEmpty()) {
|
||||||
storage.getUsersInternal(TextUtils.join(",", usersToLoad), users);
|
storage.getUsersInternal(usersToLoad, users);
|
||||||
}
|
}
|
||||||
final MessageObject finalMessageObject = messageObject;
|
final MessageObject finalMessageObject = messageObject;
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class QuickRepliesEmptyView extends LinearLayout {
|
||||||
|
|
||||||
titleView = new TextView(context);
|
titleView = new TextView(context);
|
||||||
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
titleView.setTypeface(AndroidUtilities.bold());
|
||||||
titleView.setTextAlignment(TEXT_ALIGNMENT_CENTER);
|
titleView.setTextAlignment(TEXT_ALIGNMENT_CENTER);
|
||||||
titleView.setGravity(Gravity.CENTER);
|
titleView.setGravity(Gravity.CENTER);
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,6 @@ import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class CacheControlActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
public class CacheControlActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
|
||||||
|
@ -519,7 +518,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
|
ArrayList<TLRPC.Chat> chats = new ArrayList<>();
|
||||||
if (!unknownUsers.isEmpty()) {
|
if (!unknownUsers.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
getMessagesStorage().getUsersInternal(TextUtils.join(",", unknownUsers), users);
|
getMessagesStorage().getUsersInternal(unknownUsers, users);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
|
@ -683,7 +682,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
String percentString = percent <= 0 ? String.format("<%.1f%%", 1f) : String.format("%d%%", percent);
|
String percentString = percent <= 0 ? String.format("<%.1f%%", 1f) : String.format("%d%%", percent);
|
||||||
SpannableString percentStr = new SpannableString(percentString);
|
SpannableString percentStr = new SpannableString(percentString);
|
||||||
percentStr.setSpan(new RelativeSizeSpan(.834f), 0, percentStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
percentStr.setSpan(new RelativeSizeSpan(.834f), 0, percentStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
percentStr.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, percentStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
percentStr.setSpan(new TypefaceSpan(AndroidUtilities.bold()), 0, percentStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
SpannableStringBuilder string = new SpannableStringBuilder(header);
|
SpannableStringBuilder string = new SpannableStringBuilder(header);
|
||||||
string.append(" ");
|
string.append(" ");
|
||||||
string.append(percentStr);
|
string.append(percentStr);
|
||||||
|
@ -1268,7 +1267,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
actionModeTitle = new AnimatedTextView(context, true, true, true);
|
actionModeTitle = new AnimatedTextView(context, true, true, true);
|
||||||
actionModeTitle.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
|
actionModeTitle.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||||
actionModeTitle.setTextSize(AndroidUtilities.dp(18));
|
actionModeTitle.setTextSize(AndroidUtilities.dp(18));
|
||||||
actionModeTitle.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
actionModeTitle.setTypeface(AndroidUtilities.bold());
|
||||||
actionModeTitle.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
actionModeTitle.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||||
actionModeLayout.addView(actionModeTitle, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.LEFT | Gravity.CENTER_VERTICAL, 0, -11, 18, 0));
|
actionModeLayout.addView(actionModeTitle, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.LEFT | Gravity.CENTER_VERTICAL, 0, -11, 18, 0));
|
||||||
|
|
||||||
|
@ -1283,7 +1282,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
actionModeClearButton.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(14), 0);
|
actionModeClearButton.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(14), 0);
|
||||||
actionModeClearButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
actionModeClearButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
||||||
actionModeClearButton.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, 6));
|
actionModeClearButton.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, 6));
|
||||||
actionModeClearButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
actionModeClearButton.setTypeface(AndroidUtilities.bold());
|
||||||
actionModeClearButton.setGravity(Gravity.CENTER);
|
actionModeClearButton.setGravity(Gravity.CENTER);
|
||||||
actionModeClearButton.setText(LocaleController.getString("CacheClear", R.string.CacheClear));
|
actionModeClearButton.setText(LocaleController.getString("CacheClear", R.string.CacheClear));
|
||||||
actionModeClearButton.setOnClickListener(e -> clearSelectedFiles());
|
actionModeClearButton.setOnClickListener(e -> clearSelectedFiles());
|
||||||
|
@ -1717,7 +1716,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
|
|
||||||
title = new AnimatedTextView(context);
|
title = new AnimatedTextView(context);
|
||||||
title.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
|
title.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||||
title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
title.setTypeface(AndroidUtilities.bold());
|
||||||
title.setTextSize(AndroidUtilities.dp(20));
|
title.setTextSize(AndroidUtilities.dp(20));
|
||||||
title.setText(LocaleController.getString("StorageUsage", R.string.StorageUsage));
|
title.setText(LocaleController.getString("StorageUsage", R.string.StorageUsage));
|
||||||
title.setGravity(Gravity.CENTER);
|
title.setGravity(Gravity.CENTER);
|
||||||
|
@ -1941,7 +1940,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
percentsTextView.setGravity(Gravity.CENTER_HORIZONTAL);
|
percentsTextView.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
percentsTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
percentsTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
||||||
percentsTextView.setTextSize(AndroidUtilities.dp(24));
|
percentsTextView.setTextSize(AndroidUtilities.dp(24));
|
||||||
percentsTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
percentsTextView.setTypeface(AndroidUtilities.bold());
|
||||||
addView(percentsTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 - 6, 0, 0));
|
addView(percentsTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 - 6, 0, 0));
|
||||||
|
|
||||||
progressView = new ProgressView(context);
|
progressView = new ProgressView(context);
|
||||||
|
@ -1951,7 +1950,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
title.setGravity(Gravity.CENTER_HORIZONTAL);
|
title.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
title.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
title.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
|
||||||
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
title.setTypeface(AndroidUtilities.bold());
|
||||||
title.setText(LocaleController.getString("ClearingCache", R.string.ClearingCache));
|
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));
|
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));
|
||||||
|
|
||||||
|
@ -2171,7 +2170,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
rtlTextView.setText(LocaleController.getString("ClearCache", R.string.ClearCache));
|
rtlTextView.setText(LocaleController.getString("ClearCache", R.string.ClearCache));
|
||||||
rtlTextView.setGravity(Gravity.CENTER);
|
rtlTextView.setGravity(Gravity.CENTER);
|
||||||
rtlTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
rtlTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||||
rtlTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
rtlTextView.setTypeface(AndroidUtilities.bold());
|
||||||
rtlTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
rtlTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
||||||
button.addView(rtlTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER));
|
button.addView(rtlTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER));
|
||||||
}
|
}
|
||||||
|
@ -2182,14 +2181,14 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
|
||||||
textView.setTextSize(AndroidUtilities.dp(14));
|
textView.setTextSize(AndroidUtilities.dp(14));
|
||||||
textView.setText(LocaleController.getString("ClearCache", R.string.ClearCache));
|
textView.setText(LocaleController.getString("ClearCache", R.string.ClearCache));
|
||||||
textView.setGravity(Gravity.RIGHT);
|
textView.setGravity(Gravity.RIGHT);
|
||||||
textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
textView.setTypeface(AndroidUtilities.bold());
|
||||||
textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
|
||||||
|
|
||||||
valueTextView = new AnimatedTextView.AnimatedTextDrawable(true, true, true);
|
valueTextView = new AnimatedTextView.AnimatedTextDrawable(true, true, true);
|
||||||
valueTextView.setAnimationProperties(.25f, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT);
|
valueTextView.setAnimationProperties(.25f, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||||
valueTextView.setCallback(button);
|
valueTextView.setCallback(button);
|
||||||
valueTextView.setTextSize(AndroidUtilities.dp(14));
|
valueTextView.setTextSize(AndroidUtilities.dp(14));
|
||||||
valueTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
|
valueTextView.setTypeface(AndroidUtilities.bold());
|
||||||
valueTextView.setTextColor(Theme.blendOver(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.multAlpha(Theme.getColor(Theme.key_featuredStickers_buttonText), .7f)));
|
valueTextView.setTextColor(Theme.blendOver(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.multAlpha(Theme.getColor(Theme.key_featuredStickers_buttonText), .7f)));
|
||||||
valueTextView.setText("");
|
valueTextView.setText("");
|
||||||
|
|
||||||
|
|
|
@ -285,7 +285,7 @@ public class CachedMediaLayout extends FrameLayout implements NestedSizeNotifier
|
||||||
|
|
||||||
selectedMessagesCountTextView = new AnimatedTextView(context, true, true, true);
|
selectedMessagesCountTextView = new AnimatedTextView(context, true, true, true);
|
||||||
selectedMessagesCountTextView.setTextSize(AndroidUtilities.dp(18));
|
selectedMessagesCountTextView.setTextSize(AndroidUtilities.dp(18));
|
||||||
selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
selectedMessagesCountTextView.setTypeface(AndroidUtilities.bold());
|
||||||
selectedMessagesCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon));
|
selectedMessagesCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon));
|
||||||
actionModeLayout.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 18, 0, 0, 0));
|
actionModeLayout.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 18, 0, 0, 0));
|
||||||
actionModeViews.add(selectedMessagesCountTextView);
|
actionModeViews.add(selectedMessagesCountTextView);
|
||||||
|
|
|
@ -0,0 +1,184 @@
|
||||||
|
package org.telegram.ui;
|
||||||
|
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RenderNode;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.StaticLayout;
|
||||||
|
import android.text.TextPaint;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.core.graphics.ColorUtils;
|
||||||
|
|
||||||
|
import org.telegram.messenger.Emoji;
|
||||||
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
|
|
||||||
|
public class CachedStaticLayout {
|
||||||
|
|
||||||
|
public final StaticLayout layout;
|
||||||
|
private boolean disabled;
|
||||||
|
|
||||||
|
public CachedStaticLayout(StaticLayout source) {
|
||||||
|
this.layout = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CachedStaticLayout disableCache() {
|
||||||
|
disabled = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RenderNode renderNode;
|
||||||
|
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
if (!disabled && canvas.isHardwareAccelerated() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && canvas.quickReject(0, 0, layout.getWidth(), layout.getHeight())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (hasChanges() || renderNode == null || !renderNode.hasDisplayList()) {
|
||||||
|
if (renderNode == null) {
|
||||||
|
renderNode = new RenderNode("CachedStaticLayout");
|
||||||
|
renderNode.setClipToBounds(false);
|
||||||
|
}
|
||||||
|
renderNode.setPosition(getLayoutBounds());
|
||||||
|
Canvas cacheCanvas = renderNode.beginRecording();
|
||||||
|
int color = layout.getPaint().getColor();
|
||||||
|
layout.getPaint().setColor(ColorUtils.setAlphaComponent(color, 0xFF));
|
||||||
|
layout.draw(cacheCanvas);
|
||||||
|
layout.getPaint().setColor(color);
|
||||||
|
renderNode.endRecording();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNode.setAlpha(layout.getPaint().getAlpha() / 255.0f);
|
||||||
|
canvas.drawRenderNode(renderNode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout.draw(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int textColor;
|
||||||
|
private int linkColor;
|
||||||
|
private Typeface typeface;
|
||||||
|
private float textSize;
|
||||||
|
private final Rect lastLayoutBounds = new Rect();
|
||||||
|
private boolean[] lastEmojiLoaded;
|
||||||
|
private boolean[] tempEmojiLoaded;
|
||||||
|
|
||||||
|
private boolean[] getEmojiLoaded() {
|
||||||
|
if (!(getText() instanceof Spanned)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Emoji.EmojiSpan[] spans = ((Spanned) getText()).getSpans(0, getText().length(), Emoji.EmojiSpan.class);
|
||||||
|
if (spans == null || spans.length <= 0)
|
||||||
|
return null;
|
||||||
|
if (tempEmojiLoaded == null || tempEmojiLoaded.length != spans.length) {
|
||||||
|
tempEmojiLoaded = new boolean[spans.length];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < spans.length; ++i) {
|
||||||
|
tempEmojiLoaded[i] = spans[i].getDrawable() instanceof Emoji.EmojiDrawable && ((Emoji.EmojiDrawable) spans[i].getDrawable()).isLoaded();
|
||||||
|
}
|
||||||
|
return tempEmojiLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean emojiLoadedEquals(boolean[] a, boolean[] b) {
|
||||||
|
if (a == null && b == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((a == null ? 0 : a.length) != (b == null ? 0 : b.length)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int n = a == null ? 0 : a.length;
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
if (a[i] != b[i]) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasChanges() {
|
||||||
|
boolean a = false, b = false, c = false, d = false, e = false, f = false;
|
||||||
|
boolean[] emojiLoaded = null;
|
||||||
|
if (
|
||||||
|
(a = (ColorUtils.setAlphaComponent(textColor, 0xFF) != ColorUtils.setAlphaComponent(layout.getPaint().getColor(), 0xFF))) ||
|
||||||
|
(b = (ColorUtils.setAlphaComponent(linkColor, 0xFF) != ColorUtils.setAlphaComponent(layout.getPaint().linkColor, 0xFF))) ||
|
||||||
|
(c = (Math.abs(textSize - layout.getPaint().getTextSize()) > 0.1f)) ||
|
||||||
|
(d = (typeface != layout.getPaint().getTypeface())) ||
|
||||||
|
(e = (!lastLayoutBounds.equals(getLayoutBounds()))) ||
|
||||||
|
(f = (!emojiLoadedEquals(emojiLoaded = getEmojiLoaded(), lastEmojiLoaded)))
|
||||||
|
) {
|
||||||
|
// Log.i("lolkek", "draw \"" + getText() + "\" because " + (renderNode == null ? "first" : a ? "textcolor ["+Integer.toHexString(textColor) + " => "+Integer.toHexString(layout.getPaint().getColor())+"]" : (b ? "linkcolor" : (c ? "textsize" : (d ? "typeface" : (e ? "bounds" : (f ? "emojis" : "???")))))));
|
||||||
|
textColor = layout.getPaint().getColor();
|
||||||
|
linkColor = layout.getPaint().linkColor;
|
||||||
|
textSize = layout.getPaint().getTextSize();
|
||||||
|
typeface = layout.getPaint().getTypeface();
|
||||||
|
lastLayoutBounds.set(getLayoutBounds());
|
||||||
|
if (emojiLoaded != null) {
|
||||||
|
lastEmojiLoaded = emojiLoaded.clone();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final Rect bounds = new Rect();
|
||||||
|
|
||||||
|
private Rect getLayoutBounds() {
|
||||||
|
bounds.set(0, 0, layout.getWidth(), layout.getHeight());
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharSequence getText() {
|
||||||
|
return layout.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextPaint getPaint() {
|
||||||
|
return layout.getPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return layout.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return layout.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineCount() {
|
||||||
|
return layout.getLineCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineTop(int line) {
|
||||||
|
return layout.getLineTop(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineBottom(int line) {
|
||||||
|
return layout.getLineBottom(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getLineLeft(int line) {
|
||||||
|
return layout.getLineLeft(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getLineRight(int line) {
|
||||||
|
return layout.getLineRight(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getLineWidth(int line) {
|
||||||
|
return layout.getLineWidth(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPrimaryHorizontal(int x) {
|
||||||
|
return layout.getPrimaryHorizontal(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineEnd(int line) {
|
||||||
|
return layout.getLineEnd(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLineStart(int line) {
|
||||||
|
return layout.getLineStart(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue