merge official

This commit is contained in:
luvletter2333 2022-10-11 11:07:58 +08:00
commit 4c8b0b14fa
No known key found for this signature in database
GPG Key ID: A26A8880836E1978
255 changed files with 22743 additions and 3850 deletions

View File

@ -22,7 +22,7 @@ Bool *Bool::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in Bool", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in Bool", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -40,7 +40,7 @@ void TL_boolFalse::serializeToStream(NativeByteBuffer *stream) {
TL_dcOption *TL_dcOption::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_dcOption::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_dcOption", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_dcOption", constructor);
return nullptr;
}
TL_dcOption *result = new TL_dcOption();
@ -84,7 +84,7 @@ void TL_dcOption::serializeToStream(NativeByteBuffer *stream) {
TL_cdnPublicKey *TL_cdnPublicKey::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_cdnPublicKey::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_cdnPublicKey", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_cdnPublicKey", constructor);
return nullptr;
}
TL_cdnPublicKey *result = new TL_cdnPublicKey();
@ -106,7 +106,7 @@ void TL_cdnPublicKey::serializeToStream(NativeByteBuffer *stream) {
TL_cdnConfig *TL_cdnConfig::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_cdnConfig::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_cdnConfig", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_cdnConfig", constructor);
return nullptr;
}
TL_cdnConfig *result = new TL_cdnConfig();
@ -118,7 +118,7 @@ void TL_cdnConfig::readParams(NativeByteBuffer *stream, int32_t instanceNum, boo
int magic = stream->readInt32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
int count = stream->readInt32(&error);
@ -156,7 +156,7 @@ void TL_help_getCdnConfig::serializeToStream(NativeByteBuffer *stream) {
TL_config *TL_config::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_config::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_config", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_config", constructor);
return nullptr;
}
TL_config *result = new TL_config();
@ -173,7 +173,7 @@ void TL_config::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &
uint32_t magic = stream->readUint32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
int32_t count = stream->readInt32(&error);
@ -241,6 +241,9 @@ void TL_config::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &
if ((flags & 4) != 0) {
base_lang_pack_version = stream->readInt32(&error);
}
if ((flags & 32768) != 0) {
reactions_default = std::unique_ptr<Reaction>(Reaction::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
}
}
void TL_config::serializeToStream(NativeByteBuffer *stream) {
@ -313,6 +316,9 @@ void TL_config::serializeToStream(NativeByteBuffer *stream) {
if ((flags & 4) != 0) {
stream->writeInt32(base_lang_pack_version);
}
if ((flags & 32768) != 0 && reactions_default != nullptr) {
reactions_default->serializeToStream(stream);
}
}
TLObject *TL_help_getConfig::deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
@ -344,7 +350,7 @@ void TL_account_registerDevice::serializeToStream(NativeByteBuffer *stream) {
TL_restrictionReason *TL_restrictionReason::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_restrictionReason::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_restrictionReason", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_restrictionReason", constructor);
return nullptr;
}
TL_restrictionReason *result = new TL_restrictionReason();
@ -368,15 +374,15 @@ void TL_restrictionReason::serializeToStream(NativeByteBuffer *stream) {
User *User::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
User *result = nullptr;
switch (constructor) {
case 0xd3bc4b7a:
case TL_userEmpty::constructor:
result = new TL_userEmpty();
break;
case 0x3ff6ecb0:
case TL_user::constructor:
result = new TL_user();
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in User", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in User", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -423,7 +429,7 @@ void TL_user::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &er
uint32_t magic = stream->readUint32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
int32_t count = stream->readInt32(&error);
@ -513,7 +519,7 @@ InputPeer *InputPeer::TLdeserialize(NativeByteBuffer *stream, uint32_t construct
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in InputPeer", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in InputPeer", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -602,7 +608,7 @@ InputUser *InputUser::TLdeserialize(NativeByteBuffer *stream, uint32_t construct
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in InputUser", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in InputUser", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -700,7 +706,7 @@ MessageEntity *MessageEntity::TLdeserialize(NativeByteBuffer *stream, uint32_t c
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in MessageEntity", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in MessageEntity", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -916,7 +922,7 @@ void TL_messageEntityPhone::serializeToStream(NativeByteBuffer *stream) {
TL_dataJSON *TL_dataJSON::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_dataJSON::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_dataJSON", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_dataJSON", constructor);
return nullptr;
}
TL_dataJSON *result = new TL_dataJSON();
@ -936,7 +942,7 @@ void TL_dataJSON::serializeToStream(NativeByteBuffer *stream) {
TL_help_termsOfService *TL_help_termsOfService::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_help_termsOfService::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_help_termsOfService", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_help_termsOfService", constructor);
return nullptr;
}
TL_help_termsOfService *result = new TL_help_termsOfService();
@ -952,7 +958,7 @@ void TL_help_termsOfService::readParams(NativeByteBuffer *stream, int32_t instan
int magic = stream->readInt32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
int count = stream->readInt32(&error);
@ -996,7 +1002,7 @@ auth_Authorization *auth_Authorization::TLdeserialize(NativeByteBuffer *stream,
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in auth_Authorization", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in auth_Authorization", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -1038,7 +1044,7 @@ void TL_auth_authorization::serializeToStream(NativeByteBuffer *stream) {
TL_auth_exportedAuthorization *TL_auth_exportedAuthorization::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_auth_exportedAuthorization::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_auth_exportedAuthorization", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_auth_exportedAuthorization", constructor);
return nullptr;
}
TL_auth_exportedAuthorization *result = new TL_auth_exportedAuthorization();
@ -1101,7 +1107,7 @@ UserStatus *UserStatus::TLdeserialize(NativeByteBuffer *stream, uint32_t constru
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in UserStatus", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in UserStatus", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -1150,7 +1156,7 @@ FileLocation *FileLocation::TLdeserialize(NativeByteBuffer *stream, uint32_t con
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in FileLocation", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in FileLocation", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -1179,7 +1185,7 @@ UserProfilePhoto *UserProfilePhoto::TLdeserialize(NativeByteBuffer *stream, uint
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in UserProfilePhoto", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in UserProfilePhoto", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -1214,3 +1220,52 @@ void TL_userProfilePhoto::serializeToStream(NativeByteBuffer *stream) {
void TL_updatesTooLong::serializeToStream(NativeByteBuffer *stream) {
stream->writeInt32(constructor);
}
Reaction *Reaction::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
Reaction *result = nullptr;
switch (constructor) {
case 0x79f5d419:
result = new TL_reactionEmpty();
break;
case 0x8935fc73:
result = new TL_reactionCustomEmoji();
break;
case 0x1b2286b8:
result = new TL_reactionEmoji();
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in Reaction", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
return result;
}
void TL_reactionEmpty::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
}
void TL_reactionEmpty::serializeToStream(NativeByteBuffer *stream) {
stream->writeInt32(constructor);
}
void TL_reactionCustomEmoji::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
document_id = stream->readInt64(&error);
}
void TL_reactionCustomEmoji::serializeToStream(NativeByteBuffer *stream) {
stream->writeInt32(constructor);
stream->writeInt64(document_id);
}
void TL_reactionEmoji::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
emoticon = stream->readString(&error);
}
void TL_reactionEmoji::serializeToStream(NativeByteBuffer *stream) {
stream->writeInt32(constructor);
stream->writeString(emoticon);
}

View File

@ -95,10 +95,17 @@ public:
void serializeToStream(NativeByteBuffer *stream);
};
class Reaction : public TLObject {
public:
static Reaction *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
};
class TL_config : public TLObject {
public:
static const uint32_t constructor = 0x330b4067;
static const uint32_t constructor = 0x232566ac;
int32_t flags;
int32_t date;
@ -145,6 +152,7 @@ public:
std::string suggested_lang_code;
int32_t lang_pack_version;
int32_t base_lang_pack_version;
std::unique_ptr<Reaction> reactions_default;
static TL_config *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
@ -325,7 +333,7 @@ public:
class TL_user : public User {
public:
static const uint32_t constructor = 0x3ff6ecb0;
static const uint32_t constructor = 0x5d99adee;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
@ -736,4 +744,38 @@ public:
void serializeToStream(NativeByteBuffer *stream);
};
class TL_reactionCustomEmoji : public Reaction {
public:
static const uint32_t constructor = 0x8935fc73;
int64_t document_id;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_reactionEmoji : public Reaction {
public:
static const uint32_t constructor = 0x1b2286b8;
std::string emoticon;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
class TL_reactionEmpty : public Reaction {
public:
static const uint32_t constructor = 0x79f5d419;
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
void serializeToStream(NativeByteBuffer *stream);
};
#endif

View File

@ -32,6 +32,7 @@
#include "ByteArray.h"
#include "Config.h"
#include "ProxyCheckInfo.h"
#include "Handshake.h"
#ifdef ANDROID
#include <jni.h>
@ -1893,6 +1894,9 @@ void ConnectionsManager::switchBackend(bool restart) {
scheduleTask([&, restart] {
currentDatacenterId = 1;
testBackend = !testBackend;
if (!restart) {
Handshake::cleanupServerKeys();
}
datacenters.clear();
initDatacenters();
saveConfig();

View File

@ -39,6 +39,41 @@ void FileLog::init(std::string path) {
pthread_mutex_unlock(&mutex);
}
void FileLog::fatal(const char *message, ...) {
if (!LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
time_t t = time(0);
struct tm *now = localtime(&t);
#ifdef ANDROID
__android_log_vprint(ANDROID_LOG_FATAL, "tgnet", message, argptr);
va_end(argptr);
va_start(argptr, message);
#else
printf("%d-%d %02d:%02d:%02d FATAL ERROR: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
vprintf(message, argptr);
printf("\n");
fflush(stdout);
va_end(argptr);
va_start(argptr, message);
#endif
FILE *logFile = getInstance().logFile;
if (logFile) {
fprintf(logFile, "%d-%d %02d:%02d:%02d FATAL ERROR: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
vfprintf(logFile, message, argptr);
fprintf(logFile, "\n");
fflush(logFile);
}
va_end(argptr);
#ifdef DEBUG_VERSION
abort();
#endif
}
void FileLog::e(const char *message, ...) {
if (!LOGS_ENABLED) {
return;

View File

@ -15,6 +15,7 @@ class FileLog {
public:
FileLog();
void init(std::string path);
static void fatal(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void e(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void w(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void d(const char *message, ...) __attribute__((format (printf, 1, 2)));
@ -28,6 +29,7 @@ private:
extern bool LOGS_ENABLED;
#define DEBUG_FATAL FileLog::getInstance().fatal
#define DEBUG_E FileLog::getInstance().e
#define DEBUG_W FileLog::getInstance().w
#define DEBUG_D FileLog::getInstance().d

View File

@ -190,7 +190,7 @@ inline bool factorizeValue(uint64_t what, uint32_t &p, uint32_t &q) {
}
return true;
} else {
if (LOGS_ENABLED) DEBUG_E("factorization failed for %" PRIu64, what);
if (LOGS_ENABLED) DEBUG_FATAL("factorization failed for %" PRIu64, what);
p = 0;
q = 0;
return false;
@ -200,7 +200,7 @@ inline bool factorizeValue(uint64_t what, uint32_t &p, uint32_t &q) {
inline bool check_prime(BIGNUM *p) {
int result = 0;
if (!BN_primality_test(&result, p, 64, bnContext, 0, NULL)) {
if (LOGS_ENABLED) DEBUG_E("OpenSSL error at BN_primality_test");
if (LOGS_ENABLED) DEBUG_FATAL("OpenSSL error at BN_primality_test");
return false;
}
return result != 0;
@ -215,20 +215,20 @@ inline bool isGoodPrime(BIGNUM *p, uint32_t g) {
BIGNUM *dh_g = BN_new();
if (!BN_set_word(dh_g, 4 * g)) {
if (LOGS_ENABLED) DEBUG_E("OpenSSL error at BN_set_word(dh_g, 4 * g)");
if (LOGS_ENABLED) DEBUG_FATAL("OpenSSL error at BN_set_word(dh_g, 4 * g)");
BN_free(t);
BN_free(dh_g);
return false;
}
if (!BN_mod(t, p, dh_g, bnContext)) {
if (LOGS_ENABLED) DEBUG_E("OpenSSL error at BN_mod");
if (LOGS_ENABLED) DEBUG_FATAL("OpenSSL error at BN_mod");
BN_free(t);
BN_free(dh_g);
return false;
}
uint64_t x = BN_get_word(t);
if (x >= 4 * g) {
if (LOGS_ENABLED) DEBUG_E("OpenSSL error at BN_get_word");
if (LOGS_ENABLED) DEBUG_FATAL("OpenSSL error at BN_get_word");
BN_free(t);
BN_free(dh_g);
return false;
@ -316,6 +316,11 @@ inline bool isGoodGaAndGb(BIGNUM *g_a, BIGNUM *p) {
return true;
}
void Handshake::cleanupServerKeys() {
serverPublicKeys.clear();
serverPublicKeysFingerprints.clear();
}
void Handshake::processHandshakeResponse(TLObject *message, int64_t messageId) {
if (handshakeState == 0) {
return;

View File

@ -29,6 +29,7 @@ public:
void processHandshakeResponse(TLObject *message, int64_t messageId);
void onHandshakeConnectionConnected();
void onHandshakeConnectionClosed();
static void cleanupServerKeys();
HandshakeType getType();
ByteArray *getPendingAuthKey();
int64_t getPendingAuthKeyId();

View File

@ -111,7 +111,7 @@ void TL_api_response::readParamsEx(NativeByteBuffer *stream, uint32_t bytes, boo
TL_future_salt *TL_future_salt::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_future_salt::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_future_salt", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_future_salt", constructor);
return nullptr;
}
TL_future_salt *result = new TL_future_salt();
@ -128,7 +128,7 @@ void TL_future_salt::readParams(NativeByteBuffer *stream, int32_t instanceNum, b
TL_msgs_state_info *TL_msgs_state_info::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_msgs_state_info::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_msgs_state_info", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_msgs_state_info", constructor);
return nullptr;
}
TL_msgs_state_info *result = new TL_msgs_state_info();
@ -158,7 +158,7 @@ Server_DH_Params *Server_DH_Params::TLdeserialize(NativeByteBuffer *stream, uint
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in Server_DH_Params", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in Server_DH_Params", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -180,7 +180,7 @@ void TL_server_DH_params_ok::readParams(NativeByteBuffer *stream, int32_t instan
TL_resPQ *TL_resPQ::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_resPQ::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_resPQ", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_resPQ", constructor);
return nullptr;
}
TL_resPQ *result = new TL_resPQ();
@ -195,7 +195,7 @@ void TL_resPQ::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &e
uint32_t magic = stream->readUint32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
uint32_t count = stream->readUint32(&error);
@ -297,7 +297,7 @@ void TL_auth_dropTempAuthKeys::serializeToStream(NativeByteBuffer *stream) {
TL_pong *TL_pong::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_pong::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_pong", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_pong", constructor);
return nullptr;
}
TL_pong *result = new TL_pong();
@ -313,7 +313,7 @@ void TL_pong::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &er
TL_future_salts *TL_future_salts::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_future_salts::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_future_salts", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_future_salts", constructor);
return nullptr;
}
TL_future_salts *result = new TL_future_salts();
@ -349,7 +349,7 @@ RpcDropAnswer *RpcDropAnswer::TLdeserialize(NativeByteBuffer *stream, uint32_t c
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in RpcDropAnswer", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in RpcDropAnswer", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -384,7 +384,7 @@ Set_client_DH_params_answer *Set_client_DH_params_answer::TLdeserialize(NativeBy
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in Set_client_DH_params_answer", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in Set_client_DH_params_answer", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -420,7 +420,7 @@ BadMsgNotification *BadMsgNotification::TLdeserialize(NativeByteBuffer *stream,
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in BadMsgNotification", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in BadMsgNotification", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -443,7 +443,7 @@ void TL_bad_server_salt::readParams(NativeByteBuffer *stream, int32_t instanceNu
TL_msgs_state_req *TL_msgs_state_req::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_msgs_state_req::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_msgs_state_req", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_msgs_state_req", constructor);
return nullptr;
}
TL_msgs_state_req *result = new TL_msgs_state_req();
@ -455,7 +455,7 @@ void TL_msgs_state_req::readParams(NativeByteBuffer *stream, int32_t instanceNum
uint32_t magic = stream->readUint32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
uint32_t count = stream->readUint32(&error);
@ -489,7 +489,7 @@ MsgDetailedInfo *MsgDetailedInfo::TLdeserialize(NativeByteBuffer *stream, uint32
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in MsgDetailedInfo", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in MsgDetailedInfo", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -512,7 +512,7 @@ void TL_msg_detailed_info::readParams(NativeByteBuffer *stream, int32_t instance
TL_msg_copy *TL_msg_copy::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_msg_copy::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_msg_copy", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_msg_copy", constructor);
return nullptr;
}
TL_msg_copy *result = new TL_msg_copy();
@ -532,7 +532,7 @@ void TL_msg_copy::serializeToStream(NativeByteBuffer *stream) {
TL_msgs_all_info *TL_msgs_all_info::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_msgs_all_info::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_msgs_all_info", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_msgs_all_info", constructor);
return nullptr;
}
TL_msgs_all_info *result = new TL_msgs_all_info();
@ -544,7 +544,7 @@ void TL_msgs_all_info::readParams(NativeByteBuffer *stream, int32_t instanceNum,
uint32_t magic = stream->readUint32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
uint32_t count = stream->readUint32(&error);
@ -586,7 +586,7 @@ DestroySessionRes *DestroySessionRes::TLdeserialize(NativeByteBuffer *stream, ui
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in DestroySessionRes", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in DestroySessionRes", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -604,7 +604,7 @@ void TL_destroy_session_none::readParams(NativeByteBuffer *stream, int32_t insta
TL_msgs_ack *TL_msgs_ack::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_msgs_ack::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_msgs_ack", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_msgs_ack", constructor);
return nullptr;
}
TL_msgs_ack *result = new TL_msgs_ack();
@ -616,7 +616,7 @@ void TL_msgs_ack::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool
uint32_t magic = stream->readUint32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
uint32_t count = stream->readUint32(&error);
@ -642,7 +642,7 @@ void TL_msgs_ack::serializeToStream(NativeByteBuffer *stream) {
TL_msg_container *TL_msg_container::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_msg_container::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_msg_container", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_msg_container", constructor);
return nullptr;
}
TL_msg_container *result = new TL_msg_container();
@ -674,7 +674,7 @@ void TL_msg_container::serializeToStream(NativeByteBuffer *stream) {
TL_message *TL_message::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_message::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_message", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_message", constructor);
return nullptr;
}
TL_message *result = new TL_message();
@ -709,7 +709,7 @@ void TL_message::serializeToStream(NativeByteBuffer *stream) {
TL_msg_resend_req *TL_msg_resend_req::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_msg_resend_req::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_msg_resend_req", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_msg_resend_req", constructor);
return nullptr;
}
TL_msg_resend_req *result = new TL_msg_resend_req();
@ -721,7 +721,7 @@ void TL_msg_resend_req::readParams(NativeByteBuffer *stream, int32_t instanceNum
uint32_t magic = stream->readUint32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
uint32_t count = stream->readUint32(&error);
@ -771,7 +771,7 @@ void TL_client_DH_inner_data::serializeToStream(NativeByteBuffer *stream) {
TL_server_DH_inner_data *TL_server_DH_inner_data::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_server_DH_inner_data::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_server_DH_inner_data", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_server_DH_inner_data", constructor);
return nullptr;
}
TL_server_DH_inner_data *result = new TL_server_DH_inner_data();
@ -906,7 +906,7 @@ void TL_gzip_packed::serializeToStream(NativeByteBuffer *stream) {
TL_error *TL_error::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_error::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_error", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_error", constructor);
return nullptr;
}
TL_error *result = new TL_error();
@ -971,7 +971,7 @@ JSONValue *JSONValue::TLdeserialize(NativeByteBuffer *stream, uint32_t construct
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in JSONValue", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in JSONValue", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -981,7 +981,7 @@ JSONValue *JSONValue::TLdeserialize(NativeByteBuffer *stream, uint32_t construct
TL_jsonObjectValue *TL_jsonObjectValue::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_jsonObjectValue::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_jsonObjectValue", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_jsonObjectValue", constructor);
return nullptr;
}
TL_jsonObjectValue *result = new TL_jsonObjectValue();
@ -1028,7 +1028,7 @@ void TL_jsonArray::readParams(NativeByteBuffer *stream, int32_t instanceNum, boo
int magic = stream->readInt32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
int count = stream->readInt32(&error);
@ -1055,7 +1055,7 @@ void TL_jsonObject::readParams(NativeByteBuffer *stream, int32_t instanceNum, bo
int magic = stream->readInt32(&error);
if (magic != 0x1cb5c415) {
error = true;
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
if (LOGS_ENABLED) DEBUG_FATAL("wrong Vector magic, got %x", magic);
return;
}
int count = stream->readInt32(&error);
@ -1117,7 +1117,7 @@ IpPort *IpPort::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, in
break;
default:
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in IpPort", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in IpPort", constructor);
return nullptr;
}
result->readParams(stream, instanceNum, error);
@ -1155,7 +1155,7 @@ void TL_accessPointRule::readParams(NativeByteBuffer *stream, int32_t instanceNu
TL_help_configSimple *TL_help_configSimple::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
if (TL_help_configSimple::constructor != constructor) {
error = true;
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_help_configSimple", constructor);
if (LOGS_ENABLED) DEBUG_FATAL("can't parse magic %x in TL_help_configSimple", constructor);
return nullptr;
}
TL_help_configSimple *result = new TL_help_configSimple();

View File

@ -50,6 +50,7 @@
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera2" android:required="false" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

View File

@ -26,7 +26,6 @@ chat_inPreviewInstantSelectedText=-5648402
chat_attachAudioBackground=-626837
location_sendLocationBackground=-9919529
actionBarDefaultSubmenuBackground=-14075831
actionBarDefaultSubmenuSeparator=-14733761
switchTrackBlueThumb=-14866637
avatar_nameInMessageViolet=-6643205
emptyListPlaceholder=-8549479
@ -86,11 +85,13 @@ avatar_backgroundActionBarOrange=-14602949
windowBackgroundWhiteBlackText=-1
avatar_backgroundActionBarBlue=-14602949
dialogTextLink=-10177041
chat_outReactionButtonText=-1
chat_recordTime=-1
chat_status=-9192457
windowBackgroundWhiteBlueHeader=-8796932
files_folderIconBackground=-10637333
passport_authorizeBackgroundSelected=-11627561
chat_outReactionButtonBackground=-1
switchTrackBlueChecked=-8333825
player_seekBarBackground=1196577362
dialogShadowLine=335544320
@ -103,6 +104,7 @@ dialogInputField=-8549479
windowBackgroundWhiteInputFieldActivated=-9522449
chat_attachGalleryBackground=-11692299
chat_outInstantSelected=-4268038
actionBarDefaultSubmenuSeparator=-14733761
chat_outSentCheck=-7878657
key_graySectionText=-8549479
player_placeholder=-10191983
@ -112,7 +114,7 @@ groupcreate_spanBackground=-13878194
dialogButton=-10177041
contextProgressInner1=1686212251
chat_inLoaderPhotoIconSelected=-1
actionBarDefaultSubtitle=1859907071
actionBarDefaultSubtitle=2111566591
chat_inContactPhoneText=-8812393
chat_inlineResultIcon=-8796932
chat_outBubbleGradientSelectedOverlay=352321535
@ -187,7 +189,7 @@ statisticChartLine_golden=-2184161
statisticChartSignatureAlpha=-1946157057
chat_emojiPanelTrendingDescription=-8549479
calls_callReceivedGreenIcon=-12001930
chats_pinnedOverlay=16777215
chats_pinnedOverlay=150994943
windowBackgroundWhiteInputField=-12035217
avatar_backgroundRed=-1545110
statisticChartLine_green=-12729793
@ -250,7 +252,13 @@ chats_tabletSelectedOverlay=268435455
chat_outAudioDurationSelectedText=-4268038
chat_attachCameraIcon1=-32171
undo_background=-182112197
premiumGradientBackground3=-15525343
premiumGradientBackground4=-15328990
premiumGradientBackground1=-14604747
avatar_actionBarSelectorPink=-12758164
premiumGradientBackground2=-15394271
premiumStarGradient1=-15436801
premiumStarGradient2=-4167942
dialogTextHint=-8549479
statisticChartLine_orange=-1720817
chat_topPanelTitle=-9719066
@ -306,7 +314,7 @@ avatar_actionBarSelectorViolet=-12758164
chat_attachPollBackground=-2183099
avatar_nameInMessageBlue=-8796932
dialogTextBlack=-592138
actionBarDefault=-14602949
actionBarDefault=-14406343
location_placeLocationBackground=-9919529
profile_actionIcon=-1
windowBackgroundUnchecked=-14866637
@ -326,6 +334,7 @@ chat_goDownButtonCounter=-1
switchTrackBlueSelectorChecked=848091135
chat_outFileBackground=-12095334
chats_name=-1446156
premiumStartSmallStarsColor=1904435967
switchTrackBlueSelector=431611386
dialogBadgeBackground=-10177041
chat_outBubbleSelected=-11829841
@ -469,4 +478,4 @@ chat_topPanelBackground=-14602949
chat_outSentClock=-8213557
dialogBackgroundGray=-14932431
chat_searchPanelText=-8796932
chat_inContactIcon=-1
chat_inContactIcon=-1

View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; width:100%%; height:100%%; background-color:#000; }
html { width:100%%; height:100%%; background-color:#000; }
.embed-container iframe,
.embed-container object,
.embed-container embed {
position: absolute;
top: 0;
left: 0;
width: 100%% !important;
height: 100%% !important;
}
</style>
</head>
<body>
<div class="embed-container">
<div id="player"></div>
</div>
<script src="https://www.youtube.com/iframe_api"></script>
<script>
var player;
var posted = false;
YT.ready(function() {
player = new YT.Player("player", {
"width": "100%%",
"events": {
"onReady": "onReady",
"onError": "onError",
"onStateChange": "onStateChange",
},
"videoId": "%1$s",
"height": "100%%",
"playerVars": {
"start": %2$d,
"rel": 1,
"showinfo": 0,
"modestbranding": 0,
"iv_load_policy": 3,
"autohide": 1,
"autoplay": 1,
"cc_load_policy": 1,
"playsinline": 1,
"controls": 0
}
});
player.setSize(window.innerWidth, window.innerHeight);
});
function onError(event) {
if (!posted) {
if (window.YoutubeProxy !== undefined) {
YoutubeProxy.onPlayerLoaded();
}
posted = true;
}
}
function onStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !posted) {
if (window.YoutubeProxy !== undefined) {
YoutubeProxy.onPlayerLoaded();
}
posted = true;
}
if (window.YoutubeProxy !== undefined) {
YoutubeProxy.onPlayerStateChange(event.data);
}
}
function onReady(event) {
playVideo();
if (window.YoutubeProxy !== undefined) {
YoutubeProxy.onPlayerNotifyDuration(player.getDuration());
}
}
function playVideo() {
player.playVideo();
}
function pauseVideo() {
player.pauseVideo();
}
function seekTo(time, seekAhead) {
player.seekTo(time, seekAhead);
}
function setPlaybackSpeed(speed) {
player.setPlaybackRate(speed);
}
function pollPosition() {
if (window.YoutubeProxy !== undefined) {
YoutubeProxy.onPlayerNotifyCurrentPosition(player.getCurrentTime());
YoutubeProxy.onPlayerNotifyBufferedPosition(player.getVideoLoadedFraction());
}
}
window.onresize = function() {
player.setSize(window.innerWidth, window.innerHeight);
playVideo();
}
</script>
</body>
</html>

View File

@ -0,0 +1,76 @@
package org.telegram;
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class DispatchQueuePriority {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new PriorityBlockingQueue<>(10, new Comparator<Runnable>() {
@Override
public int compare(Runnable o1, Runnable o2) {
int priority1 = 1;
int priority2 = 1;
if (o1 instanceof PriorityRunnable) {
priority1 = ((PriorityRunnable) o1).priority;
}
if (o2 instanceof PriorityRunnable) {
priority2 = ((PriorityRunnable) o2).priority;
}
return priority2 - priority1;
}
}));
public DispatchQueuePriority(String threadName) {
}
public static Runnable wrap(Runnable runnable, int priority) {
if (priority == 1) {
return runnable;
} else {
return new PriorityRunnable(priority, runnable);
}
}
public void postRunnable(Runnable runnable) {
threadPoolExecutor.execute(runnable);
}
public Runnable postRunnable(Runnable runnable, int priority) {
if (priority == 1) {
postRunnable(runnable);
return runnable;
} else {
PriorityRunnable priorityRunnable = new PriorityRunnable(priority, runnable);
threadPoolExecutor.execute(priorityRunnable);
return priorityRunnable;
}
}
public void cancelRunnable(Runnable runnable) {
if (runnable == null) {
return;
}
threadPoolExecutor.remove(runnable);
}
private static class PriorityRunnable implements Runnable {
final int priority;
final Runnable runnable;
private PriorityRunnable(int priority, Runnable runnable) {
this.priority = priority;
this.runnable = runnable;
}
@Override
public void run() {
runnable.run();
}
}
}

View File

@ -46,6 +46,7 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.os.SystemClock;
@ -101,6 +102,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.core.graphics.ColorUtils;
import androidx.core.math.MathUtils;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringAnimation;
@ -137,6 +139,7 @@ import org.telegram.ui.Components.PickerBottomLayout;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.ShareAlert;
import org.telegram.ui.Components.TypefaceSpan;
import org.telegram.ui.Components.URLSpanReplacement;
import org.telegram.ui.ThemePreviewActivity;
import org.telegram.ui.WallpapersListActivity;
@ -227,7 +230,7 @@ public class AndroidUtilities {
private static AccessibilityManager accessibilityManager;
private static Vibrator vibrator;
private static Boolean isTablet = null, isSmallScreen = null;
private static Boolean isTablet = null, wasTablet = null, isSmallScreen = null;
private static int adjustOwnerClassGuid = 0;
private static int altFocusableClassGuid = 0;
@ -436,6 +439,10 @@ public class AndroidUtilities {
}
public static CharSequence replaceSingleTag(String str, Runnable runnable) {
return replaceSingleTag(str, null, runnable);
}
public static CharSequence replaceSingleTag(String str, String colorKey, Runnable runnable) {
int startIndex = str.indexOf("**");
int endIndex = str.indexOf("**", startIndex + 1);
str = str.replace("**", "");
@ -453,6 +460,9 @@ public class AndroidUtilities {
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
if (colorKey != null) {
ds.setColor(Theme.getColor(colorKey));
}
}
@Override
@ -594,12 +604,19 @@ public class AndroidUtilities {
}
public static boolean addLinks(Spannable text, int mask, boolean internalOnly) {
return addLinks(text, mask, internalOnly, true);
}
public static boolean addLinks(Spannable text, int mask, boolean internalOnly, boolean removeOldReplacements) {
if (text == null || containsUnsupportedCharacters(text.toString()) || mask == 0) {
return false;
}
final URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
for (int i = old.length - 1; i >= 0; i--) {
text.removeSpan(old[i]);
URLSpan o = old[i];
if (!(o instanceof URLSpanReplacement) || removeOldReplacements) {
text.removeSpan(o);
}
}
final ArrayList<LinkSpec> links = new ArrayList<>();
if (!internalOnly && (mask & Linkify.PHONE_NUMBERS) != 0) {
@ -616,8 +633,13 @@ public class AndroidUtilities {
LinkSpec link = links.get(a);
URLSpan[] oldSpans = text.getSpans(link.start, link.end, URLSpan.class);
if (oldSpans != null && oldSpans.length > 0) {
for (URLSpan oldSpan : oldSpans) {
text.removeSpan(oldSpan);
for (int b = 0; b < oldSpans.length; b++) {
URLSpan o = oldSpans[b];
text.removeSpan(o);
if (!(o instanceof URLSpanReplacement) || removeOldReplacements) {
text.removeSpan(o);
}
}
}
text.setSpan(new URLSpan(link.url), link.start, link.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
@ -855,34 +877,36 @@ public class AndroidUtilities {
final float lumG = 0.6094f;
final float lumB = 0.0820f;
colorMatrix.postConcat(new ColorMatrix(new float[] {
lumR*(1-x)+x,lumG*(1-x),lumB*(1-x),0,0,
lumR*(1-x),lumG*(1-x)+x,lumB*(1-x),0,0,
lumR*(1-x),lumG*(1-x),lumB*(1-x)+x,0,0,
0,0,0,1,0
colorMatrix.postConcat(new ColorMatrix(new float[]{
lumR * (1 - x) + x, lumG * (1 - x), lumB * (1 - x), 0, 0,
lumR * (1 - x), lumG * (1 - x) + x, lumB * (1 - x), 0, 0,
lumR * (1 - x), lumG * (1 - x), lumB * (1 - x) + x, 0, 0,
0, 0, 0, 1, 0
}));
}
public static void adjustBrightnessColorMatrix(ColorMatrix colorMatrix, float brightness) {
if (colorMatrix == null) {
return;
}
brightness *= 255;
colorMatrix.postConcat(new ColorMatrix(new float[] {
1,0,0,0,brightness,
0,1,0,0,brightness,
0,0,1,0,brightness,
0,0,0,1,0
colorMatrix.postConcat(new ColorMatrix(new float[]{
1, 0, 0, 0, brightness,
0, 1, 0, 0, brightness,
0, 0, 1, 0, brightness,
0, 0, 0, 1, 0
}));
}
public static void multiplyBrightnessColorMatrix(ColorMatrix colorMatrix, float v) {
if (colorMatrix == null) {
return;
}
colorMatrix.postConcat(new ColorMatrix(new float[] {
v,0,0,0,0,
0,v,0,0,0,
0,0,v,0,0,
0,0,0,1,0
colorMatrix.postConcat(new ColorMatrix(new float[]{
v, 0, 0, 0, 0,
0, v, 0, 0, 0,
0, 0, v, 0, 0,
0, 0, 0, 1, 0
}));
}
@ -1877,7 +1901,7 @@ public class AndroidUtilities {
roundPlayingMessageSize = (int) (AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(28));
} else {
roundMessageSize = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.6f);
roundPlayingMessageSize = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(28));
roundPlayingMessageSize = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(28));
}
roundMessageInset = dp(2);
}
@ -1991,7 +2015,7 @@ public class AndroidUtilities {
return ch == '-' || ch == '~';
}
public static boolean isTablet() {
public static boolean isTabletInternal() {
if (isTablet == null) switch (NekoConfig.tabletMode.Int()) {
case 0:
isTablet = ApplicationLoader.applicationContext != null && ApplicationLoader.applicationContext.getResources().getBoolean(R.bool.isTablet);
@ -2006,6 +2030,26 @@ public class AndroidUtilities {
return isTablet;
}
public static void resetTabletFlag() {
if (wasTablet == null) {
wasTablet = isTabletInternal();
}
isTablet = null;
SharedConfig.updateTabletConfig();
}
public static void resetWasTabletFlag() {
wasTablet = null;
}
public static Boolean getWasTablet() {
return wasTablet;
}
public static boolean isTablet() {
return isTabletInternal() && !SharedConfig.forceDisableTabletMode;
}
public static boolean isSmallScreen() {
if (isSmallScreen == null) {
isSmallScreen = (Math.max(displaySize.x, displaySize.y) - statusBarHeight - navigationBarHeight) / density <= 650;
@ -2516,18 +2560,8 @@ public class AndroidUtilities {
}
}*/
public static void startAppCenter(Activity context) {
}
private static long lastUpdateCheckTime;
public static void checkForUpdates() {
}
public static void appCenterLog(Throwable e) {
// ApplicationLoader.appCenterLog(e);
}
public static boolean shouldShowClipboardToast() {
@ -2576,7 +2610,7 @@ public class AndroidUtilities {
}
private static File getAlbumDir(boolean secretChat) {
if (secretChat || !BuildVars.NO_SCOPED_STORAGE ||(Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
if (secretChat || !BuildVars.NO_SCOPED_STORAGE || (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) {
return FileLoader.getDirectory(FileLoader.MEDIA_DIR_IMAGE);
}
File storageDir = null;
@ -2710,7 +2744,7 @@ public class AndroidUtilities {
if (type == 0) {
return "IMG_" + timeStamp + "." + (TextUtils.isEmpty(ext) ? "jpg" : ext);
} else {
return "VID_" + timeStamp + ".mp4";
return "VID_" + timeStamp + ".mp4";
}
}
@ -2784,6 +2818,7 @@ public class AndroidUtilities {
}
private static SimpleDateFormat generatingVideoPathFormat;
public static File generateVideoPath(boolean secretChat) {
try {
File storageDir = getAlbumDir(secretChat);
@ -4450,10 +4485,10 @@ public class AndroidUtilities {
public static void lerp(RectF a, RectF b, float f, RectF to) {
if (to != null) {
to.set(
AndroidUtilities.lerp(a.left, b.left, f),
AndroidUtilities.lerp(a.top, b.top, f),
AndroidUtilities.lerp(a.right, b.right, f),
AndroidUtilities.lerp(a.bottom, b.bottom, f)
AndroidUtilities.lerp(a.left, b.left, f),
AndroidUtilities.lerp(a.top, b.top, f),
AndroidUtilities.lerp(a.right, b.right, f),
AndroidUtilities.lerp(a.bottom, b.bottom, f)
);
}
}
@ -4461,20 +4496,24 @@ public class AndroidUtilities {
public static void lerp(Rect a, Rect b, float f, Rect to) {
if (to != null) {
to.set(
AndroidUtilities.lerp(a.left, b.left, f),
AndroidUtilities.lerp(a.top, b.top, f),
AndroidUtilities.lerp(a.right, b.right, f),
AndroidUtilities.lerp(a.bottom, b.bottom, f)
AndroidUtilities.lerp(a.left, b.left, f),
AndroidUtilities.lerp(a.top, b.top, f),
AndroidUtilities.lerp(a.right, b.right, f),
AndroidUtilities.lerp(a.bottom, b.bottom, f)
);
}
}
public static float cascade(float fullAnimationT, int position, int count, float waveLength) {
public static float cascade(float fullAnimationT, float position, float count, float waveLength) {
final float waveDuration = 1f / count * waveLength;
final float waveOffset = position / (float) count * (1f - waveDuration);
final float waveOffset = position / count * (1f - waveDuration);
return MathUtils.clamp((fullAnimationT - waveOffset) / waveDuration, 0, 1);
}
public static int multiplyAlphaComponent(int color, float k) {
return ColorUtils.setAlphaComponent(color, (int) (Color.alpha(color) * k));
}
public static float computeDampingRatio(float tension /* stiffness */, float friction /* damping */, float mass) {
return friction / (2f * (float) Math.sqrt(mass * tension));
}
@ -4507,6 +4546,7 @@ public class AndroidUtilities {
}
private static final HashMap<Window, ArrayList<Long>> flagSecureReasons = new HashMap<>();
// Sets FLAG_SECURE to true, until it gets unregistered (when returned callback is run)
// Useful for having multiple reasons to have this flag on.
public static Runnable registerFlagSecure(Window window) {
@ -4526,6 +4566,7 @@ public class AndroidUtilities {
updateFlagSecure(window);
};
}
private static void updateFlagSecure(Window window) {
if (Build.VERSION.SDK_INT >= 23) {
if (window == null) {
@ -4538,7 +4579,8 @@ public class AndroidUtilities {
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
}
} catch (Exception ignore) {}
} catch (Exception ignore) {
}
}
}
@ -4574,7 +4616,7 @@ public class AndroidUtilities {
return "";
}
private static char[] characters = new char[] {' ', ' ', '!', '"', '#', '%', '&', '\'', '(', ')', '*', ',', '-', '.', '/', ':', ';', '?', '@', '[', '\\', ']', '_', '{', '}', '¡', '§', '«', '¶', '·', '»', '¿', ';', '·', '՚', '՛', '՜', '՝', '՞', '՟', '։', '֊', '־', '׀', '׃', '׆', '׳', '״', '؉', '؊', '،', '؍', '؛', '؞', '؟', '٪', '٫', '٬', '٭', '۔', '܀', '܁', '܂', '܃', '܄', '܅', '܆', '܇', '܈', '܉', '܊', '܋', '܌', '܍', '߷', '߸', '߹', '࠰', '࠱', '࠲', '࠳', '࠴', '࠵', '࠶', '࠷', '࠸', '࠹', '࠺', '࠻', '࠼', '࠽', '࠾', '࡞', '।', '॥', '॰', '৽', '੶', '૰', '౷', '಄', '෴', '๏', '๚', '๛', '༄', '༅', '༆', '༇', '༈', '༉', '༊', '་', '༌', '།', '༎', '༏', '༐', '༑', '༒', '༔', '༺', '༻', '༼', '༽', '྅', '࿐', '࿑', '࿒', '࿓', '࿔', '࿙', '࿚', '၊', '။', '၌', '၍', '၎', '၏', '჻', '፠', '፡', '።', '፣', '፤', '፥', '፦', '፧', '፨', '', '', '᚛', '᚜', '᛫', '', '', '', '᜶', '។', '៕', '៖', '៘', '៙', '៚', '᠀', '᠁', '᠂', '', '᠄', '᠅', '᠆', '᠇', '᠈', '', '᠊', '᥄', '᥅', '᨞', '᨟', '᪠', '᪡', '᪢', '᪣', '᪤', '᪥', '᪦', '᪨', '᪩', '᪪', '᪫', '᪬', '᪭', '᭚', '᭛', '᭜', '᭝', '᭞', '᭟', '᭠', '᯼', '᯽', '᯾', '᯿', '᰻', '᰼', '᰽', '᰾', '᰿', '᱾', '᱿', '᳀', '᳁', '᳂', '᳃', '᳄', '᳅', '᳆', '᳇', '᳓', '', '', '', '', '—', '―', '‖', '‗', '', '', '', '', '“', '”', '„', '‟', '†', '‡', '•', '‣', '', '‥', '…', '‧', '‰', '‱', '', '″', '‴', '', '‶', '‷', '‸', '', '', '※', '‼', '‽', '‾', '‿', '⁀', '', '⁂', '', '⁅', '⁆', '⁇', '⁈', '⁉', '⁊', '⁋', '⁌', '⁍', '', '⁏', '⁐', '⁑', '', '⁔', '⁕', '⁖', '⁗', '⁘', '⁙', '', '⁛', '⁜', '⁝', '⁞', '⁽', '⁾', '₍', '₎', '⌈', '⌉', '⌊', '⌋', '〈', '〉', '', '', '❪', '❫', '❬', '❭', '', '', '❰', '❱', '', '', '', '', '⟅', '⟆', '⟦', '⟧', '⟨', '⟩', '⟪', '⟫', '⟬', '⟭', '⟮', '⟯', '⦃', '⦄', '⦅', '⦆', '⦇', '⦈', '⦉', '⦊', '⦋', '⦌', '⦍', '⦎', '⦏', '⦐', '⦑', '⦒', '⦓', '⦔', '⦕', '⦖', '⦗', '⦘', '⧘', '⧙', '⧚', '⧛', '⧼', '⧽', '⳹', '⳺', '⳻', '⳼', '⳾', '⳿', '⵰', '⸀', '⸁', '⸂', '⸃', '⸄', '⸅', '⸆', '⸇', '⸈', '⸉', '⸊', '⸋', '⸌', '⸍', '⸎', '⸏', '⸐', '⸑', '⸒', '⸓', '⸔', '⸕', '⸖', '⸗', '⸘', '⸙', '⸚', '⸛', '⸜', '⸝', '⸞', '⸟', '⸠', '⸡', '⸢', '⸣', '⸤', '⸥', '⸦', '⸧', '⸨', '⸩', '⸪', '⸫', '⸬', '⸭', '⸮', '⸰', '⸱', '⸲', '⸳', '⸴', '⸵', '⸶', '⸷', '⸸', '⸹', '⸺', '⸻', '⸼', '⸽', '⸾', '⸿', '', '⹁', '⹂', '⹃', '⹄', '⹅', '⹆', '⹇', '⹈', '⹉', '⹊', '⹋', '⹌', '⹍', '⹎', '⹏', '、', '。', '〃', '〈', '〉', '《', '》', '「', '」', '『', '』', '【', '】', '', '', '〖', '〗', '〘', '〙', '〚', '〛', '〜', '〝', '〞', '〟', '〰', '〽', '', '・', '꓾', '', '꘍', '', '꘏', '꙳', '꙾', '꛲', '꛳', '꛴', '꛵', '꛶', '꛷', '꡴', '꡵', '꡶', '꡷', '꣎', '꣏', '꣸', '꣹', '꣺', '꣼', '꤮', '꤯', '꥟', '꧁', '꧂', '꧃', '꧄', '꧅', '꧆', '꧇', '꧈', '꧉', '꧊', '꧋', '꧌', '꧍', '꧞', '꧟', '꩜', '꩝', '꩞', '꩟', '꫞', '꫟', '꫰', '꫱', '꯫', '', '﴿', '︐', '︑', '︒', '︓', '︔', '︕', '︖', '︗', '︘', '︙', '', '︱', '︲', '︳', '︴', '︵', '︶', '︷', '︸', '︹', '︺', '︻', '︼', '︽', '︾', '︿', '﹀', '﹁', '﹂', '﹃', '﹄', '﹅', '﹆', '﹇', '﹈', '﹉', '﹊', '﹋', '﹌', '', '', '', '﹐', '﹑', '﹒', '﹔', '﹕', '﹖', '﹗', '', '﹙', '﹚', '﹛', '﹜', '﹝', '﹞', '﹟', '﹠', '﹡', '﹣', '', '﹪', '﹫', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '_', '', '', '⦅', '⦆', '。', '「', '」', '、', '・'};
private static char[] characters = new char[]{' ', ' ', '!', '"', '#', '%', '&', '\'', '(', ')', '*', ',', '-', '.', '/', ':', ';', '?', '@', '[', '\\', ']', '_', '{', '}', '¡', '§', '«', '¶', '·', '»', '¿', ';', '·', '՚', '՛', '՜', '՝', '՞', '՟', '։', '֊', '־', '׀', '׃', '׆', '׳', '״', '؉', '؊', '،', '؍', '؛', '؞', '؟', '٪', '٫', '٬', '٭', '۔', '܀', '܁', '܂', '܃', '܄', '܅', '܆', '܇', '܈', '܉', '܊', '܋', '܌', '܍', '߷', '߸', '߹', '࠰', '࠱', '࠲', '࠳', '࠴', '࠵', '࠶', '࠷', '࠸', '࠹', '࠺', '࠻', '࠼', '࠽', '࠾', '࡞', '।', '॥', '॰', '৽', '੶', '૰', '౷', '಄', '෴', '๏', '๚', '๛', '༄', '༅', '༆', '༇', '༈', '༉', '༊', '་', '༌', '།', '༎', '༏', '༐', '༑', '༒', '༔', '༺', '༻', '༼', '༽', '྅', '࿐', '࿑', '࿒', '࿓', '࿔', '࿙', '࿚', '၊', '။', '၌', '၍', '၎', '၏', '჻', '፠', '፡', '።', '፣', '፤', '፥', '፦', '፧', '፨', '', '', '᚛', '᚜', '᛫', '', '', '', '᜶', '។', '៕', '៖', '៘', '៙', '៚', '᠀', '᠁', '᠂', '', '᠄', '᠅', '᠆', '᠇', '᠈', '', '᠊', '᥄', '᥅', '᨞', '᨟', '᪠', '᪡', '᪢', '᪣', '᪤', '᪥', '᪦', '᪨', '᪩', '᪪', '᪫', '᪬', '᪭', '᭚', '᭛', '᭜', '᭝', '᭞', '᭟', '᭠', '᯼', '᯽', '᯾', '᯿', '᰻', '᰼', '᰽', '᰾', '᰿', '᱾', '᱿', '᳀', '᳁', '᳂', '᳃', '᳄', '᳅', '᳆', '᳇', '᳓', '', '', '', '', '—', '―', '‖', '‗', '', '', '', '', '“', '”', '„', '‟', '†', '‡', '•', '‣', '', '‥', '…', '‧', '‰', '‱', '', '″', '‴', '', '‶', '‷', '‸', '', '', '※', '‼', '‽', '‾', '‿', '⁀', '', '⁂', '', '⁅', '⁆', '⁇', '⁈', '⁉', '⁊', '⁋', '⁌', '⁍', '', '⁏', '⁐', '⁑', '', '⁔', '⁕', '⁖', '⁗', '⁘', '⁙', '', '⁛', '⁜', '⁝', '⁞', '⁽', '⁾', '₍', '₎', '⌈', '⌉', '⌊', '⌋', '〈', '〉', '', '', '❪', '❫', '❬', '❭', '', '', '❰', '❱', '', '', '', '', '⟅', '⟆', '⟦', '⟧', '⟨', '⟩', '⟪', '⟫', '⟬', '⟭', '⟮', '⟯', '⦃', '⦄', '⦅', '⦆', '⦇', '⦈', '⦉', '⦊', '⦋', '⦌', '⦍', '⦎', '⦏', '⦐', '⦑', '⦒', '⦓', '⦔', '⦕', '⦖', '⦗', '⦘', '⧘', '⧙', '⧚', '⧛', '⧼', '⧽', '⳹', '⳺', '⳻', '⳼', '⳾', '⳿', '⵰', '⸀', '⸁', '⸂', '⸃', '⸄', '⸅', '⸆', '⸇', '⸈', '⸉', '⸊', '⸋', '⸌', '⸍', '⸎', '⸏', '⸐', '⸑', '⸒', '⸓', '⸔', '⸕', '⸖', '⸗', '⸘', '⸙', '⸚', '⸛', '⸜', '⸝', '⸞', '⸟', '⸠', '⸡', '⸢', '⸣', '⸤', '⸥', '⸦', '⸧', '⸨', '⸩', '⸪', '⸫', '⸬', '⸭', '⸮', '⸰', '⸱', '⸲', '⸳', '⸴', '⸵', '⸶', '⸷', '⸸', '⸹', '⸺', '⸻', '⸼', '⸽', '⸾', '⸿', '', '⹁', '⹂', '⹃', '⹄', '⹅', '⹆', '⹇', '⹈', '⹉', '⹊', '⹋', '⹌', '⹍', '⹎', '⹏', '、', '。', '〃', '〈', '〉', '《', '》', '「', '」', '『', '』', '【', '】', '', '', '〖', '〗', '〘', '〙', '〚', '〛', '〜', '〝', '〞', '〟', '〰', '〽', '', '・', '꓾', '', '꘍', '', '꘏', '꙳', '꙾', '꛲', '꛳', '꛴', '꛵', '꛶', '꛷', '꡴', '꡵', '꡶', '꡷', '꣎', '꣏', '꣸', '꣹', '꣺', '꣼', '꤮', '꤯', '꥟', '꧁', '꧂', '꧃', '꧄', '꧅', '꧆', '꧇', '꧈', '꧉', '꧊', '꧋', '꧌', '꧍', '꧞', '꧟', '꩜', '꩝', '꩞', '꩟', '꫞', '꫟', '꫰', '꫱', '꯫', '', '﴿', '︐', '︑', '︒', '︓', '︔', '︕', '︖', '︗', '︘', '︙', '', '︱', '︲', '︳', '︴', '︵', '︶', '︷', '︸', '︹', '︺', '︻', '︼', '︽', '︾', '︿', '﹀', '﹁', '﹂', '﹃', '﹄', '﹅', '﹆', '﹇', '﹈', '﹉', '﹊', '﹋', '﹌', '', '', '', '﹐', '﹑', '﹒', '﹔', '﹕', '﹖', '﹗', '', '﹙', '﹚', '﹛', '﹜', '﹝', '﹞', '﹟', '﹠', '﹡', '﹣', '', '﹪', '﹫', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '_', '', '', '⦅', '⦆', '。', '「', '」', '、', '・'};
//private static String[] longCharacters = new String[] {"𐄀", "𐄁", "𐄂", "𐎟", "𐏐", "𐕯", "𐡗", "𐤟", "𐤿", "𐩐", "𐩑", "𐩒", "𐩓", "𐩔", "𐩕", "𐩖", "𐩗", "𐩘", "𐩿", "𐫰", "𐫱", "𐫲", "𐫳", "𐫴", "𐫵", "𐫶", "𐬹", "𐬺", "𐬻", "𐬼", "𐬽", "𐬾", "𐬿", "𐮙", "𐮚", "𐮛", "𐮜", "𐽕", "𐽖", "𐽗", "𐽘", "𐽙", "𑁇", "𑁈", "𑁉", "𑁊", "𑁋", "𑁌", "𑁍", "𑂻", "𑂼", "𑂾", "𑂿", "𑃀", "𑃁", "𑅀", "𑅁", "𑅂", "𑅃", "𑅴", "𑅵", "𑇅", "𑇆", "𑇇", "𑇈", "𑇍", "𑇛", "𑇝", "𑇞", "𑇟", "𑈸", "𑈹", "𑈺", "𑈻", "𑈼", "𑈽", "𑊩", "𑑋", "𑑌", "𑑍", "𑑎", "𑑏", "𑑛", "𑑝", "𑓆", "𑗁", "𑗂", "𑗃", "𑗄", "𑗅", "𑗆", "𑗇", "𑗈", "𑗉", "𑗊", "𑗋", "𑗌", "𑗍", "𑗎", "𑗏", "𑗐", "𑗑", "𑗒", "𑗓", "𑗔", "𑗕", "𑗖", "𑗗", "𑙁", "𑙂", "𑙃", "𑙠", "𑙡", "𑙢", "𑙣", "𑙤", "𑙥", "𑙦", "𑙧", "𑙨", "𑙩", "𑙪", "𑙫", "𑙬", "𑜼", "𑜽", "𑜾", "𑠻", "𑧢", "𑨿", "𑩀", "𑩁", "𑩂", "𑩃", "𑩄", "𑩅", "𑩆", "𑪚", "𑪛", "𑪜", "𑪞", "𑪟", "𑪠", "𑪡", "𑪢", "𑱁", "𑱂", "𑱃", "𑱄", "𑱅", "𑱰", "𑱱", "𑻷", "𑻸", "𑿿", "𒑰", "𒑱", "𒑲", "𒑳", "𒑴", "𖩮", "𖩯", "𖫵", "𖬷", "𖬸", "𖬹", "𖬺", "𖬻", "𖭄", "𖺗", "𖺘", "𖺙", "𖺚", "𖿢", "𛲟", "𝪇", "𝪈", "𝪉", "𝪊", "𝪋", "𞥞", "𞥟"};
private static HashSet<Character> charactersMap;
@ -4675,6 +4717,7 @@ public class AndroidUtilities {
}
private static HashMap<Window, ValueAnimator> navigationBarColorAnimators;
public interface IntColorCallback {
public void run(int color);
}
@ -4703,7 +4746,8 @@ public class AndroidUtilities {
}
try {
window.setNavigationBarColor(color);
} catch (Exception ignore) {}
} catch (Exception ignore) {
}
} else {
ValueAnimator animator = ValueAnimator.ofArgb(window.getNavigationBarColor(), color);
animator.addUpdateListener(a -> {
@ -4713,7 +4757,8 @@ public class AndroidUtilities {
}
try {
window.setNavigationBarColor(tcolor);
} catch (Exception ignore) {}
} catch (Exception ignore) {
}
});
animator.addListener(new AnimatorListenerAdapter() {
@Override

View File

@ -381,6 +381,7 @@ public class ApplicationLoader extends Application {
LocaleController.getInstance().onDeviceConfigurationChange(newConfig);
AndroidUtilities.checkDisplaySize(applicationContext, newConfig);
VideoCapturerDevice.checkScreenCapturerSize();
AndroidUtilities.resetTabletFlag();
} catch (Exception e) {
e.printStackTrace();
}
@ -569,4 +570,29 @@ public class ApplicationLoader extends Application {
}
return result;
}
public static void startAppCenter(Activity context) {
applicationLoaderInstance.startAppCenterInternal(context);
}
public static void checkForUpdates() {
applicationLoaderInstance.checkForUpdatesInternal();
}
public static void appCenterLog(Throwable e) {
applicationLoaderInstance.appCenterLogInternal(e);
}
protected void appCenterLogInternal(Throwable e) {
}
protected void checkForUpdatesInternal() {
}
protected void startAppCenterInternal(Activity context) {
}
}

View File

@ -35,7 +35,7 @@ public class AutoMessageReplyReceiver extends BroadcastReceiver {
if (dialogId == 0 || maxId == 0 || !UserConfig.isValidAccount(currentAccount)) {
return;
}
SendMessagesHelper.getInstance(currentAccount).sendMessage(text.toString(), dialogId, null, null, null, true, null, null, null, true, 0, null);
SendMessagesHelper.getInstance(currentAccount).sendMessage(text.toString(), dialogId, null, null, null, true, null, null, null, true, 0, null, false);
MessagesController.getInstance(currentAccount).markDialogAsRead(dialogId, maxId, maxId, 0, false, 0, 0, true, 0);
}
}

View File

@ -6,15 +6,15 @@ import android.os.VibrationEffect;
import androidx.annotation.RequiresApi;
public enum BotWebViewVibrationEffect {
IMPACT_LIGHT(new long[] {7}, new int[] {65}, new long[] {50}),
IMPACT_MEDIUM(new long[] {7}, new int[] {145}, new long[] {50}),
IMPACT_HEAVY(new long[] {7}, new int[] {255}, new long[] {50}),
IMPACT_LIGHT(new long[] {7}, new int[] {65}, new long[] {60}),
IMPACT_MEDIUM(new long[] {7}, new int[] {145}, new long[] {70}),
IMPACT_HEAVY(new long[] {7}, new int[] {255}, new long[] {80}),
IMPACT_RIGID(new long[] {3}, new int[] {225}, new long[] {50}),
IMPACT_SOFT(new long[] {10}, new int[] {175}, new long[] {50}),
NOTIFICATION_ERROR(new long[] {14,48,14,48,14,48,20}, new int[] {200,0,200,0,255,0,145}, new long[] {50}),
NOTIFICATION_SUCCESS(new long[] {14,65,14}, new int[] {175,0,255}, new long[] {50}),
NOTIFICATION_WARNING(new long[] {14,64,14}, new int[] {225,0,175}, new long[] {50}),
SELECTION_CHANGE(new long[] {1}, new int[] {65}, new long[] {50});
IMPACT_SOFT(new long[] {10}, new int[] {175}, new long[] {55}),
NOTIFICATION_ERROR(new long[] {14,48,14,48,14,48,20}, new int[] {200,0,200,0,255,0,145}, new long[] {40,60,40,60,65,60,40}),
NOTIFICATION_SUCCESS(new long[] {14,65,14}, new int[] {175,0,255}, new long[] {50,60,65}),
NOTIFICATION_WARNING(new long[] {14,64,14}, new int[] {225,0,175}, new long[] {65,60,40}),
SELECTION_CHANGE(new long[] {1}, new int[] {65}, new long[] {30});
public final long[] timings;
public final int[] amplitudes;

View File

@ -17,7 +17,7 @@ import android.os.Build;
@SuppressWarnings("ConstantConditions")
public class BuildVars {
public static final boolean IS_BILLING_UNAVAILABLE = false;
public static final boolean IS_BILLING_UNAVAILABLE = true;
public static boolean DEBUG_VERSION = BuildConfig.BUILD_TYPE.equals("debug");
public static boolean DEBUG_PRIVATE_VERSION = DEBUG_VERSION;
public static boolean LOGS_ENABLED = DEBUG_PRIVATE_VERSION;

View File

@ -61,6 +61,21 @@ public class ChatObject {
private static final int MAX_PARTICIPANTS_COUNT = 5000;
public static boolean reactionIsAvailable(TLRPC.ChatFull chatInfo, String reaction) {
if (chatInfo.available_reactions instanceof TLRPC.TL_chatReactionsAll) {
return true;
}
if (chatInfo.available_reactions instanceof TLRPC.TL_chatReactionsSome) {
TLRPC.TL_chatReactionsSome someReactions = (TLRPC.TL_chatReactionsSome) chatInfo.available_reactions;
for (int i = 0; i < someReactions.reactions.size(); i++) {
if (someReactions.reactions.get(i) instanceof TLRPC.TL_reactionEmoji && TextUtils.equals(((TLRPC.TL_reactionEmoji) someReactions.reactions.get(i)).emoticon, reaction)) {
return true;
}
}
}
return false;
}
public static class Call {
public final static int RECORD_TYPE_AUDIO = 0,
RECORD_TYPE_VIDEO_PORTAIT = 1,

View File

@ -852,10 +852,10 @@ public class DownloadController extends BaseController implements NotificationCe
} else {
cacheType = 0;
}
getFileLoader().loadFile(ImageLocation.getForPhoto(photoSize, photo), downloadObject.parent, null, 0, cacheType);
getFileLoader().loadFile(ImageLocation.getForPhoto(photoSize, photo), downloadObject.parent, null, FileLoader.PRIORITY_LOW, cacheType);
} else if (downloadObject.object instanceof TLRPC.Document) {
TLRPC.Document document = (TLRPC.Document) downloadObject.object;
getFileLoader().loadFile(document, downloadObject.parent, 0, downloadObject.secret ? 2 : 0);
getFileLoader().loadFile(document, downloadObject.parent, FileLoader.PRIORITY_LOW, downloadObject.secret ? 2 : 0);
} else {
added = false;
}
@ -1143,7 +1143,7 @@ public class DownloadController extends BaseController implements NotificationCe
}
}
if (!contains) {
downloadingFiles.add(parentObject);
downloadingFiles.add(0, parentObject);
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
NativeByteBuffer data = new NativeByteBuffer(parentObject.messageOwner.getObjectSize());
@ -1358,6 +1358,24 @@ public class DownloadController extends BaseController implements NotificationCe
});
}
public void swapLoadingPriority(MessageObject o1, MessageObject o2) {
int index1 = downloadingFiles.indexOf(o1);
int index2 = downloadingFiles.indexOf(o2);
if (index1 >= 0 && index2 >= 0) {
downloadingFiles.set(index1, o2);
downloadingFiles.set(index2, o1);
}
updateFilesLoadingPriority();
}
public void updateFilesLoadingPriority() {
for (int i = downloadingFiles.size() - 1; i >= 0 ; i--) {
if (getFileLoader().isLoadingFile(downloadingFiles.get(i).getFileName())) {
getFileLoader().loadFile(downloadingFiles.get(i).getDocument(), downloadingFiles.get(i), FileLoader.PRIORITY_NORMAL_UP, 0);
}
}
}
public void clearRecentDownloadedFiles() {
recentDownloadingFiles.clear();
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);
@ -1391,7 +1409,7 @@ public class DownloadController extends BaseController implements NotificationCe
}
}
messageObjects.get(i).putInDownloadsStore = false;
FileLoader.getInstance(currentAccount).loadFile(messageObjects.get(i).getDocument(), messageObjects.get(i), 0, 0);
FileLoader.getInstance(currentAccount).loadFile(messageObjects.get(i).getDocument(), messageObjects.get(i), FileLoader.PRIORITY_LOW, 0);
FileLoader.getInstance(currentAccount).cancelLoadFile(messageObjects.get(i).getDocument(), true);
}
getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged);

View File

@ -30,6 +30,18 @@ import tw.nekomimi.nekogram.NekoConfig;
public class FileLoadOperation {
FileLoadOperationStream stream;
boolean streamPriority;
long streamOffset;
public static volatile DispatchQueue filesQueue = new DispatchQueue("writeFileQueue");
public void setStream(FileLoadOperationStream stream, boolean streamPriority, long streamOffset) {
this.stream = stream;
this.streamOffset = streamOffset;
this.streamPriority = streamPriority;
}
protected static class RequestInfo {
private int requestToken;
private long offset;
@ -84,7 +96,6 @@ public class FileLoadOperation {
private String fileName;
private String storeFileName;
private int currentQueueType;
private HashMap<Long, PreloadRange> preloadedBytesRanges;
private HashMap<Long, Integer> requestedPreloadedBytesRanges;
@ -182,6 +193,7 @@ public class FileLoadOperation {
private int currentType;
public FilePathDatabase.PathData pathSaveData;
private long startTime;
private FileLoaderPriorityQueue priorityQueue;
public interface FileLoadOperationDelegate {
void didFinishLoadingFile(FileLoadOperation operation, File finalFile);
@ -398,17 +410,17 @@ public class FileLoadOperation {
return priority;
}
public void setPaths(int instance, String name, int queueType, File store, File temp, String finalName) {
storePath = store;
tempPath = temp;
currentAccount = instance;
fileName = name;
storeFileName = finalName;
currentQueueType = queueType;
public void setPaths(int instance, String name, FileLoaderPriorityQueue priorityQueue, File store, File temp, String finalName) {
this.storePath = store;
this.tempPath = temp;
this.currentAccount = instance;
this.fileName = name;
this.storeFileName = finalName;
this.priorityQueue = priorityQueue;
}
public int getQueueType() {
return currentQueueType;
public FileLoaderPriorityQueue getQueue() {
return priorityQueue;
}
public boolean wasStarted() {
@ -460,6 +472,8 @@ public class FileLoadOperation {
}
}
long totalTime;
private void addPart(ArrayList<Range> ranges, long start, long end, boolean save) {
if (ranges == null || end < start) {
return;
@ -495,18 +509,28 @@ public class FileLoadOperation {
}
if (save) {
if (modified) {
try {
filePartsStream.seek(0);
count = ranges.size();
filePartsStream.writeInt(count);
for (int a = 0; a < count; a++) {
range = ranges.get(a);
filePartsStream.writeLong(range.start);
filePartsStream.writeLong(range.end);
ArrayList<FileLoadOperation.Range> rangesFinal = new ArrayList<>(ranges);
filesQueue.postRunnable(() -> {
long time = System.currentTimeMillis();
try {
synchronized (FileLoadOperation.this) {
if (filePartsStream == null) {
return;
}
filePartsStream.seek(0);
int countFinal = rangesFinal.size();
filePartsStream.writeInt(countFinal);
for (int a = 0; a < countFinal; a++) {
Range rangeFinal = rangesFinal.get(a);
filePartsStream.writeLong(rangeFinal.start);
filePartsStream.writeLong(rangeFinal.end);
}
}
} catch (Exception e) {
FileLog.e(e);
}
} catch (Exception e) {
FileLog.e(e);
}
totalTime += System.currentTimeMillis() - time;
});
notifyStreamListeners();
} else {
if (BuildVars.LOGS_ENABLED) {
@ -637,7 +661,7 @@ public class FileLoadOperation {
}
public boolean start() {
return start(null, 0, false);
return start(stream, streamOffset, streamPriority);
}
public boolean start(final FileLoadOperationStream stream, final long streamOffset, final boolean steamPriority) {
@ -1184,13 +1208,15 @@ public class FileLoadOperation {
}
try {
if (filePartsStream != null) {
try {
filePartsStream.getChannel().close();
} catch (Exception e) {
FileLog.e(e);
synchronized (FileLoadOperation.this) {
try {
filePartsStream.getChannel().close();
} catch (Exception e) {
FileLog.e(e);
}
filePartsStream.close();
filePartsStream = null;
}
filePartsStream.close();
filePartsStream = null;
}
} catch (Exception e) {
FileLog.e(e);

View File

@ -10,7 +10,6 @@ package org.telegram.messenger;
import android.text.TextUtils;
import android.util.SparseArray;
import android.util.SparseIntArray;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
@ -28,6 +27,31 @@ import java.util.function.Function;
public class FileLoader extends BaseController {
private static final int PRIORITY_STREAM = 4;
public static final int PRIORITY_HIGH = 3;
public static final int PRIORITY_NORMAL_UP = 2;
public static final int PRIORITY_NORMAL = 1;
public static final int PRIORITY_LOW = 0;
private int priorityIncreasePointer;
private int getPriorityValue(int priorityType) {
if (priorityType == PRIORITY_STREAM) {
return Integer.MAX_VALUE;
} else if (priorityType == PRIORITY_HIGH) {
priorityIncreasePointer++;
return (1 << 20) + priorityIncreasePointer;
} else if (priorityType == PRIORITY_NORMAL_UP) {
priorityIncreasePointer++;
return (1 << 16) + priorityIncreasePointer;
} else if (priorityType == PRIORITY_NORMAL) {
return 1 << 16;
} else {
return 0;
}
}
public interface FileLoaderDelegate {
void fileUploadProgressChanged(FileUploadOperation operation, String location, long uploadedSize, long totalSize, boolean isEncrypted);
@ -58,10 +82,10 @@ public class FileLoader extends BaseController {
public static final int IMAGE_TYPE_SVG_WHITE = 4;
public static final int IMAGE_TYPE_THEME_PREVIEW = 5;
public static final int QUEUE_TYPE_FILE = 0;
public static final int QUEUE_TYPE_IMAGE = 1;
public static final int QUEUE_TYPE_AUDIO = 2;
public static final int QUEUE_TYPE_PRELOAD = 3;
private final FileLoaderPriorityQueue largeFilesQueue = new FileLoaderPriorityQueue("large files queue", 2);
private final FileLoaderPriorityQueue filesQueue = new FileLoaderPriorityQueue("files queue", 3);
private final FileLoaderPriorityQueue imagesQueue = new FileLoaderPriorityQueue("imagesQueue queue", 6);
private final FileLoaderPriorityQueue audioQueue = new FileLoaderPriorityQueue("audioQueue queue", 3);
public final static long DEFAULT_MAX_FILE_SIZE = 1024L * 1024L * 2000L;
public final static long DEFAULT_MAX_FILE_SIZE_PREMIUM = DEFAULT_MAX_FILE_SIZE * 2L;
@ -78,14 +102,6 @@ public class FileLoader extends BaseController {
private int currentUploadOperationsCount = 0;
private int currentUploadSmallOperationsCount = 0;
private SparseArray<LinkedList<FileLoadOperation>> fileLoadOperationQueues = new SparseArray<>();
private SparseArray<LinkedList<FileLoadOperation>> audioLoadOperationQueues = new SparseArray<>();
private SparseArray<LinkedList<FileLoadOperation>> imageLoadOperationQueues = new SparseArray<>();
private SparseArray<LinkedList<FileLoadOperation>> preloadingLoadOperationQueues = new SparseArray<>();
private SparseIntArray fileLoadOperationsCount = new SparseIntArray();
private SparseIntArray audioLoadOperationsCount = new SparseIntArray();
private SparseIntArray imageLoadOperationsCount = new SparseIntArray();
private SparseIntArray preloadingLoadOperationsCount = new SparseIntArray();
private ConcurrentHashMap<String, FileLoadOperation> loadOperationPaths = new ConcurrentHashMap<>();
private ArrayList<FileLoadOperation> activeFileLoadOperation = new ArrayList<>();
@ -395,38 +411,6 @@ public class FileLoader extends BaseController {
});
}
private LinkedList<FileLoadOperation> getLoadOperationQueue(int datacenterId, int type) {
SparseArray<LinkedList<FileLoadOperation>> queues;
if (type == QUEUE_TYPE_PRELOAD) {
queues = preloadingLoadOperationQueues;
} else if (type == QUEUE_TYPE_AUDIO) {
queues = audioLoadOperationQueues;
} else if (type == QUEUE_TYPE_IMAGE) {
queues = imageLoadOperationQueues;
} else {
queues = fileLoadOperationQueues;
}
LinkedList<FileLoadOperation> queue = queues.get(datacenterId);
if (queue == null) {
queue = new LinkedList<>();
queues.put(datacenterId, queue);
}
return queue;
}
private SparseIntArray getLoadOperationCount(int type) {
SparseArray<LinkedList<FileLoadOperation>> queues;
if (type == QUEUE_TYPE_PRELOAD) {
return preloadingLoadOperationsCount;
} else if (type == QUEUE_TYPE_AUDIO) {
return audioLoadOperationsCount;
} else if (type == QUEUE_TYPE_IMAGE) {
return imageLoadOperationsCount;
} else {
return fileLoadOperationsCount;
}
}
public void setForceStreamLoadingFile(TLRPC.FileLocation location, String ext) {
if (location == null) {
return;
@ -439,29 +423,9 @@ public class FileLoader extends BaseController {
operation.setIsPreloadVideoOperation(false);
}
operation.setForceRequest(true);
int datacenterId = operation.getDatacenterId();
int queueType = operation.getQueueType();
LinkedList<FileLoadOperation> downloadQueue = getLoadOperationQueue(datacenterId, queueType);
SparseIntArray count = getLoadOperationCount(queueType);
int index = downloadQueue.indexOf(operation);
if (index >= 0) {
downloadQueue.remove(index);
if (operation.start()) {
count.put(datacenterId, count.get(datacenterId) + 1);
}
if (queueType == QUEUE_TYPE_FILE) {
if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) {
pauseCurrentFileLoadOperations(operation);
activeFileLoadOperation.add(operation);
}
}
} else {
pauseCurrentFileLoadOperations(operation);
operation.start();
if (queueType == QUEUE_TYPE_FILE && !activeFileLoadOperation.contains(operation)) {
activeFileLoadOperation.add(operation);
}
}
operation.setPriority(getPriorityValue(PRIORITY_STREAM));
operation.getQueue().add(operation);
operation.getQueue().checkLoadingOperations();
}
});
}
@ -533,17 +497,8 @@ public class FileLoader extends BaseController {
fileLoaderQueue.postRunnable(() -> {
FileLoadOperation operation = loadOperationPaths.remove(fileName);
if (operation != null) {
int queueType = operation.getQueueType();
int datacenterId = operation.getDatacenterId();
LinkedList<FileLoadOperation> queue = getLoadOperationQueue(datacenterId, queueType);
if (!queue.remove(operation)) {
SparseIntArray count = getLoadOperationCount(queueType);
count.put(datacenterId, count.get(datacenterId) - 1);
}
if (queueType == QUEUE_TYPE_FILE) {
activeFileLoadOperation.remove(operation);
}
operation.cancel(deleteFile);
FileLoaderPriorityQueue queue = operation.getQueue();
queue.cancel(operation);
}
});
if (removed && document != null) {
@ -600,27 +555,8 @@ public class FileLoader extends BaseController {
loadFile(null, null, document, null, null, null, null, 0, priority, cacheType);
}
private void pauseCurrentFileLoadOperations(FileLoadOperation newOperation) {
for (int a = 0; a < activeFileLoadOperation.size(); a++) {
FileLoadOperation operation = activeFileLoadOperation.get(a);
if (operation == newOperation || operation.getDatacenterId() != newOperation.getDatacenterId() || operation.getFileName().equals(forceLoadingFile)) {
continue;
}
activeFileLoadOperation.remove(operation);
a--;
int datacenterId = operation.getDatacenterId();
int queueType = operation.getQueueType();
LinkedList<FileLoadOperation> downloadQueue = getLoadOperationQueue(datacenterId, queueType);
SparseIntArray count = getLoadOperationCount(queueType);
downloadQueue.add(0, operation);
if (operation.wasStarted()) {
count.put(datacenterId, count.get(datacenterId) - 1);
}
operation.pause();
}
}
private FileLoadOperation loadFileInternal(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, TLRPC.TL_fileLocationToBeDeprecated location, final ImageLocation imageLocation, Object parentObject, final String locationExt, final long locationSize, final int priority, final FileLoadOperationStream stream, final long streamOffset, boolean streamPriority, final int cacheType) {
private FileLoadOperation loadFileInternal(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, TLRPC.TL_fileLocationToBeDeprecated location, final ImageLocation imageLocation, Object parentObject, final String locationExt, final long locationSize, int priority, final FileLoadOperationStream stream, final long streamOffset, boolean streamPriority, final int cacheType) {
String fileName;
if (location != null) {
fileName = getAttachFileName(location, locationExt);
@ -648,44 +584,21 @@ public class FileLoader extends BaseController {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("checkFile operation fileName=" + fileName + " documentName=" + getDocumentFileName(document) + " operation=" + operation);
}
if (stream != null) {
priority = PRIORITY_STREAM;
}
priority = getPriorityValue(priority);
if (operation != null) {
if (cacheType != 10 && operation.isPreloadVideoOperation()) {
operation.setIsPreloadVideoOperation(false);
}
if (stream != null || priority > 0) {
int datacenterId = operation.getDatacenterId();
operation.setForceRequest(true);
int queueType = operation.getQueueType();
LinkedList<FileLoadOperation> downloadQueue = getLoadOperationQueue(datacenterId, queueType);
SparseIntArray count = getLoadOperationCount(queueType);
int index = downloadQueue.indexOf(operation);
if (index >= 0) {
downloadQueue.remove(index);
if (stream != null) {
if (operation.start(stream, streamOffset, streamPriority)) {
count.put(datacenterId, count.get(datacenterId) + 1);
}
if (queueType == QUEUE_TYPE_FILE) {
if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) {
pauseCurrentFileLoadOperations(operation);
activeFileLoadOperation.add(operation);
}
}
} else {
downloadQueue.add(0, operation);
}
} else {
if (stream != null) {
pauseCurrentFileLoadOperations(operation);
}
operation.start(stream, streamOffset, streamPriority);
if (queueType == QUEUE_TYPE_FILE && !activeFileLoadOperation.contains(operation)) {
activeFileLoadOperation.add(operation);
}
}
}
operation.setForceRequest(priority > 0);
operation.setPriority(priority);
operation.setStream(stream, streamPriority, streamOffset);
operation.getQueue().add(operation);
operation.updateProgress();
operation.getQueue().checkLoadingOperations();
return operation;
}
@ -738,15 +651,17 @@ public class FileLoader extends BaseController {
type = MEDIA_DIR_DOCUMENT;
}
}
int queueType;
if (cacheType == PRELOAD_CACHE_TYPE) {
queueType = QUEUE_TYPE_PRELOAD;
} else if (type == MEDIA_DIR_AUDIO) {
queueType = QUEUE_TYPE_AUDIO;
} else if (secureDocument != null || location != null && (imageLocation == null || imageLocation.imageType != IMAGE_TYPE_ANIMATION) || MessageObject.isImageWebDocument(webDocument) || MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document) || MessageObject.isVideoStickerDocument(document)) {
queueType = QUEUE_TYPE_IMAGE;
FileLoaderPriorityQueue loaderQueue;
if (type == MEDIA_DIR_AUDIO) {
loaderQueue = audioQueue;
} else if (secureDocument != null || location != null && (imageLocation == null || imageLocation.imageType != IMAGE_TYPE_ANIMATION) || MessageObject.isImageWebDocument(webDocument) || MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isVideoStickerDocument(document)) {
loaderQueue = imagesQueue;
} else {
queueType = QUEUE_TYPE_FILE;
if (document == null || document.size > 20 * 1024 * 1024) {
loaderQueue = largeFilesQueue;
} else {
loaderQueue = filesQueue;
}
}
String storeFileName = fileName;
@ -799,7 +714,7 @@ public class FileLoader extends BaseController {
} else if (cacheType == 2) {
operation.setEncryptFile(true);
}
operation.setPaths(currentAccount, fileName, queueType, storeDir, tempDir, storeFileName);
operation.setPaths(currentAccount, fileName, loaderQueue, storeDir, tempDir, storeFileName);
if (cacheType == 10) {
operation.setIsPreloadVideoOperation(true);
}
@ -823,13 +738,13 @@ public class FileLoader extends BaseController {
}
}
checkDownloadQueue(operation.getDatacenterId(), queueType, fileName);
checkDownloadQueue(operation.getQueue(), fileName);
}
@Override
public void didFailedLoadingFile(FileLoadOperation operation, int reason) {
loadOperationPathsUI.remove(fileName);
checkDownloadQueue(operation.getDatacenterId(), queueType, fileName);
checkDownloadQueue(operation.getQueue(), fileName);
if (getDelegate() != null) {
delegate.fileDidFailedLoad(fileName, reason);
}
@ -858,58 +773,16 @@ public class FileLoader extends BaseController {
};
operation.setDelegate(fileLoadOperationDelegate);
int datacenterId = operation.getDatacenterId();
loadOperationPaths.put(fileName, operation);
operation.setPriority(priority);
boolean started;
int maxCount, count;
if (queueType == QUEUE_TYPE_PRELOAD) {
maxCount = priority > 0 ? 6 : 2;
count = preloadingLoadOperationsCount.get(datacenterId);
if (started = (stream != null || count < maxCount)) {
if (operation.start(stream, streamOffset, streamPriority)) {
preloadingLoadOperationsCount.put(datacenterId, count + 1);
}
}
} else if (queueType == QUEUE_TYPE_AUDIO) {
maxCount = priority > 0 ? 3 : 1;
count = audioLoadOperationsCount.get(datacenterId);
if (started = (stream != null || count < maxCount)) {
if (operation.start(stream, streamOffset, streamPriority)) {
audioLoadOperationsCount.put(datacenterId, count + 1);
}
}
} else if (queueType == QUEUE_TYPE_IMAGE) {
maxCount = priority > 0 ? 6 : 2;
count = imageLoadOperationsCount.get(datacenterId);
if (started = (stream != null || count < maxCount)) {
if (operation.start(stream, streamOffset, streamPriority)) {
imageLoadOperationsCount.put(datacenterId, count + 1);
}
}
} else {
maxCount = priority > 0 ? 4 : 1;
count = fileLoadOperationsCount.get(datacenterId);
if (started = (stream != null || count < maxCount)) {
if (operation.start(stream, streamOffset, streamPriority)) {
fileLoadOperationsCount.put(datacenterId, count + 1);
activeFileLoadOperation.add(operation);
}
if (operation.wasStarted() && stream != null) {
pauseCurrentFileLoadOperations(operation);
}
}
}
operation.setStream(stream, streamPriority, streamOffset);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("loadFileInternal fileName=" + fileName + " documentName=" + getDocumentFileName(document) + " queueType=" + queueType + " maxCount=" + maxCount + " count=" + count);
FileLog.d("loadFileInternal fileName=" + fileName + " documentName=" + getDocumentFileName(document));
}
if (!started) {
addOperationToQueue(operation, getLoadOperationQueue(datacenterId, queueType));
}
loaderQueue.add(operation);
loaderQueue.checkLoadingOperations();
return operation;
}
@ -1004,50 +877,11 @@ public class FileLoader extends BaseController {
return result[0];
}
private void checkDownloadQueue(int datacenterId, int queueType, String fileName) {
private void checkDownloadQueue(FileLoaderPriorityQueue queue, String fileName) {
fileLoaderQueue.postRunnable(() -> {
FileLoadOperation operation = loadOperationPaths.remove(fileName);
LinkedList<FileLoadOperation> queue = getLoadOperationQueue(datacenterId, queueType);
SparseIntArray operationCount = getLoadOperationCount(queueType);
int count = operationCount.get(datacenterId);
if (operation != null) {
if (operation.wasStarted()) {
count--;
operationCount.put(datacenterId, count);
} else {
queue.remove(operation);
}
if (queueType == QUEUE_TYPE_FILE) {
activeFileLoadOperation.remove(operation);
}
}
while (!queue.isEmpty()) {
operation = queue.get(0);
int maxCount;
if (queueType == QUEUE_TYPE_PRELOAD) {
maxCount = operation.getPriority() != 0 ? 6 : 2;
} else if (queueType == QUEUE_TYPE_AUDIO) {
maxCount = operation.getPriority() != 0 ? 3 : 1;
} else if (queueType == QUEUE_TYPE_IMAGE) {
maxCount = operation.getPriority() != 0 ? 6 : 2;
} else {
maxCount = operation.isForceRequest() ? 3 : 1;
}
if (count < maxCount) {
operation = queue.poll();
if (operation != null && operation.start()) {
count++;
operationCount.put(datacenterId, count);
if (queueType == QUEUE_TYPE_FILE) {
if (!activeFileLoadOperation.contains(operation)) {
activeFileLoadOperation.add(operation);
}
}
}
} else {
break;
}
}
queue.remove(operation);
queue.checkLoadingOperations();
});
}
@ -1066,21 +900,21 @@ public class FileLoader extends BaseController {
}
}
} else {
if (message.media instanceof TLRPC.TL_messageMediaDocument) {
return getAttachFileName(message.media.document);
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
ArrayList<TLRPC.PhotoSize> sizes = message.media.photo.sizes;
if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaDocument) {
return getAttachFileName(MessageObject.getMedia(message).document);
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto) {
ArrayList<TLRPC.PhotoSize> sizes = MessageObject.getMedia(message).photo.sizes;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize(), false, null, true);
if (sizeFull != null) {
return getAttachFileName(sizeFull);
}
}
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage.document != null) {
return getAttachFileName(message.media.webpage.document);
} else if (message.media.webpage.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = message.media.webpage.photo.sizes;
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaWebPage) {
if (MessageObject.getMedia(message).webpage.document != null) {
return getAttachFileName(MessageObject.getMedia(message).webpage.document);
} else if (MessageObject.getMedia(message).webpage.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = MessageObject.getMedia(message).webpage.photo.sizes;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize());
if (sizeFull != null) {
@ -1088,8 +922,8 @@ public class FileLoader extends BaseController {
}
}
}
} else if (message.media instanceof TLRPC.TL_messageMediaInvoice) {
TLRPC.WebDocument document = ((TLRPC.TL_messageMediaInvoice) message.media).photo;
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaInvoice) {
TLRPC.WebDocument document = ((TLRPC.TL_messageMediaInvoice) MessageObject.getMedia(message)).photo;
if (document != null) {
return Utilities.MD5(document.url) + "." + ImageLoader.getHttpUrlExtension(document.url, getMimeTypePart(document.mime_type));
}
@ -1117,21 +951,21 @@ public class FileLoader extends BaseController {
}
}
} else {
if (message.media instanceof TLRPC.TL_messageMediaDocument) {
return getPathToAttach(message.media.document, null, message.media.ttl_seconds != 0, useFileDatabaseQueue);
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
ArrayList<TLRPC.PhotoSize> sizes = message.media.photo.sizes;
if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaDocument) {
return getPathToAttach(MessageObject.getMedia(message).document, null, MessageObject.getMedia(message).ttl_seconds != 0, useFileDatabaseQueue);
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto) {
ArrayList<TLRPC.PhotoSize> sizes = MessageObject.getMedia(message).photo.sizes;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize(), false, null, true);
if (sizeFull != null) {
return getPathToAttach(sizeFull, null, message.media.ttl_seconds != 0, useFileDatabaseQueue);
return getPathToAttach(sizeFull, null, MessageObject.getMedia(message).ttl_seconds != 0, useFileDatabaseQueue);
}
}
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage.document != null) {
return getPathToAttach(message.media.webpage.document, null, false, useFileDatabaseQueue);
} else if (message.media.webpage.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = message.media.webpage.photo.sizes;
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaWebPage) {
if (MessageObject.getMedia(message).webpage.document != null) {
return getPathToAttach(MessageObject.getMedia(message).webpage.document, null, false, useFileDatabaseQueue);
} else if (MessageObject.getMedia(message).webpage.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = MessageObject.getMedia(message).webpage.photo.sizes;
if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize());
if (sizeFull != null) {
@ -1139,8 +973,8 @@ public class FileLoader extends BaseController {
}
}
}
} else if (message.media instanceof TLRPC.TL_messageMediaInvoice) {
return getPathToAttach(((TLRPC.TL_messageMediaInvoice) message.media).photo, null, true, useFileDatabaseQueue);
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaInvoice) {
return getPathToAttach(((TLRPC.TL_messageMediaInvoice) MessageObject.getMedia(message)).photo, null, true, useFileDatabaseQueue);
}
}
return new File("");

View File

@ -0,0 +1,86 @@
package org.telegram.messenger;
import java.util.ArrayList;
public class FileLoaderPriorityQueue {
private final int maxActiveOperationsCount;
String name;
ArrayList<FileLoadOperation> allOperations = new ArrayList<>();
ArrayList<FileLoadOperation> activeOperations = new ArrayList<>();
private int PRIORITY_VALUE_MAX = (1 << 20);
private int PRIORITY_VALUE_NORMAL = (1 << 16);
private int PRIORITY_VALUE_LOW = 0;
FileLoaderPriorityQueue(String name, int maxActiveOperationsCount) {
this.name = name;
this.maxActiveOperationsCount = maxActiveOperationsCount;
}
public void add(FileLoadOperation operation) {
if (operation == null) {
return;
}
int index = -1;
allOperations.remove(operation);
for (int i = 0; i < allOperations.size(); i++) {
if (operation.getPriority() > allOperations.get(i).getPriority()) {
index = i;
break;
}
}
if (index >= 0) {
allOperations.add(index, operation);
} else {
allOperations.add(operation);
}
}
public void cancel(FileLoadOperation operation) {
if (operation == null) {
return;
}
allOperations.remove(operation);
operation.cancel();
}
public void checkLoadingOperations() {
int activeCount = 0;
int lastPriority = 0;
boolean pauseAllNextOperations = false;
for (int i = 0; i < allOperations.size(); i++) {
FileLoadOperation operation = allOperations.get(i);
if (i > 0 && !pauseAllNextOperations) {
if (lastPriority > PRIORITY_VALUE_LOW && operation.getPriority() == PRIORITY_VALUE_LOW) {
pauseAllNextOperations = true;
}
}
if (!pauseAllNextOperations && i < maxActiveOperationsCount) {
operation.start();
activeCount++;
} else {
if (operation.wasStarted()) {
operation.pause();
}
}
lastPriority = operation.getPriority();
}
}
public void remove(FileLoadOperation operation) {
if (operation == null) {
return;
}
allOperations.remove(operation);
}
private FileLoadOperation remove() {
if (allOperations.isEmpty()) {
return null;
}
return allOperations.remove(0);
}
}

View File

@ -56,6 +56,44 @@ public class FileLog {
e(e);
}
public static void fatal(final Throwable e) {
fatal(e, true);
}
public static void fatal(final Throwable e, boolean logToAppCenter) {
if (!BuildVars.LOGS_ENABLED) {
return;
}
if (BuildVars.DEBUG_VERSION && needSent(e) && logToAppCenter) {
AndroidUtilities.appCenterLog(e);
}
ensureInitied();
e.printStackTrace();
if (getInstance().streamWriter != null) {
getInstance().logQueue.postRunnable(() -> {
try {
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + e + "\n");
StackTraceElement[] stack = e.getStackTrace();
for (int a = 0; a < stack.length; a++) {
getInstance().streamWriter.write(getInstance().dateFormat.format(System.currentTimeMillis()) + " E/tmessages: " + stack[a] + "\n");
}
getInstance().streamWriter.flush();
} catch (Exception e1) {
e1.printStackTrace();
}
if (BuildVars.DEBUG_PRIVATE_VERSION) {
System.exit(2);
}
});
} else {
e.printStackTrace();
if (BuildVars.DEBUG_PRIVATE_VERSION) {
System.exit(2);
}
}
}
private static boolean needSent(Throwable e) {
if (e instanceof InterruptedException || e instanceof MediaCodecVideoConvertor.ConversionCanceledException) {
return false;

View File

@ -34,6 +34,7 @@ import androidx.exifinterface.media.ExifInterface;
import org.json.JSONArray;
import org.json.JSONObject;
import org.telegram.DispatchQueuePriority;
import org.telegram.messenger.secretmedia.EncryptedFileInputStream;
import org.telegram.messenger.utils.BitmapsCache;
import org.telegram.tgnet.ConnectionsManager;
@ -105,7 +106,7 @@ public class ImageLoader {
private SparseArray<String> waitingForQualityThumbByTag = new SparseArray<>();
private LinkedList<HttpImageTask> httpTasks = new LinkedList<>();
private LinkedList<ArtworkLoadTask> artworkTasks = new LinkedList<>();
private DispatchQueue cacheOutQueue = new DispatchQueue("cacheOutQueue");
private DispatchQueuePriority cacheOutQueue = new DispatchQueuePriority("cacheOutQueue");
private DispatchQueue cacheThumbOutQueue = new DispatchQueue("cacheThumbOutQueue");
private DispatchQueue thumbGeneratingQueue = new DispatchQueue("thumbGeneratingQueue");
private DispatchQueue imageLoadQueue = new DispatchQueue("imageLoadQueue");
@ -154,7 +155,11 @@ public class ImageLoader {
if (key == null) {
return;
}
BitmapDrawable drawable = memCache.get(key);
BitmapDrawable drawable = lottieMemCache.get(key);
if (drawable != null) {
lottieMemCache.moveToFront(key);
}
drawable = memCache.get(key);
if (drawable != null) {
memCache.moveToFront(key);
}
@ -170,6 +175,10 @@ public class ImageLoader {
}
}
public LruCache<BitmapDrawable> getLottieMemCahce() {
return lottieMemCache;
}
private static class ThumbGenerateInfo {
private TLRPC.Document parentDocument;
private String filter;
@ -679,12 +688,12 @@ public class ImageLoader {
}
});
});
imageLoadQueue.postRunnable(() -> runHttpTasks(true));
imageLoadQueue.postRunnable(() -> runHttpTasks(true), cacheImage.priority);
}
@Override
protected void onCancelled() {
imageLoadQueue.postRunnable(() -> runHttpTasks(true));
imageLoadQueue.postRunnable(() -> runHttpTasks(true), cacheImage.priority);
Utilities.stageQueue.postRunnable(() -> {
fileProgresses.remove(cacheImage.url);
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(cacheImage.currentAccount).postNotificationName(NotificationCenter.fileLoadFailed, cacheImage.url, 1));
@ -884,7 +893,7 @@ public class ImageLoader {
if (args.length >= 3 && "pcache".equals(args[2])) {
precache = true;
} else {
precache = !cacheImage.filter.contains("nolimit") && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_HIGH;
precache = cacheImage.filter.contains("pcache") || !cacheImage.filter.contains("nolimit") && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_HIGH;
}
if (cacheImage.filter.contains("lastframe")) {
@ -1614,7 +1623,7 @@ public class ImageLoader {
}
final Drawable toSetFinal = toSet;
final String decrementKetFinal = decrementKey;
imageLoadQueue.postRunnable(() -> cacheImage.setImageAndClear(toSetFinal, decrementKetFinal));
imageLoadQueue.postRunnable(() -> cacheImage.setImageAndClear(toSetFinal, decrementKetFinal), cacheImage.priority);
});
}
@ -1674,6 +1683,8 @@ public class ImageLoader {
private class CacheImage {
public int priority = 1;
public Runnable runningTask;
protected String key;
protected String url;
protected String filter;
@ -1774,6 +1785,7 @@ public class ImageLoader {
cacheThumbOutQueue.cancelRunnable(cacheTask);
} else {
cacheOutQueue.cancelRunnable(cacheTask);
cacheOutQueue.cancelRunnable(runningTask);
}
cacheTask.cancel();
cacheTask = null;
@ -2395,7 +2407,7 @@ public class ImageLoader {
}
}
}
});
}, imageReceiver.getFileLoadingPriority() == FileLoader.PRIORITY_LOW ? 0 : 1);
}
public BitmapDrawable getImageFromMemory(TLObject fileLocation, String httpUrl, String filter) {
@ -2643,6 +2655,7 @@ public class ImageLoader {
if (thumb != 2) {
boolean isEncrypted = imageLocation.isEncrypted();
CacheImage img = new CacheImage();
img.priority = imageReceiver.getFileLoadingPriority() == FileLoader.PRIORITY_LOW ? 0 : 1;
if (!currentKeyQuality) {
if (imageLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION || MessageObject.isGifDocument(imageLocation.webFile) || MessageObject.isGifDocument(imageLocation.document) || MessageObject.isRoundVideoDocument(imageLocation.document) || MessageObject.isVideoSticker(imageLocation.document)) {
img.imageType = FileLoader.IMAGE_TYPE_ANIMATION;
@ -2769,11 +2782,12 @@ public class ImageLoader {
img.finalFilePath = cacheFile;
img.imageLocation = imageLocation;
img.cacheTask = new CacheOutTask(img);
imageLoadingByKeys.put(key, img);
if (thumb != 0) {
cacheThumbOutQueue.postRunnable(img.cacheTask);
} else {
cacheOutQueue.postRunnable(img.cacheTask);
img.runningTask = cacheOutQueue.postRunnable(img.cacheTask, img.priority);
}
} else {
img.url = url;
@ -2794,18 +2808,19 @@ public class ImageLoader {
runHttpTasks(false);
}
} else {
int loadingPriority = thumb != 0 ? FileLoader.PRIORITY_HIGH : imageReceiver.getFileLoadingPriority();
if (imageLocation.location != null) {
int localCacheType = cacheType;
if (localCacheType == 0 && (size <= 0 || imageLocation.key != null)) {
localCacheType = 1;
}
FileLoader.getInstance(currentAccount).loadFile(imageLocation, parentObject, ext, thumb != 0 ? 2 : 1, localCacheType);
FileLoader.getInstance(currentAccount).loadFile(imageLocation, parentObject, ext, loadingPriority, localCacheType);
} else if (imageLocation.document != null) {
FileLoader.getInstance(currentAccount).loadFile(imageLocation.document, parentObject, thumb != 0 ? 2 : 1, cacheType);
FileLoader.getInstance(currentAccount).loadFile(imageLocation.document, parentObject, loadingPriority, cacheType);
} else if (imageLocation.secureDocument != null) {
FileLoader.getInstance(currentAccount).loadFile(imageLocation.secureDocument, thumb != 0 ? 2 : 1);
FileLoader.getInstance(currentAccount).loadFile(imageLocation.secureDocument, loadingPriority);
} else if (imageLocation.webFile != null) {
FileLoader.getInstance(currentAccount).loadFile(imageLocation.webFile, thumb != 0 ? 2 : 1, cacheType);
FileLoader.getInstance(currentAccount).loadFile(imageLocation.webFile, loadingPriority, cacheType);
}
if (imageReceiver.isForceLoding()) {
forceLoadingImages.put(img.key, 0);
@ -2815,7 +2830,7 @@ public class ImageLoader {
}
}
};
imageLoadQueue.postRunnable(loadOperationRunnable);
imageLoadQueue.postRunnable(loadOperationRunnable, imageReceiver.getFileLoadingPriority() == FileLoader.PRIORITY_LOW ? 0 : 1);
imageReceiver.addLoadingImageRunnable(loadOperationRunnable);
}
@ -3230,6 +3245,7 @@ public class ImageLoader {
CacheImage cacheImage = imageLoadingByKeys.get(key);
if (cacheImage == null) {
cacheImage = new CacheImage();
cacheImage.priority = img.priority;
cacheImage.secureDocument = img.secureDocument;
cacheImage.currentAccount = img.currentAccount;
cacheImage.finalFilePath = finalFile;
@ -3252,7 +3268,7 @@ public class ImageLoader {
if (task.cacheImage.type == ImageReceiver.TYPE_THUMB) {
cacheThumbOutQueue.postRunnable(task);
} else {
cacheOutQueue.postRunnable(task);
cacheOutQueue.postRunnable(task, task.cacheImage.priority);
}
}
});
@ -3830,6 +3846,8 @@ public class ImageLoader {
}
}
}
} else if (message.media instanceof TLRPC.TL_messageMediaInvoice && message.media.extended_media instanceof TLRPC.TL_messageExtendedMediaPreview) {
photoSize = ((TLRPC.TL_messageExtendedMediaPreview) message.media.extended_media).thumb;
}
return photoSize;
}
@ -3922,7 +3940,7 @@ public class ImageLoader {
}
}
public DispatchQueue getCacheOutQueue() {
public DispatchQueuePriority getCacheOutQueue() {
return cacheOutQueue;
}

View File

@ -32,7 +32,6 @@ import androidx.annotation.Keep;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedFileDrawable;
import org.telegram.ui.Components.LoadingStickerDrawable;
import org.telegram.ui.Components.RLottieDrawable;
@ -42,8 +41,6 @@ import java.util.ArrayList;
public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate {
private long currentTime;
public interface ImageReceiverDelegate {
void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb, boolean memCache);
@ -175,6 +172,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private static PorterDuffColorFilter selectedColorFilter = new PorterDuffColorFilter(0xffdddddd, PorterDuff.Mode.SRC_IN);
private static PorterDuffColorFilter selectedGroupColorFilter = new PorterDuffColorFilter(0xffbbbbbb, PorterDuff.Mode.SRC_IN);
private boolean forceLoding;
private long currentTime;
private int fileLoadingPriority = FileLoader.PRIORITY_NORMAL;
private int currentLayerNum;
private int currentOpenedLayerFlags;
@ -233,6 +232,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private boolean useSharedAnimationQueue;
private boolean allowDecodeSingleFrame;
private int autoRepeat = 1;
private int autoRepeatCount = -1;
private long autoRepeatTimeout;
private boolean animationReadySent;
@ -498,7 +498,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (imageKey == null && imageLocation != null) {
imageLocation = null;
}
animatedFileDrawableRepeatMaxCount = 0;
animatedFileDrawableRepeatMaxCount = Math.max(autoRepeatCount, 0);
currentKeyQuality = false;
if (imageKey == null && needsQualityThumb && (parentObject instanceof MessageObject || qulityThumbDocument != null)) {
TLRPC.Document document = qulityThumbDocument != null ? qulityThumbDocument : ((MessageObject) parentObject).getDocument();
@ -708,6 +708,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
public void setLayerNum(int value) {
currentLayerNum = value;
if (attachedToWindow) {
currentOpenedLayerFlags = NotificationCenter.getGlobalInstance().getCurrentHeavyOperationFlags();
currentOpenedLayerFlags &= ~currentLayerNum;
}
}
public void setImageBitmap(Bitmap bitmap) {
@ -947,7 +951,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
}
}
private boolean setBackupImage() {
public boolean setBackupImage() {
if (setImageBackup != null && setImageBackup.isSet()) {
SetImageBackup temp = setImageBackup;
setImageBackup = null;
@ -1025,18 +1029,24 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
protected void drawDrawable(Canvas canvas, Drawable drawable, int alpha, BitmapShader shader, int orientation, int isPressed, BackgroundThreadDrawHolder backgroundThreadDrawHolder) {
float imageX, imageY, imageH, imageW;
RectF drawRegion;
ColorFilter colorFilter;
int[] roundRadius;
if (backgroundThreadDrawHolder != null) {
imageX = backgroundThreadDrawHolder.imageX;
imageY = backgroundThreadDrawHolder.imageY;
imageH = backgroundThreadDrawHolder.imageH;
imageW = backgroundThreadDrawHolder.imageW;
drawRegion = backgroundThreadDrawHolder.drawRegion;
colorFilter = backgroundThreadDrawHolder.colorFilter;
roundRadius = backgroundThreadDrawHolder.roundRadius;
} else {
imageX = this.imageX;
imageY = this.imageY;
imageH = this.imageH;
imageW = this.imageW;
drawRegion = this.drawRegion;
colorFilter = this.colorFilter;
roundRadius = this.roundRadius;
}
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
@ -1271,6 +1281,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
((AnimatedFileDrawable) bitmapDrawable).setActualDrawRect(drawRegion.left, drawRegion.top, drawRegion.width(), drawRegion.height());
}
}
if (backgroundThreadDrawHolder != null && roundRadius != null && roundRadius[0] > 0) {
canvas.save();
Path path = backgroundThreadDrawHolder.roundPath == null ? backgroundThreadDrawHolder.roundPath = new Path() : backgroundThreadDrawHolder.roundPath;
path.rewind();
AndroidUtilities.rectTmp.set(imageX, imageY, imageX + imageW, imageY + imageH);
path.addRoundRect(AndroidUtilities.rectTmp, roundRadius[0], roundRadius[2], Path.Direction.CW);
canvas.clipPath(path);
}
if (isVisible) {
try {
bitmapDrawable.setAlpha(alpha);
@ -1283,6 +1301,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
}
}
canvas.restore();
if (backgroundThreadDrawHolder != null && roundRadius != null && roundRadius[0] > 0) {
canvas.restore();
}
} else {
if (Math.abs(scaleW - scaleH) > 0.00001f) {
canvas.save();
@ -1435,9 +1456,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private void drawBitmapDrawable(Canvas canvas, BitmapDrawable bitmapDrawable, BackgroundThreadDrawHolder backgroundThreadDrawHolder, int alpha) {
if (backgroundThreadDrawHolder != null) {
if (bitmapDrawable instanceof RLottieDrawable) {
((RLottieDrawable) bitmapDrawable).drawInBackground(canvas, backgroundThreadDrawHolder.imageX, backgroundThreadDrawHolder.imageY, backgroundThreadDrawHolder.imageW, backgroundThreadDrawHolder.imageH, alpha);
((RLottieDrawable) bitmapDrawable).drawInBackground(canvas, backgroundThreadDrawHolder.imageX, backgroundThreadDrawHolder.imageY, backgroundThreadDrawHolder.imageW, backgroundThreadDrawHolder.imageH, alpha, backgroundThreadDrawHolder.colorFilter);
} else if (bitmapDrawable instanceof AnimatedFileDrawable) {
((AnimatedFileDrawable) bitmapDrawable).drawInBackground(canvas, backgroundThreadDrawHolder.imageX, backgroundThreadDrawHolder.imageY, backgroundThreadDrawHolder.imageW, backgroundThreadDrawHolder.imageH, alpha);
((AnimatedFileDrawable) bitmapDrawable).drawInBackground(canvas, backgroundThreadDrawHolder.imageX, backgroundThreadDrawHolder.imageY, backgroundThreadDrawHolder.imageW, backgroundThreadDrawHolder.imageH, alpha, backgroundThreadDrawHolder.colorFilter);
} else {
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null) {
@ -1445,6 +1466,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
backgroundThreadDrawHolder.paint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
backgroundThreadDrawHolder.paint.setAlpha(alpha);
backgroundThreadDrawHolder.paint.setColorFilter(backgroundThreadDrawHolder.colorFilter);
canvas.save();
canvas.translate(backgroundThreadDrawHolder.imageX, backgroundThreadDrawHolder.imageY);
canvas.scale(backgroundThreadDrawHolder.imageW / bitmap.getWidth(), backgroundThreadDrawHolder.imageH / bitmap.getHeight());
@ -1503,13 +1525,13 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
setImage(currentMediaLocation, currentMediaFilter, currentImageLocation, currentImageFilter, currentThumbLocation, currentThumbFilter, currentThumbDrawable, currentSize, currentExt, currentParentObject, currentCacheType);
}
private void checkAlphaAnimation(boolean skip, boolean drawInBackground) {
private void checkAlphaAnimation(boolean skip, BackgroundThreadDrawHolder backgroundThreadDrawHolder) {
if (manualAlphaAnimator) {
return;
}
if (currentAlpha != 1) {
if (!skip) {
if (drawInBackground) {
if (backgroundThreadDrawHolder != null) {
long currentTime = System.currentTimeMillis();
long dt = currentTime - lastUpdateAlphaTime;
if (lastUpdateAlphaTime == 0) {
@ -1531,7 +1553,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
}
}
}
invalidate();
if (backgroundThreadDrawHolder != null) {
AndroidUtilities.runOnUIThread(this::invalidate);
} else {
invalidate();
}
}
}
@ -1754,14 +1780,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
drawDrawable(canvas, drawable, (int) (overrideAlpha * 255), shaderToUse, orientation, backgroundThreadDrawHolder);
}
checkAlphaAnimation(animationNotReady && crossfadeWithThumb, drawInBackground);
checkAlphaAnimation(animationNotReady && crossfadeWithThumb, backgroundThreadDrawHolder);
result = true;
} else if (staticThumbDrawable != null) {
drawDrawable(canvas, staticThumbDrawable, (int) (overrideAlpha * 255), null, thumbOrientation, backgroundThreadDrawHolder);
checkAlphaAnimation(animationNotReady, drawInBackground);
checkAlphaAnimation(animationNotReady, backgroundThreadDrawHolder);
result = true;
} else {
checkAlphaAnimation(animationNotReady, drawInBackground);
checkAlphaAnimation(animationNotReady, backgroundThreadDrawHolder);
}
if (drawable == null && animationNotReady && !drawInBackground) {
@ -2271,6 +2297,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
}
}
public void setAutoRepeatCount(int count) {
autoRepeatCount = count;
if (getLottieAnimation() != null) {
getLottieAnimation().setAutoRepeatCount(count);
} else {
animatedFileDrawableRepeatMaxCount = count;
if (getAnimation() != null) {
getAnimation().repeatCount = 0;
}
}
}
public void setAutoRepeatTimeout(long timeout) {
autoRepeatTimeout = timeout;
RLottieDrawable drawable = getLottieAnimation();
@ -2382,6 +2420,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
boolean allowCrossFade = true;
if (!(drawable instanceof AnimatedFileDrawable)) {
ImageLoader.getInstance().incrementUseCount(currentImageKey);
if (videoThumbIsSame) {
allowCrossFade = drawable != currentImageDrawable && currentAlpha >= 1;
}
} else {
AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable;
animatedFileDrawable.setStartEndTime(startTime, endTime);
@ -2529,6 +2570,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
}
fileDrawable.setAllowDecodeSingleFrame(true);
fileDrawable.setAutoRepeat(autoRepeat);
fileDrawable.setAutoRepeatCount(autoRepeatCount);
fileDrawable.setAutoRepeatTimeout(autoRepeatTimeout);
animationReadySent = false;
}
@ -2731,6 +2773,25 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
ImageLoader.getInstance().moveToFront(currentThumbKey);
}
public void moveLottieToFront() {
BitmapDrawable drawable = null;
String key = null;
if (currentMediaDrawable instanceof RLottieDrawable) {
drawable = (BitmapDrawable) currentMediaDrawable;
key = currentMediaKey;
} else if (currentImageDrawable instanceof RLottieDrawable) {
drawable = (BitmapDrawable) currentImageDrawable;
key = currentImageKey;
}
if (key != null && drawable != null) {
ImageLoader.getInstance().moveToFront(key);
if (!ImageLoader.getInstance().isInMemCache(key, true)) {
ImageLoader.getInstance().getLottieMemCahce().put(key, drawable);
}
}
}
public View getParentView() {
return parentView;
}
@ -2755,6 +2816,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
this.currentTime = time;
}
public void setFileLoadingPriority(int fileLoadingPriority) {
this.fileLoadingPriority = fileLoadingPriority;
}
public int getFileLoadingPriority() {
return fileLoadingPriority;
}
public BackgroundThreadDrawHolder setDrawInBackgroundThread(BackgroundThreadDrawHolder holder) {
if (holder == null) {
holder = new BackgroundThreadDrawHolder();
@ -2772,6 +2841,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
holder.thumbShader = thumbShader;
holder.staticThumbDrawable = staticThumbDrawable;
holder.crossfadeImage = crossfadeImage;
holder.colorFilter = colorFilter;
holder.crossfadingWithThumb = crossfadingWithThumb;
holder.crossfadeWithOldImage = crossfadeWithOldImage;
holder.currentAlpha = currentAlpha;
@ -2808,7 +2878,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private boolean crossfadingWithThumb;
private Drawable crossfadeImage;
public RectF drawRegion = new RectF();
public ColorFilter colorFilter;
Paint paint;
private Path roundPath;
public void release() {
animation = null;
@ -2824,6 +2896,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
thumbShader = null;
staticThumbDrawable = null;
crossfadeImage = null;
colorFilter = null;
}
public void setBounds(Rect bounds) {

View File

@ -1728,6 +1728,29 @@ public class LocaleController {
return "LOC_ERR";
}
public static String formatStatusExpireDateTime(long date) {
try {
date *= 1000;
Calendar rightNow = Calendar.getInstance();
int day = rightNow.get(Calendar.DAY_OF_YEAR);
int year = rightNow.get(Calendar.YEAR);
rightNow.setTimeInMillis(date);
int dateDay = rightNow.get(Calendar.DAY_OF_YEAR);
int dateYear = rightNow.get(Calendar.YEAR);
if (dateDay == day && year == dateYear) {
return LocaleController.formatString("TodayAtFormatted", R.string.TodayAtFormatted, getInstance().formatterDay.format(new Date(date)));
} else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) {
return getInstance().formatterScheduleDay.format(new Date(date));
} else {
return getInstance().chatFullDate.format(new Date(date));
}
} catch (Exception e) {
FileLog.e(e);
}
return "LOC_ERR";
}
public static String formatDateTime(long date) {
try {
date *= 1000;

View File

@ -15,6 +15,8 @@ import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DownloadManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothProfile;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@ -2385,7 +2387,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
final File cacheFile = file != null ? file : FileLoader.getInstance(currentAccount).getPathToMessage(nextAudio.messageOwner);
boolean exist = cacheFile.exists();
if (cacheFile != file && !cacheFile.exists()) {
FileLoader.getInstance(currentAccount).loadFile(nextAudio.getDocument(), nextAudio, 0, 0);
FileLoader.getInstance(currentAccount).loadFile(nextAudio.getDocument(), nextAudio, FileLoader.PRIORITY_LOW, 0);
}
}
@ -2424,7 +2426,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
final File cacheFile = file != null ? file : FileLoader.getInstance(currentAccount).getPathToMessage(nextAudio.messageOwner);
boolean exist = cacheFile.exists();
if (cacheFile != file && !cacheFile.exists() && nextAudio.isMusic()) {
FileLoader.getInstance(currentAccount).loadFile(nextAudio.getDocument(), nextAudio, 0, 0);
FileLoader.getInstance(currentAccount).loadFile(nextAudio.getDocument(), nextAudio, FileLoader.PRIORITY_LOW, 0);
}
}
@ -2854,7 +2856,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
});
} else {
AndroidUtilities.runOnUIThread(() -> accountInstance.getFileLoader().loadFile(document, null, 1, 1));
AndroidUtilities.runOnUIThread(() -> accountInstance.getFileLoader().loadFile(document, null, FileLoader.PRIORITY_NORMAL, 1));
}
});
}
@ -2876,6 +2878,25 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
} catch (Exception ignore) {}
}
private void setBluetoothScoOn(boolean scoOn) {
AudioManager am = (AudioManager) ApplicationLoader.applicationContext.getSystemService(Context.AUDIO_SERVICE);
if (am.isBluetoothScoAvailableOffCall() && SharedConfig.recordViaSco || !scoOn) {
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
try {
if (btAdapter != null && btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET) == BluetoothProfile.STATE_CONNECTED || !scoOn) {
if (scoOn && !am.isBluetoothScoOn()) {
am.startBluetoothSco();
} else if (!scoOn && am.isBluetoothScoOn()) {
am.stopBluetoothSco();
}
}
} catch (SecurityException ignored) {
} catch (Throwable e) {
FileLog.e(e);
}
}
}
public boolean playMessage(final MessageObject messageObject) {
if (messageObject == null) {
return false;
@ -2918,7 +2939,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
final File cacheFile = file != null ? file : FileLoader.getInstance(messageObject.currentAccount).getPathToMessage(messageObject.messageOwner);
boolean canStream = SharedConfig.streamMedia && (messageObject.isMusic() || messageObject.isRoundVideo() || messageObject.isVideo() && messageObject.canStreamVideo()) && !DialogObject.isEncryptedDialog(messageObject.getDialogId());
if (cacheFile != file && !(exists = cacheFile.exists()) && !canStream) {
FileLoader.getInstance(messageObject.currentAccount).loadFile(messageObject.getDocument(), messageObject, 0, 0);
FileLoader.getInstance(messageObject.currentAccount).loadFile(messageObject.getDocument(), messageObject, FileLoader.PRIORITY_LOW, 0);
downloadingCurrentMessage = true;
isPaused = false;
lastProgress = 0;
@ -3519,6 +3540,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
return;
}
setBluetoothScoOn(true);
sendAfterDone = 0;
recordingAudio = new TLRPC.TL_document();
recordingGuid = guid;
@ -3564,6 +3587,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
} catch (Exception e2) {
FileLog.e(e2);
}
setBluetoothScoOn(false);
AndroidUtilities.runOnUIThread(() -> {
recordStartRunnable = null;
@ -3635,7 +3659,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
if (duration > 700) {
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.beforeAudioDidSent, recordingGuid, send == 2 ? audioToSend : null, send == 2 ? recordingAudioFileToSend.getAbsolutePath() : null);
if (send == 1) {
SendMessagesHelper.getInstance(recordingCurrentAccount).sendMessage(audioToSend, null, recordingAudioFileToSend.getAbsolutePath(), recordDialogId, recordReplyingMsg, recordReplyingTopMsg, null, null, null, null, notify, scheduleDate, 0, null, null);
SendMessagesHelper.getInstance(recordingCurrentAccount).sendMessage(audioToSend, null, recordingAudioFileToSend.getAbsolutePath(), recordDialogId, recordReplyingMsg, recordReplyingTopMsg, null, null, null, null, notify, scheduleDate, 0, null, null, false);
}
NotificationCenter.getInstance(recordingCurrentAccount).postNotificationName(NotificationCenter.audioDidSent, recordingGuid, send == 2 ? audioToSend : null, send == 2 ? recordingAudioFileToSend.getAbsolutePath() : null);
} else {
@ -3682,6 +3706,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
sendAfterDoneNotify = notify;
sendAfterDoneScheduleDate = scheduleDate;
audioRecorder.stop();
setBluetoothScoOn(false);
} catch (Exception e) {
FileLog.e(e);
if (recordingAudioFile != null) {
@ -3854,7 +3879,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
}
String fileName = FileLoader.getAttachFileName(document);
loadingMessageObjects.put(fileName, messageObject);
currentAccount.getFileLoader().loadFile(document, messageObject, 1, 0);
currentAccount.getFileLoader().loadFile(document, messageObject, FileLoader.PRIORITY_LOW, 0);
});
}

View File

@ -55,6 +55,7 @@ import org.telegram.messenger.ringtone.RingtoneUploader;
import org.telegram.messenger.support.SparseLongArray;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.RequestDelegate;
import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
@ -65,7 +66,10 @@ import org.telegram.ui.Components.AnimatedEmojiSpan;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.ChatThemeBottomSheet;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.Reactions.ReactionsUtils;
import org.telegram.ui.Components.StickerSetBulletinLayout;
import org.telegram.ui.Components.StickersArchiveAlert;
import org.telegram.ui.Components.TextStyleSpan;
@ -174,6 +178,7 @@ public class MediaDataController extends BaseController {
loadStickersByEmojiOrName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME, false, true);
loadEmojiThemes();
loadRecentAndTopReactions(false);
ringtoneDataStore = new RingtoneDataStore(currentAccount);
}
@ -200,6 +205,7 @@ public class MediaDataController extends BaseController {
private String doubleTapReaction;
private boolean isLoadingReactions;
private int reactionsUpdateDate;
private boolean reactionsCacheGenerated;
private TLRPC.TL_help_premiumPromo premiumPromo;
private boolean isLoadingPremiumPromo;
@ -213,6 +219,7 @@ public class MediaDataController extends BaseController {
private ArrayList<Long> uninstalledForceStickerSetsById = new ArrayList<>();
private LongSparseArray<TLRPC.TL_messages_stickerSet> groupStickerSets = new LongSparseArray<>();
private ConcurrentHashMap<String, TLRPC.TL_messages_stickerSet> stickerSetsByName = new ConcurrentHashMap<>(100, 1.0f, 1);
private TLRPC.TL_messages_stickerSet stickerSetDefaultStatuses = null;
private HashMap<String, TLRPC.TL_messages_stickerSet> diceStickerSetsByEmoji = new HashMap<>();
private LongSparseArray<String> diceEmojiStickerSetsById = new LongSparseArray<>();
private HashSet<String> loadingDiceStickerSets = new HashSet<>();
@ -240,24 +247,25 @@ public class MediaDataController extends BaseController {
new ArrayList<>(),
new ArrayList<>(),
new ArrayList<>(),
new ArrayList<>()
new ArrayList<>(),
};
private boolean[] loadingRecentStickers = new boolean[8];
private boolean[] recentStickersLoaded = new boolean[8];
private boolean[] loadingRecentStickers = new boolean[9];
private boolean[] recentStickersLoaded = new boolean[9];
private ArrayList<TLRPC.Document> recentGifs = new ArrayList<>();
private boolean loadingRecentGifs;
private boolean recentGifsLoaded;
private boolean loadingPremiumGiftStickers;
private boolean loadingGenericAnimations;
private long loadFeaturedHash[] = new long[2];
private int loadFeaturedDate[] = new int[2];
public boolean loadFeaturedPremium;
private ArrayList<TLRPC.StickerSetCovered>[] featuredStickerSets = new ArrayList[] { new ArrayList<>(), new ArrayList<>() };
private LongSparseArray<TLRPC.StickerSetCovered>[] featuredStickerSetsById = new LongSparseArray[] { new LongSparseArray<>(), new LongSparseArray<>() };
private ArrayList<Long> unreadStickerSets[] = new ArrayList[] { new ArrayList<Long>(), new ArrayList<Long>() };
private ArrayList<Long> readingStickerSets[] = new ArrayList[] { new ArrayList<Long>(), new ArrayList<Long>() };
private ArrayList<TLRPC.StickerSetCovered>[] featuredStickerSets = new ArrayList[]{new ArrayList<>(), new ArrayList<>()};
private LongSparseArray<TLRPC.StickerSetCovered>[] featuredStickerSetsById = new LongSparseArray[]{new LongSparseArray<>(), new LongSparseArray<>()};
private ArrayList<Long> unreadStickerSets[] = new ArrayList[]{new ArrayList<Long>(), new ArrayList<Long>()};
private ArrayList<Long> readingStickerSets[] = new ArrayList[]{new ArrayList<Long>(), new ArrayList<Long>()};
private boolean loadingFeaturedStickers[] = new boolean[2];
private boolean featuredStickersLoaded[] = new boolean[2];
@ -268,6 +276,12 @@ public class MediaDataController extends BaseController {
public final ArrayList<TLRPC.Document> premiumPreviewStickers = new ArrayList<>();
boolean previewStickersLoading;
private long[] emojiStatusesHash = new long[2];
private ArrayList<TLRPC.EmojiStatus>[] emojiStatuses = new ArrayList[2];
private Long[] emojiStatusesFetchDate = new Long[2];
private boolean[] emojiStatusesFromCacheFetched = new boolean[2];
private boolean[] emojiStatusesFetching = new boolean[2];
public void cleanup() {
for (int a = 0; a < recentStickers.length; a++) {
if (recentStickers[a] != null) {
@ -633,30 +647,46 @@ public class MediaDataController extends BaseController {
}
public void preloadReactions() {
if (reactionsList == null) {
if (reactionsList == null || reactionsCacheGenerated) {
return;
}
reactionsCacheGenerated = true;
ArrayList<TLRPC.TL_availableReaction> arrayList = new ArrayList<>(reactionsList);
for (int i = 0; i < arrayList.size(); i++) {
TLRPC.TL_availableReaction reaction = arrayList.get(i);
int size = ReactionsEffectOverlay.sizeForBigReaction();
preloadImage(ImageLocation.getForDocument(reaction.effect_animation), size + "_" + size + "_pcache");
preloadImage(ImageLocation.getForDocument(reaction.around_animation), ReactionsEffectOverlay.getFilterForAroundAnimation(), true);
preloadImage(ImageLocation.getForDocument(reaction.effect_animation), size + "_" + size);
preloadImage(ImageLocation.getForDocument(reaction.activate_animation), null);
preloadImage(ImageLocation.getForDocument(reaction.appear_animation), "60_60_nolimit");
preloadImage(ImageLocation.getForDocument(reaction.appear_animation), ReactionsUtils.APPEAR_ANIMATION_FILTER);
size = ReactionsEffectOverlay.sizeForAroundReaction();
preloadImage(ImageLocation.getForDocument(reaction.around_animation), size + "_" + size + "_pcache");
preloadImage(ImageLocation.getForDocument(reaction.center_icon), null);
preloadImage(ImageLocation.getForDocument(reaction.center_icon), null);
}
}
private void preloadImage(ImageLocation location, String filter) {
ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setDelegate((imageReceiver1, set, thumb, memCache) -> imageReceiver1.clearImage());
//imageReceiver.setFileLoadingPriority(FileLoader.PRIORITY_LOW);
preloadImage(location, filter, false);
}
private void preloadImage(ImageLocation location, String filter, boolean log) {
ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setDelegate((imageReceiver1, set, thumb, memCache) -> {
if (set) {
RLottieDrawable rLottieDrawable = imageReceiver.getLottieAnimation();
if (rLottieDrawable != null) {
rLottieDrawable.checkCache(() -> {
imageReceiver.clearImage();
imageReceiver.setDelegate(null);
});
} else {
imageReceiver.clearImage();
imageReceiver.setDelegate(null);
}
}
});
imageReceiver.setFileLoadingPriority(FileLoader.PRIORITY_LOW);
imageReceiver.setUniqKeyPrefix("preload");
imageReceiver.setImage(location, filter, null, null, 0, FileLoader.PRELOAD_CACHE_TYPE);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);
}
private void putReactionsToCache(List<TLRPC.TL_availableReaction> reactions, int hash, int date) {
@ -697,13 +727,13 @@ public class MediaDataController extends BaseController {
public void checkFeaturedStickers() {
if (!loadingFeaturedStickers[0] && (!featuredStickersLoaded[0] || Math.abs(System.currentTimeMillis() / 1000 - loadFeaturedDate[0]) >= 60 * 60)) {
loadFeaturedStickers(false,true, false);
loadFeaturedStickers(false, true, false);
}
}
public void checkFeaturedEmoji() {
if (!loadingFeaturedStickers[1] && (!featuredStickersLoaded[1] || Math.abs(System.currentTimeMillis() / 1000 - loadFeaturedDate[1]) >= 60 * 60)) {
loadFeaturedStickers(true,true, false);
loadFeaturedStickers(true, true, false);
}
}
@ -738,7 +768,7 @@ public class MediaDataController extends BaseController {
public void clearRecentStickers() {
TLRPC.TL_messages_clearRecentStickers req = new TLRPC.TL_messages_clearRecentStickers();
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()-> {
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (response instanceof TLRPC.TL_boolTrue) {
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
@ -1034,6 +1064,7 @@ public class MediaDataController extends BaseController {
public TLRPC.TL_messages_stickerSet getStickerSet(TLRPC.InputStickerSet inputStickerSet, boolean cacheOnly) {
return getStickerSet(inputStickerSet, cacheOnly, null);
}
public TLRPC.TL_messages_stickerSet getStickerSet(TLRPC.InputStickerSet inputStickerSet, boolean cacheOnly, Runnable onNotFound) {
if (inputStickerSet == null) {
return null;
@ -1042,6 +1073,8 @@ public class MediaDataController extends BaseController {
return stickerSetsById.get(inputStickerSet.id);
} else if (inputStickerSet instanceof TLRPC.TL_inputStickerSetShortName && inputStickerSet.short_name != null && stickerSetsByName.containsKey(inputStickerSet.short_name.toLowerCase())) {
return stickerSetsByName.get(inputStickerSet.short_name.toLowerCase());
} else if (inputStickerSet instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses && stickerSetDefaultStatuses != null) {
return stickerSetDefaultStatuses;
}
if (cacheOnly) {
return null;
@ -1057,6 +1090,9 @@ public class MediaDataController extends BaseController {
}
stickerSetsById.put(set.set.id, set);
stickerSetsByName.put(set.set.short_name.toLowerCase(), set);
if (inputStickerSet instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses) {
stickerSetDefaultStatuses = set;
}
getNotificationCenter().postNotificationName(NotificationCenter.groupStickersDidLoad, set.set.id, set);
});
} else {
@ -1578,9 +1614,9 @@ public class MediaDataController extends BaseController {
editor.putLong("lastStickersLoadTimeMask", System.currentTimeMillis()).commit();
} else if (type == TYPE_GREETINGS) {
editor.putLong("lastStickersLoadTimeGreet", System.currentTimeMillis()).commit();
} else if (type == TYPE_EMOJIPACKS){
} else if (type == TYPE_EMOJIPACKS) {
editor.putLong("lastStickersLoadTimeEmojiPacks", System.currentTimeMillis()).commit();
} else if (type == TYPE_PREMIUM_STICKERS){
} else if (type == TYPE_PREMIUM_STICKERS) {
editor.putLong("lastStickersLoadTimePremiumStickers", System.currentTimeMillis()).commit();
} else {
editor.putLong("lastStickersLoadTimeFavs", System.currentTimeMillis()).commit();
@ -1604,7 +1640,7 @@ public class MediaDataController extends BaseController {
}
}
public void reorderStickers(int type, ArrayList<Long> order) {
public void reorderStickers(int type, ArrayList<Long> order, boolean forceUpdateUi) {
Collections.sort(stickerSets[type], (lhs, rhs) -> {
int index1 = order.indexOf(lhs.set.id);
int index2 = order.indexOf(rhs.set.id);
@ -1616,8 +1652,8 @@ public class MediaDataController extends BaseController {
return 0;
});
loadHash[type] = calcStickersHash(stickerSets[type]);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type);
loadStickers(type, false, true);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, forceUpdateUi);
//loadStickers(type, false, true);
}
public void calcNewHash(int type) {
@ -1668,7 +1704,7 @@ public class MediaDataController extends BaseController {
}
}
loadHash[type] = calcStickersHash(stickerSets[type]);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);
loadStickers(type, false, true);
}
@ -1734,7 +1770,7 @@ public class MediaDataController extends BaseController {
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (response instanceof TLRPC.TL_messages_featuredStickers) {
TLRPC.TL_messages_featuredStickers res = (TLRPC.TL_messages_featuredStickers) response;
processLoadedFeaturedStickers(emoji, res.sets, res.unread, res.premium,false, (int) (System.currentTimeMillis() / 1000), res.hash);
processLoadedFeaturedStickers(emoji, res.sets, res.unread, res.premium, false, (int) (System.currentTimeMillis() / 1000), res.hash);
} else {
processLoadedFeaturedStickers(emoji, null, null, false, false, (int) (System.currentTimeMillis() / 1000), hash);
}
@ -1753,6 +1789,7 @@ public class MediaDataController extends BaseController {
if (res != null && hash != 0) {
loadFeaturedHash[emoji ? 1 : 0] = hash;
}
loadingFeaturedStickers[emoji ? 1 : 0] = false;
loadFeaturedStickers(emoji, false, false);
}, res == null && !cache ? 1000 : 0);
if (res == null) {
@ -2103,13 +2140,46 @@ public class MediaDataController extends BaseController {
getUserConfig().lastUpdatedPremiumGiftsStickerPack = System.currentTimeMillis();
getUserConfig().saveConfig(false);
processLoadedDiceStickers(getUserConfig().premiumGiftsStickerPack, false, stickerSet, false, (int)(System.currentTimeMillis() / 1000));
processLoadedDiceStickers(getUserConfig().premiumGiftsStickerPack, false, stickerSet, false, (int) (System.currentTimeMillis() / 1000));
getNotificationCenter().postNotificationName(NotificationCenter.didUpdatePremiumGiftStickers);
}
}));
}
public void checkGenericAnimations() {
if (getUserConfig().genericAnimationsStickerPack != null) {
String packName = getUserConfig().genericAnimationsStickerPack;
TLRPC.TL_messages_stickerSet set = getStickerSetByName(packName);
if (set == null) {
set = getStickerSetByEmojiOrName(packName);
}
if (set == null) {
MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(packName, false, true);
}
}
if (loadingGenericAnimations /*|| System.currentTimeMillis() - getUserConfig().lastUpdatedGenericAnimations < 86400000*/) {
return;
}
loadingGenericAnimations = true;
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
req.stickerset = new TLRPC.TL_inputStickerSetEmojiGenericAnimations();
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (response instanceof TLRPC.TL_messages_stickerSet) {
TLRPC.TL_messages_stickerSet stickerSet = (TLRPC.TL_messages_stickerSet) response;
getUserConfig().genericAnimationsStickerPack = stickerSet.set.short_name;
getUserConfig().lastUpdatedGenericAnimations = System.currentTimeMillis();
getUserConfig().saveConfig(false);
processLoadedDiceStickers(getUserConfig().genericAnimationsStickerPack, false, stickerSet, false, (int) (System.currentTimeMillis() / 1000));
for (int i = 0; i < stickerSet.documents.size(); i++) {
preloadImage(ImageLocation.getForDocument(stickerSet.documents.get(i)), null);
}
}
}));
}
public void loadStickersByEmojiOrName(String name, boolean isEmoji, boolean cache) {
if (loadingDiceStickerSets.contains(name) || isEmoji && diceStickerSetsByEmoji.get(name) != null) {
return;
@ -2326,6 +2396,7 @@ public class MediaDataController extends BaseController {
} else if (type == TYPE_EMOJI) {
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
req.stickerset = new TLRPC.TL_inputStickerSetAnimatedEmoji();
getConnectionsManager().sendRequest(req, (response, error) -> {
if (response instanceof TLRPC.TL_messages_stickerSet) {
ArrayList<TLRPC.TL_messages_stickerSet> newStickerArray = new ArrayList<>();
@ -2457,6 +2528,9 @@ public class MediaDataController extends BaseController {
private static long calcStickersHash(ArrayList<TLRPC.TL_messages_stickerSet> sets) {
long acc = 0;
for (int a = 0; a < sets.size(); a++) {
if (sets.get(a) == null) {
continue;
}
TLRPC.StickerSet set = sets.get(a).set;
if (set.archived) {
continue;
@ -2574,7 +2648,7 @@ public class MediaDataController extends BaseController {
} else if (type == TYPE_FEATURED) {
allStickersFeatured = allStickersNew;
}
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);
if (onFinish != null) {
onFinish.run();
}
@ -2639,7 +2713,7 @@ public class MediaDataController extends BaseController {
ImageLocation imageLocation = ImageLocation.getForSticker(thumb, sticker, thumbVersion);
if (imageLocation != null) {
String ext = imageLocation.imageType == FileLoader.IMAGE_TYPE_LOTTIE ? "tgs" : "webp";
getFileLoader().loadFile(imageLocation, parentObject, ext, 2, 1);
getFileLoader().loadFile(imageLocation, parentObject, ext, FileLoader.PRIORITY_HIGH, 1);
}
}
@ -2649,6 +2723,7 @@ public class MediaDataController extends BaseController {
public void toggleStickerSet(Context context, TLObject stickerSetObject, int toggle, BaseFragment baseFragment, boolean showSettings, boolean showTooltip) {
toggleStickerSet(context, stickerSetObject, toggle, baseFragment, showSettings, showTooltip, null);
}
public void toggleStickerSet(Context context, TLObject stickerSetObject, int toggle, BaseFragment baseFragment, boolean showSettings, boolean showTooltip, Runnable onUndo) {
TLRPC.StickerSet stickerSet;
TLRPC.TL_messages_stickerSet messages_stickerSet;
@ -2741,7 +2816,7 @@ public class MediaDataController extends BaseController {
onUndo.run();
}
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);
}).setDelayedAction(() -> {
if (undoDone[0]) {
return;
@ -2754,7 +2829,7 @@ public class MediaDataController extends BaseController {
Bulletin.make(baseFragment, bulletinLayout, Bulletin.DURATION_LONG).show();
}
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);
}
public void removeMultipleStickerSets(Context context, BaseFragment fragment, ArrayList<TLRPC.TL_messages_stickerSet> sets) {
@ -2795,7 +2870,7 @@ public class MediaDataController extends BaseController {
}
putStickersToCache(type, stickerSets[type], loadDate[type], loadHash[type] = calcStickersHash(stickerSets[type]));
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);
for (int i = 0; i < sets.size(); ++i) {
markSetUninstalling(sets.get(i).set.id, true);
@ -2820,7 +2895,7 @@ public class MediaDataController extends BaseController {
}
putStickersToCache(type, stickerSets[type], loadDate[type], loadHash[type] = calcStickersHash(stickerSets[type]));
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);
}).setDelayedAction(() -> {
if (undoDone[0]) {
return;
@ -2906,7 +2981,7 @@ public class MediaDataController extends BaseController {
loadHash[type] = calcStickersHash(this.stickerSets[type]);
putStickersToCache(type, this.stickerSets[type], loadDate[type], loadHash[type]);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);
TLRPC.TL_messages_toggleStickerSets req = new TLRPC.TL_messages_toggleStickerSets();
req.stickersets = inputStickerSets;
@ -3450,10 +3525,10 @@ public class MediaDataController extends BaseController {
if (message == null) {
return -1;
}
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto) {
return MEDIA_PHOTOVIDEO;
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
TLRPC.Document document = message.media.document;
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaDocument) {
TLRPC.Document document = MessageObject.getMedia(message).document;
if (document == null) {
return -1;
}
@ -3502,9 +3577,9 @@ public class MediaDataController extends BaseController {
}
public static boolean canAddMessageToMedia(TLRPC.Message message) {
if (message instanceof TLRPC.TL_message_secret && (message.media instanceof TLRPC.TL_messageMediaPhoto || MessageObject.isVideoMessage(message) || MessageObject.isGifMessage(message)) && message.media.ttl_seconds != 0 && message.media.ttl_seconds <= 60) {
if (message instanceof TLRPC.TL_message_secret && (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto || MessageObject.isVideoMessage(message) || MessageObject.isGifMessage(message)) && MessageObject.getMedia(message).ttl_seconds != 0 && MessageObject.getMedia(message).ttl_seconds <= 60) {
return false;
} else if (!(message instanceof TLRPC.TL_message_secret) && message instanceof TLRPC.TL_message && (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaDocument) && message.media.ttl_seconds != 0) {
} else if (!(message instanceof TLRPC.TL_message_secret) && message instanceof TLRPC.TL_message && (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto || MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaDocument) && MessageObject.getMedia(message).ttl_seconds != 0) {
return false;
} else {
return getMediaType(message) != -1;
@ -4868,7 +4943,7 @@ public class MediaDataController extends BaseController {
int checkedCount = 0;
for (int a = 0, N = results.size(); a < N; a++) {
TLRPC.Message message = results.get(a);
if (message.media instanceof TLRPC.TL_messageMediaDocument || message.media instanceof TLRPC.TL_messageMediaPhoto) {
if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaDocument || MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto) {
checkedCount++;
}
messageObjects.add(new MessageObject(currentAccount, message, usersDict, chatsDict, false, checkedCount < 30));
@ -4881,7 +4956,7 @@ public class MediaDataController extends BaseController {
int checkedCount = 0;
for (int a = 0, N = results.size(); a < N; a++) {
TLRPC.Message message = results.get(a);
if (message.media instanceof TLRPC.TL_messageMediaDocument || message.media instanceof TLRPC.TL_messageMediaPhoto) {
if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaDocument || MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto) {
checkedCount++;
}
messageObjects.add(new MessageObject(currentAccount, message, usersDict, chatsDict, false, checkedCount < 30));
@ -5746,7 +5821,7 @@ public class MediaDataController extends BaseController {
}
if (spannable instanceof Spannable) {
AndroidUtilities.addLinks((Spannable) spannable, Linkify.WEB_URLS);
AndroidUtilities.addLinks((Spannable) spannable, Linkify.WEB_URLS, false, false);
URLSpan[] spansUrl = spannable.getSpans(0, message[0].length(), URLSpan.class);
if (spansUrl != null && spansUrl.length > 0) {
if (entities == null) {
@ -6339,7 +6414,7 @@ public class MediaDataController extends BaseController {
}
if (!getReactionsList().isEmpty()) {
String savedReaction = MessagesController.getEmojiSettings(currentAccount).getString("reaction_on_double_tap", null);
if (savedReaction != null && getReactionsMap().get(savedReaction) != null) {
if (savedReaction != null && (getReactionsMap().get(savedReaction) != null || savedReaction.startsWith("animated_"))) {
doubleTapReaction = savedReaction;
return doubleTapReaction;
}
@ -6458,6 +6533,30 @@ public class MediaDataController extends BaseController {
checkMenuBots();
checkPremiumPromo();
checkPremiumGiftStickers();
checkGenericAnimations();
}
public void moveStickerSetToTop(long setId, boolean emojis, boolean masks) {
ArrayList<TLRPC.TL_messages_stickerSet> arrayList = null;
int type = 0;
if (emojis) {
type = TYPE_EMOJIPACKS;
} else if (masks) {
type = TYPE_MASK;
} else {
}
arrayList = getStickerSets(type);
if (arrayList != null) {
for (int i = 0; i < arrayList.size(); i++) {
if (arrayList.get(i).set.id == setId) {
TLRPC.TL_messages_stickerSet set = arrayList.get(i);
arrayList.remove(i);
arrayList.add(0, set);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, false);
break;
}
}
}
}
//---------------- BOT END ----------------
@ -6465,11 +6564,14 @@ public class MediaDataController extends BaseController {
//---------------- EMOJI START ----------------
public static class KeywordResult {
public KeywordResult() {}
public KeywordResult() {
}
public KeywordResult(String emoji, String keyword) {
this.emoji = emoji;
this.keyword = keyword;
}
public String emoji;
public String keyword;
}
@ -6613,11 +6715,68 @@ public class MediaDataController extends BaseController {
});
}
public void getAnimatedEmojiByKeywords(String query, Utilities.Callback<ArrayList<Long>> onResult) {
if (query == null) {
if (onResult != null) {
onResult.run(new ArrayList<>());
}
return;
}
final ArrayList<TLRPC.TL_messages_stickerSet> stickerSets = getStickerSets(TYPE_EMOJIPACKS);
final ArrayList<TLRPC.StickerSetCovered> featuredStickerSets = getFeaturedEmojiSets();
Utilities.searchQueue.postRunnable(() -> {
ArrayList<Long> fullMatch = new ArrayList<>();
ArrayList<Long> halfMatch = new ArrayList<>();
String queryLowercased = query.toLowerCase();
for (int i = 0; i < stickerSets.size(); ++i) {
if (stickerSets.get(i).keywords != null) {
ArrayList<TLRPC.TL_stickerKeyword> keywords = stickerSets.get(i).keywords;
for (int j = 0; j < keywords.size(); ++j) {
for (int k = 0; k < keywords.get(j).keyword.size(); ++k) {
String keyword = keywords.get(j).keyword.get(k);
if (queryLowercased.equals(keyword)) {
fullMatch.add(keywords.get(j).document_id);
} else if (queryLowercased.contains(keyword) || keyword.contains(queryLowercased)) {
halfMatch.add(keywords.get(j).document_id);
}
}
}
}
}
for (int i = 0; i < featuredStickerSets.size(); ++i) {
if (featuredStickerSets.get(i) instanceof TLRPC.TL_stickerSetFullCovered &&
((TLRPC.TL_stickerSetFullCovered) featuredStickerSets.get(i)).keywords != null) {
ArrayList<TLRPC.TL_stickerKeyword> keywords = ((TLRPC.TL_stickerSetFullCovered) featuredStickerSets.get(i)).keywords;
for (int j = 0; j < keywords.size(); ++j) {
for (int k = 0; k < keywords.get(j).keyword.size(); ++k) {
String keyword = keywords.get(j).keyword.get(k);
if (queryLowercased.equals(keyword)) {
fullMatch.add(keywords.get(j).document_id);
} else if (queryLowercased.contains(keyword) || keyword.contains(queryLowercased)) {
halfMatch.add(keywords.get(j).document_id);
}
}
}
}
}
fullMatch.addAll(halfMatch);
if (onResult != null) {
onResult.run(fullMatch);
}
});
}
public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, boolean allowAnimated) {
getEmojiSuggestions(langCodes, keyword, fullMatch, callback, null, allowAnimated);
getEmojiSuggestions(langCodes, keyword, fullMatch, callback, null, allowAnimated, null);
}
public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, final CountDownLatch sync, boolean allowAnimated) {
getEmojiSuggestions(langCodes, keyword, fullMatch, callback, sync, allowAnimated, null);
}
public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, final CountDownLatch sync, boolean allowAnimated, Integer maxAnimatedPerEmoji) {
if (callback == null) {
return;
}
@ -6729,7 +6888,7 @@ public class MediaDataController extends BaseController {
});
String aliasFinal = alias;
if (allowAnimated && SharedConfig.suggestAnimatedEmoji) {
fillWithAnimatedEmoji(result, null, () -> {
fillWithAnimatedEmoji(result, maxAnimatedPerEmoji, () -> {
if (sync != null) {
callback.run(result, aliasFinal);
sync.countDown();
@ -6756,6 +6915,7 @@ public class MediaDataController extends BaseController {
}
private boolean triedLoadingEmojipacks = false;
public void fillWithAnimatedEmoji(ArrayList<KeywordResult> result, Integer maxAnimatedPerEmojiInput, Runnable onDone) {
if (result == null || result.isEmpty()) {
if (onDone != null) {
@ -6770,7 +6930,8 @@ public class MediaDataController extends BaseController {
ArrayList<KeywordResult> animatedResult = new ArrayList<>();
ArrayList<TLRPC.Document> animatedEmoji = new ArrayList<>();
final int maxAnimatedPerEmoji = maxAnimatedPerEmojiInput == null ? (result.size() > 5 ? 1 : (result.size() > 2 ? 2 : 3)) : maxAnimatedPerEmojiInput;
for (int i = 0; i < Math.min(15, result.size()); ++i) {
int len = maxAnimatedPerEmojiInput == null ? Math.min(15, result.size()) : result.size();
for (int i = 0; i < len; ++i) {
String emoji = result.get(i).emoji;
if (emoji == null) {
continue;
@ -6803,17 +6964,6 @@ public class MediaDataController extends BaseController {
for (int d = 0; d < set.documents.size(); ++d) {
TLRPC.Document document = set.documents.get(d);
if (document != null && document.attributes != null && !animatedEmoji.contains(document)) {
boolean duplicate = false;
for (int l = 0; l < animatedEmoji.size(); ++l) {
if (animatedEmoji.get(l).id == document.id) {
duplicate = true;
break;
}
}
if (duplicate) {
continue;
}
TLRPC.TL_documentAttributeCustomEmoji attribute = null;
for (int k = 0; k < document.attributes.size(); ++k) {
TLRPC.DocumentAttribute attr = document.attributes.get(k);
@ -6824,9 +6974,18 @@ public class MediaDataController extends BaseController {
}
if (attribute != null && emoji.equals(attribute.alt) && (isPremium || attribute.free)) {
animatedEmoji.add(document);
if (animatedEmoji.size() >= maxAnimatedPerEmoji) {
break;
boolean duplicate = false;
for (int l = 0; l < animatedEmoji.size(); ++l) {
if (animatedEmoji.get(l).id == document.id) {
duplicate = true;
break;
}
}
if (!duplicate) {
animatedEmoji.add(document);
if (animatedEmoji.size() >= maxAnimatedPerEmoji) {
break;
}
}
}
}
@ -6850,17 +7009,6 @@ public class MediaDataController extends BaseController {
for (int d = 0; d < documents.size(); ++d) {
TLRPC.Document document = documents.get(d);
if (document != null && document.attributes != null && !animatedEmoji.contains(document)) {
boolean duplicate = false;
for (int l = 0; l < animatedEmoji.size(); ++l) {
if (animatedEmoji.get(l).id == document.id) {
duplicate = true;
break;
}
}
if (duplicate) {
continue;
}
TLRPC.TL_documentAttributeCustomEmoji attribute = null;
for (int k = 0; k < document.attributes.size(); ++k) {
TLRPC.DocumentAttribute attr = document.attributes.get(k);
@ -6871,9 +7019,18 @@ public class MediaDataController extends BaseController {
}
if (attribute != null && emoji.equals(attribute.alt) && (isPremium || attribute.free)) {
animatedEmoji.add(document);
if (animatedEmoji.size() >= maxAnimatedPerEmoji) {
break;
boolean duplicate = false;
for (int l = 0; l < animatedEmoji.size(); ++l) {
if (animatedEmoji.get(l).id == document.id) {
duplicate = true;
break;
}
}
if (!duplicate) {
animatedEmoji.add(document);
if (animatedEmoji.size() >= maxAnimatedPerEmoji) {
break;
}
}
}
}
@ -6907,12 +7064,12 @@ public class MediaDataController extends BaseController {
final boolean[] done = new boolean[1];
AndroidUtilities.runOnUIThread(() -> {
loadStickers(TYPE_EMOJIPACKS, true, false, false, packs -> {
if (!done[0]) {
emojiPacks[0] = packs;
fillRunnable.run();
done[0] = true;
}
});
if (!done[0]) {
emojiPacks[0] = packs;
fillRunnable.run();
done[0] = true;
}
});
});
AndroidUtilities.runOnUIThread(() -> {
if (!done[0]) {
@ -7001,4 +7158,259 @@ public class MediaDataController extends BaseController {
}
//---------------- EMOJI END ----------------
public ArrayList<TLRPC.EmojiStatus> getDefaultEmojiStatuses() {
final int type = 1; // default
if (!emojiStatusesFromCacheFetched[type]) {
fetchEmojiStatuses(type, true);
} else if (/*emojiStatusesHash[type] == 0 || */emojiStatusesFetchDate[type] == null || (System.currentTimeMillis() / 1000 - emojiStatusesFetchDate[type]) > 60 * 30) {
fetchEmojiStatuses(type, false);
}
return emojiStatuses[type];
}
public ArrayList<TLRPC.EmojiStatus> getRecentEmojiStatuses() {
final int type = 0; // recent
if (!emojiStatusesFromCacheFetched[type]) {
fetchEmojiStatuses(type, true);
} else if (/*emojiStatusesHash[type] == 0 || */emojiStatusesFetchDate[type] == null || (System.currentTimeMillis() / 1000 - emojiStatusesFetchDate[type]) > 60 * 30) {
fetchEmojiStatuses(type, false);
}
return emojiStatuses[type];
}
public ArrayList<TLRPC.EmojiStatus> clearRecentEmojiStatuses() {
final int type = 0; // recent
if (emojiStatuses[type] != null) {
emojiStatuses[type].clear();
}
emojiStatusesHash[type] = 0;
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
getMessagesStorage().getDatabase().executeFast("DELETE FROM emoji_statuses WHERE type = " + type).stepThis().dispose();
} catch (Exception e) {}
});
return emojiStatuses[type];
}
public void pushRecentEmojiStatus(TLRPC.EmojiStatus status) {
final int type = 0; // recent
if (emojiStatuses[type] != null) {
if (status instanceof TLRPC.TL_emojiStatus) {
long documentId = ((TLRPC.TL_emojiStatus) status).document_id;
for (int i = 0; i < emojiStatuses[type].size(); ++i) {
if (emojiStatuses[type].get(i) instanceof TLRPC.TL_emojiStatus &&
((TLRPC.TL_emojiStatus) emojiStatuses[type].get(i)).document_id == documentId) {
emojiStatuses[type].remove(i--);
}
}
}
emojiStatuses[type].add(0, status);
while (emojiStatuses[type].size() > 50) {
emojiStatuses[type].remove(emojiStatuses[type].size() - 1);
}
TLRPC.TL_account_emojiStatuses statuses = new TLRPC.TL_account_emojiStatuses();
// todo: calc hash
statuses.hash = emojiStatusesHash[type];
statuses.statuses = emojiStatuses[type];
updateEmojiStatuses(type, statuses);
}
}
public void fetchEmojiStatuses(int type, boolean cache) {
if (emojiStatusesFetching[type]) {
return;
}
emojiStatusesFetching[type] = true;
if (cache) {
getMessagesStorage().getStorageQueue().postRunnable(() -> {
boolean done = false;
try {
SQLiteCursor cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT data FROM emoji_statuses WHERE type = " + type + " LIMIT 1");
if (cursor.next() && cursor.getColumnCount() > 0 && !cursor.isNull(0)) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
TLRPC.account_EmojiStatuses response = TLRPC.account_EmojiStatuses.TLdeserialize(data, data.readInt32(false), false);
if (response instanceof TLRPC.TL_account_emojiStatuses) {
emojiStatusesHash[type] = response.hash;
emojiStatuses[type] = response.statuses;
done = true;
}
data.reuse();
}
}
cursor.dispose();
} catch (Exception e) {
FileLog.e(e);
}
emojiStatusesFromCacheFetched[type] = true;
emojiStatusesFetching[type] = false;
if (done) {
AndroidUtilities.runOnUIThread(() -> {
getNotificationCenter().postNotificationName(NotificationCenter.recentEmojiStatusesUpdate);
});
} else {
fetchEmojiStatuses(type, false);
}
});
} else {
TLObject req;
if (type == 0) {
TLRPC.TL_account_getRecentEmojiStatuses recentReq = new TLRPC.TL_account_getRecentEmojiStatuses();
recentReq.hash = emojiStatusesHash[type];
req = recentReq;
} else {
TLRPC.TL_account_getDefaultEmojiStatuses defaultReq = new TLRPC.TL_account_getDefaultEmojiStatuses();
defaultReq.hash = emojiStatusesHash[type];
req = defaultReq;
}
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> {
emojiStatusesFetchDate[type] = System.currentTimeMillis() / 1000;
if (res instanceof TLRPC.TL_account_emojiStatusesNotModified) {
emojiStatusesFetching[type] = false;
} else if (res instanceof TLRPC.TL_account_emojiStatuses) {
TLRPC.TL_account_emojiStatuses response = (TLRPC.TL_account_emojiStatuses) res;
emojiStatusesHash[type] = response.hash;
emojiStatuses[type] = response.statuses;
updateEmojiStatuses(type, response);
AndroidUtilities.runOnUIThread(() -> {
getNotificationCenter().postNotificationName(NotificationCenter.recentEmojiStatusesUpdate);
});
}
});
}
}
private void updateEmojiStatuses(int type, TLRPC.TL_account_emojiStatuses response) {
getMessagesStorage().getStorageQueue().postRunnable(() -> {
try {
getMessagesStorage().getDatabase().executeFast("DELETE FROM emoji_statuses WHERE type = " + type).stepThis().dispose();
SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("INSERT INTO emoji_statuses VALUES(?, ?)");
state.requery();
NativeByteBuffer data = new NativeByteBuffer(response.getObjectSize());
response.serializeToStream(data);
state.bindByteBuffer(1, data);
state.bindInteger(2, type);
state.step();
data.reuse();
state.dispose();
} catch (Exception e) {
FileLog.e(e);
}
emojiStatusesFetching[type] = false;
});
}
ArrayList<TLRPC.Reaction> recentReactions = new ArrayList<>();
ArrayList<TLRPC.Reaction> topReactions = new ArrayList<>();
boolean loadingRecentReactions;
public ArrayList<TLRPC.Reaction> getRecentReactions() {
return recentReactions;
}
public void clearRecentReactions() {
recentReactions.clear();
SharedPreferences recentReactionsPref = ApplicationLoader.applicationContext.getSharedPreferences("recent_reactions_" + currentAccount, Context.MODE_PRIVATE);
recentReactionsPref.edit().clear().apply();
TLRPC.TL_messages_clearRecentReactions clearRecentReaction = new TLRPC.TL_messages_clearRecentReactions();
ConnectionsManager.getInstance(currentAccount).sendRequest(clearRecentReaction, new RequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
});
}
public ArrayList<TLRPC.Reaction> getTopReactions() {
return topReactions;
}
public void loadRecentAndTopReactions(boolean force) {
if (loadingRecentReactions || !recentReactions.isEmpty() || force) {
return;
}
SharedPreferences recentReactionsPref = ApplicationLoader.applicationContext.getSharedPreferences("recent_reactions_" + currentAccount, Context.MODE_PRIVATE);
SharedPreferences topReactionsPref = ApplicationLoader.applicationContext.getSharedPreferences("top_reactions_" + currentAccount, Context.MODE_PRIVATE);
recentReactions.clear();
topReactions.clear();
recentReactions.addAll(loadReactionsFromPref(recentReactionsPref));
topReactions.addAll(loadReactionsFromPref(topReactionsPref));
loadingRecentReactions = true;
boolean loadFromServer = true;
if (loadFromServer) {
TLRPC.TL_messages_getRecentReactions recentReactionsRequest = new TLRPC.TL_messages_getRecentReactions();
recentReactionsRequest.hash = recentReactionsPref.getLong("hash", 0);
recentReactionsRequest.limit = 50;
ConnectionsManager.getInstance(currentAccount).sendRequest(recentReactionsRequest, (response, error) -> {
if (error == null) {
if (response instanceof TLRPC.TL_messages_reactions) {
TLRPC.TL_messages_reactions reactions = (TLRPC.TL_messages_reactions) response;
recentReactions.clear();
recentReactions.addAll(reactions.reactions);
saveReactionsToPref(recentReactionsPref, reactions.hash, reactions.reactions);
}
if (response instanceof TLRPC.TL_messages_reactionsNotModified) {
}
}
});
TLRPC.TL_messages_getTopReactions topReactionsRequest = new TLRPC.TL_messages_getTopReactions();
topReactionsRequest.hash = topReactionsPref.getLong("hash", 0);
topReactionsRequest.limit = 100;
ConnectionsManager.getInstance(currentAccount).sendRequest(topReactionsRequest, (response, error) -> {
if (error == null) {
if (response instanceof TLRPC.TL_messages_reactions) {
TLRPC.TL_messages_reactions reactions = (TLRPC.TL_messages_reactions) response;
topReactions.clear();
topReactions.addAll(reactions.reactions);
saveReactionsToPref(topReactionsPref, reactions.hash, reactions.reactions);
}
if (response instanceof TLRPC.TL_messages_reactionsNotModified) {
}
}
});
}
}
public static void saveReactionsToPref(SharedPreferences preferences, long hash, ArrayList<? extends TLObject> object) {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt("count", object.size());
editor.putLong("hash", hash);
for (int i = 0; i < object.size(); ++i) {
TLObject tlObject = object.get(i);
SerializedData data = new SerializedData(tlObject.getObjectSize());
tlObject.serializeToStream(data);
editor.putString("object_" + i, Utilities.bytesToHex(data.toByteArray()));
}
editor.apply();
}
public static ArrayList<TLRPC.Reaction> loadReactionsFromPref(SharedPreferences preferences) {
int count = preferences.getInt("count", 0);
ArrayList<TLRPC.Reaction> objects = new ArrayList<>(count);
if (count > 0) {
for (int i = 0; i < count; ++i) {
String value = preferences.getString("object_" + i, "");
SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value));
try {
objects.add(TLRPC.Reaction.TLdeserialize(serializedData, serializedData.readInt32(true), true));
} catch (Throwable e) {
FileLog.e(e);
}
}
}
return objects;
}
}

View File

@ -32,8 +32,6 @@ import androidx.collection.LongSparseArray;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.util.Consumer;
import com.google.android.exoplayer2.util.Log;
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLiteException;
import org.telegram.SQLite.SQLitePreparedStatement;
@ -50,6 +48,7 @@ import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.ChatReactionsEditActivity;
import org.telegram.ui.ChatRightsEditActivity;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
@ -74,6 +73,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
@ -377,6 +377,9 @@ public class MessagesController extends BaseController implements NotificationCe
public int captionLengthLimitPremium;
public int aboutLengthLimitDefault;
public int aboutLengthLimitPremium;
public int reactionsUserMaxDefault;
public int reactionsUserMaxPremium;
public int reactionsInChatMax;
public int uploadMaxFileParts;
public int uploadMaxFilePartsPremium;
@ -391,8 +394,14 @@ public class MessagesController extends BaseController implements NotificationCe
public volatile boolean ignoreSetOnline;
public boolean premiumLocked;
public List<String> directPaymentsCurrency = new ArrayList<>();
public NewMessageCallback newMessageCallback;
private long recentEmojiStatusUpdateRunnableTimeout, recentEmojiStatusUpdateRunnableTime;
private Runnable recentEmojiStatusUpdateRunnable;
private LongSparseArray<Integer> emojiStatusUntilValues = new LongSparseArray<>();
public void getNextReactionMention(long dialogId, int count, Consumer<Integer> callback) {
final MessagesStorage messagesStorage = getMessagesStorage();
messagesStorage.getStorageQueue().postRunnable(() -> {
@ -491,6 +500,14 @@ public class MessagesController extends BaseController implements NotificationCe
return getUserConfig().isPremium() ? aboutLengthLimitPremium : aboutLengthLimitDefault;
}
public int getMaxUserReactionsCount() {
return getUserConfig().isPremium() ? reactionsUserMaxPremium : reactionsUserMaxDefault;
}
public int getChatReactionsCount() {
return getUserConfig().isPremium() ? reactionsInChatMax : 1;
}
public boolean isPremiumUser(TLRPC.User currentUser) {
return !premiumLocked && currentUser.premium;
}
@ -681,6 +698,7 @@ public class MessagesController extends BaseController implements NotificationCe
public static int UPDATE_MASK_CHECK = 65536;
public static int UPDATE_MASK_REORDER = 131072;
public static int UPDATE_MASK_EMOJI_INTERACTIONS = 262144;
public static int UPDATE_MASK_EMOJI_STATUS = 524288;
public static int UPDATE_MASK_ALL = UPDATE_MASK_AVATAR | UPDATE_MASK_STATUS | UPDATE_MASK_NAME | UPDATE_MASK_CHAT_AVATAR | UPDATE_MASK_CHAT_NAME | UPDATE_MASK_CHAT_MEMBERS | UPDATE_MASK_USER_PRINT | UPDATE_MASK_USER_PHONE | UPDATE_MASK_READ_DIALOG_MESSAGE | UPDATE_MASK_PHONE;
public static int PROMO_TYPE_PROXY = 0;
@ -1118,11 +1136,21 @@ public class MessagesController extends BaseController implements NotificationCe
captionLengthLimitPremium = mainPreferences.getInt("captionLengthLimitPremium", 4096);
aboutLengthLimitDefault = mainPreferences.getInt("aboutLengthLimitDefault", 70);
aboutLengthLimitPremium = mainPreferences.getInt("aboutLengthLimitPremium", 140);
reactionsUserMaxDefault = mainPreferences.getInt("reactionsUserMaxDefault", 1);
reactionsUserMaxPremium = mainPreferences.getInt("reactionsUserMaxPremium", 3);
reactionsInChatMax = mainPreferences.getInt("reactionsInChatMax", 3);
uploadMaxFileParts = mainPreferences.getInt("uploadMaxFileParts", (int) (FileLoader.DEFAULT_MAX_FILE_SIZE / 1024L / 512L));
uploadMaxFilePartsPremium = mainPreferences.getInt("uploadMaxFilePartsPremium", uploadMaxFileParts * 2);
premiumInvoiceSlug = mainPreferences.getString("premiumInvoiceSlug", null);
premiumBotUsername = mainPreferences.getString("premiumBotUsername", null);
premiumLocked = mainPreferences.getBoolean("premiumLocked", false);
BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID);
Set<String> currencySet = mainPreferences.getStringSet("directPaymentsCurrency", null);
if (currencySet != null) {
directPaymentsCurrency.clear();
directPaymentsCurrency.addAll(currencySet);
}
loadPremiumFeaturesPreviewOrder(mainPreferences.getString("premiumFeaturesTypesToPosition", null));
if (pendingSuggestions != null) {
@ -1735,6 +1763,40 @@ public class MessagesController extends BaseController implements NotificationCe
for (int a = 0, N = object.value.size(); a < N; a++) {
TLRPC.TL_jsonObjectValue value = object.value.get(a);
switch (value.key) {
case "login_google_oauth_client_id": {
if (value.value instanceof TLRPC.TL_jsonString) {
String str = ((TLRPC.TL_jsonString) value.value).value;
if (!Objects.equals(BuildVars.GOOGLE_AUTH_CLIENT_ID, str)) {
BuildVars.GOOGLE_AUTH_CLIENT_ID = str;
editor.putString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID);
changed = true;
}
}
break;
}
case "premium_playmarket_direct_currency_list": {
if (value.value instanceof TLRPC.TL_jsonArray) {
TLRPC.TL_jsonArray arr = (TLRPC.TL_jsonArray) value.value;
HashSet<String> currencySet = new HashSet<>();
for (TLRPC.JSONValue el : arr.value) {
if (el instanceof TLRPC.TL_jsonString) {
TLRPC.TL_jsonString currencyEl = (TLRPC.TL_jsonString) el;
String currency = currencyEl.value;
currencySet.add(currency);
}
}
if (!(directPaymentsCurrency.containsAll(currencySet) && currencySet.containsAll(directPaymentsCurrency))) {
directPaymentsCurrency.clear();
directPaymentsCurrency.addAll(currencySet);
editor.putStringSet("directPaymentsCurrency", currencySet);
changed = true;
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.billingProductDetailsUpdated);
}
}
break;
}
case "premium_purchase_blocked": {
if (value.value instanceof TLRPC.TL_jsonBool) {
if (premiumLocked != ((TLRPC.TL_jsonBool) value.value).value) {
@ -2502,6 +2564,39 @@ public class MessagesController extends BaseController implements NotificationCe
}
break;
}
case "reactions_user_max_default": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value;
if (number.value != reactionsUserMaxDefault) {
reactionsUserMaxDefault = (int) number.value;
editor.putInt("reactionsUserMaxDefault", reactionsUserMaxDefault);
changed = true;
}
}
break;
}
case "reactions_user_max_premium": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value;
if (number.value != reactionsUserMaxPremium) {
reactionsUserMaxPremium = (int) number.value;
editor.putInt("reactionsUserMaxPremium", reactionsUserMaxPremium);
changed = true;
}
}
break;
}
case "reactions_in_chat_max": {
if (value.value instanceof TLRPC.TL_jsonNumber) {
TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value;
if (number.value != reactionsInChatMax) {
reactionsInChatMax = (int) number.value;
editor.putInt("reactionsInChatMax", reactionsInChatMax);
changed = true;
}
}
break;
}
}
}
if (changed) {
@ -3213,8 +3308,8 @@ public class MessagesController extends BaseController implements NotificationCe
if (message.peer_id.channel_id == 0) {
MessageObject existMessageObject = dialogMessagesByIds.get(message.id);
if (existMessageObject != null) {
existMessageObject.messageOwner.media = message.media;
if (message.media.ttl_seconds != 0 && (message.media.photo instanceof TLRPC.TL_photoEmpty || message.media.document instanceof TLRPC.TL_documentEmpty)) {
existMessageObject.messageOwner.media = MessageObject.getMedia(message);
if (MessageObject.getMedia(message).ttl_seconds != 0 && (MessageObject.getMedia(message).photo instanceof TLRPC.TL_photoEmpty || MessageObject.getMedia(message).document instanceof TLRPC.TL_documentEmpty)) {
existMessageObject.setType();
getNotificationCenter().postNotificationName(NotificationCenter.notificationsSettingsUpdated);
}
@ -3593,6 +3688,7 @@ public class MessagesController extends BaseController implements NotificationCe
if (!TextUtils.isEmpty(user.username)) {
objectsByUsernames.put(user.username.toLowerCase(), user);
}
updateEmojiStatusUntilUpdate(user.id, user.emoji_status);
if (user.min) {
if (oldUser != null) {
if (!fromCache) {
@ -5778,7 +5874,7 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
for (int j = 0; j < sendAsInfo.sendAsPeers.peers.size(); j++) {
if (sendAsInfo.sendAsPeers.peers.get(j).channel_id == -did || sendAsInfo.sendAsPeers.peers.get(j).chat_id == -did) {
if (sendAsInfo.sendAsPeers.peers.get(j).peer.channel_id == -did || sendAsInfo.sendAsPeers.peers.get(j).peer.chat_id == -did) {
sendAsInfo.sendAsPeers.peers.remove(j);
break;
}
@ -7480,19 +7576,19 @@ public class MessagesController extends BaseController implements NotificationCe
if (isCache) {
if (message.legacy && message.layer < TLRPC.LAYER) {
messagesToReload.add(message.id);
} else if (message.media instanceof TLRPC.TL_messageMediaUnsupported) {
if (message.media.bytes != null && (message.media.bytes.length == 0 || message.media.bytes.length == 1 && message.media.bytes[0] < TLRPC.LAYER || message.media.bytes.length == 4 && Utilities.bytesToInt(message.media.bytes) < TLRPC.LAYER)) {
} else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaUnsupported) {
if (MessageObject.getMedia(message).bytes != null && (MessageObject.getMedia(message).bytes.length == 0 || MessageObject.getMedia(message).bytes.length == 1 && MessageObject.getMedia(message).bytes[0] < TLRPC.LAYER || MessageObject.getMedia(message).bytes.length == 4 && Utilities.bytesToInt(MessageObject.getMedia(message).bytes) < TLRPC.LAYER)) {
messagesToReload.add(message.id);
}
}
if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage instanceof TLRPC.TL_webPagePending && message.media.webpage.date <= getConnectionsManager().getCurrentTime()) {
if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaWebPage) {
if (MessageObject.getMedia(message).webpage instanceof TLRPC.TL_webPagePending && MessageObject.getMedia(message).webpage.date <= getConnectionsManager().getCurrentTime()) {
messagesToReload.add(message.id);
} else if (message.media.webpage instanceof TLRPC.TL_webPageUrlPending) {
ArrayList<MessageObject> arrayList = webpagesToReload.get(message.media.webpage.url);
} else if (MessageObject.getMedia(message).webpage instanceof TLRPC.TL_webPageUrlPending) {
ArrayList<MessageObject> arrayList = webpagesToReload.get(MessageObject.getMedia(message).webpage.url);
if (arrayList == null) {
arrayList = new ArrayList<>();
webpagesToReload.put(message.media.webpage.url, arrayList);
webpagesToReload.put(MessageObject.getMedia(message).webpage.url, arrayList);
}
arrayList.add(messageObject);
}
@ -9060,9 +9156,17 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
}
if (currentDialog == null) {
if (BuildVars.DEBUG_PRIVATE_VERSION) {
FileLog.d("can't update dialog " + dialogId + " with new unread " + dialogsToUpdate.valueAt(a));
}
}
if (currentDialog != null) {
int prevCount = currentDialog.unread_count;
currentDialog.unread_count = dialogsToUpdate.valueAt(a);
if (BuildVars.DEBUG_PRIVATE_VERSION) {
FileLog.d("update dialog " + dialogId + " with new unread " + currentDialog.unread_count);
}
if (prevCount != 0 && currentDialog.unread_count == 0) {
if (!isDialogMuted(dialogId)) {
unreadUnmutedDialogs--;
@ -9455,6 +9559,23 @@ public class MessagesController extends BaseController implements NotificationCe
});
}
public void loadExtendedMediaForMessages(long dialogId, ArrayList<MessageObject> visibleObjects) {
if (visibleObjects.isEmpty()) {
return;
}
TLRPC.TL_messages_getExtendedMedia req = new TLRPC.TL_messages_getExtendedMedia();
req.peer = getInputPeer(dialogId);
for (int i = 0; i < visibleObjects.size(); i++) {
MessageObject messageObject = visibleObjects.get(i);
req.id.add(messageObject.getId());
}
getConnectionsManager().sendRequest(req, (response, error) -> {
if (error == null) {
processUpdates((TLRPC.Updates) response, false);
}
});
}
public void loadReactionsForMessages(long dialogId, ArrayList<MessageObject> visibleObjects) {
if (visibleObjects.isEmpty()) {
return;
@ -10428,11 +10549,11 @@ public class MessagesController extends BaseController implements NotificationCe
});
}
public void deleteParticipantFromChat(long chatId, TLRPC.User user, TLRPC.ChatFull info) {
deleteParticipantFromChat(chatId, user, null, info, false, false);
public void deleteParticipantFromChat(long chatId, TLRPC.User user) {
deleteParticipantFromChat(chatId, user, null, false, false);
}
public void deleteParticipantFromChat(long chatId, TLRPC.User user, TLRPC.Chat chat, TLRPC.ChatFull info, boolean forceDelete, boolean revoke) {
public void deleteParticipantFromChat(long chatId, TLRPC.User user, TLRPC.Chat chat, boolean forceDelete, boolean revoke) {
if (user == null && chat == null) {
return;
}
@ -13355,6 +13476,12 @@ public class MessagesController extends BaseController implements NotificationCe
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateUserEmojiStatus) {
interfaceUpdateMask |= UPDATE_MASK_EMOJI_STATUS;
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateUserName) {
interfaceUpdateMask |= UPDATE_MASK_NAME;
if (updatesOnMainThread == null) {
@ -13645,6 +13772,7 @@ public class MessagesController extends BaseController implements NotificationCe
markAsReadMessagesInbox.put(dialogId, update.max_id);
stillUnreadMessagesCount.put(dialogId, update.still_unread_count);
dialogs_read_inbox_max.put(dialogId, Math.max(value, update.max_id));
FileLog.d("TL_updateReadChannelInbox " + dialogId + " new unread " + update.still_unread_count + " from get diff" + fromGetDifference);
} else if (baseUpdate instanceof TLRPC.TL_updateReadChannelOutbox) {
TLRPC.TL_updateReadChannelOutbox update = (TLRPC.TL_updateReadChannelOutbox) baseUpdate;
if (BuildVars.LOGS_ENABLED) {
@ -13755,6 +13883,11 @@ public class MessagesController extends BaseController implements NotificationCe
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateMoveStickerSetToTop) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateSavedGifs) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
@ -13893,7 +14026,12 @@ public class MessagesController extends BaseController implements NotificationCe
} else if (baseUpdate instanceof TLRPC.TL_updateLangPackTooLong) {
TLRPC.TL_updateLangPackTooLong update = (TLRPC.TL_updateLangPackTooLong) baseUpdate;
LocaleController.getInstance().reloadCurrentRemoteLocale(currentAccount, update.lang_code, false);
} else if (baseUpdate instanceof TLRPC.TL_updateFavedStickers) {
} else if (baseUpdate instanceof TLRPC.TL_updateRecentReactions) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
}if (baseUpdate instanceof TLRPC.TL_updateFavedStickers) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
@ -13942,6 +14080,22 @@ public class MessagesController extends BaseController implements NotificationCe
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateMessageExtendedMedia) {
TLRPC.TL_updateMessageExtendedMedia extendedMedia = (TLRPC.TL_updateMessageExtendedMedia) baseUpdate;
if (extendedMedia.extended_media instanceof TLRPC.TL_messageExtendedMedia) {
TLRPC.Message msg = getMessagesStorage().getMessage(DialogObject.getPeerDialogId(extendedMedia.peer), extendedMedia.msg_id);
if (msg != null) {
msg.media.extended_media = extendedMedia.extended_media;
if (messagesArr == null) {
messagesArr = new ArrayList<>();
}
messagesArr.add(msg);
}
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
}
} else if (baseUpdate instanceof TLRPC.TL_updatePeerLocated) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
@ -13969,6 +14123,11 @@ public class MessagesController extends BaseController implements NotificationCe
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateRecentEmojiStatuses) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
}
updatesOnMainThread.add(baseUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateWebViewResultSent) {
if (updatesOnMainThread == null) {
updatesOnMainThread = new ArrayList<>();
@ -14156,8 +14315,23 @@ public class MessagesController extends BaseController implements NotificationCe
} else {
offlineSent = offline;
}
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.updateUserStatus, update);
}
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.updateUserStatus, update);
} else if (baseUpdate instanceof TLRPC.TL_updateUserEmojiStatus) {
TLRPC.TL_updateUserEmojiStatus update = (TLRPC.TL_updateUserEmojiStatus) baseUpdate;
TLRPC.User currentUser = getUser(update.user_id);
if (currentUser != null) {
currentUser.id = update.user_id;
currentUser.emoji_status = update.emoji_status;
if (UserObject.isUserSelf(currentUser)) {
getNotificationCenter().postNotificationName(NotificationCenter.userEmojiStatusUpdated, currentUser);
}
}
TLRPC.User toDbUser = new TLRPC.TL_user();
toDbUser.id = update.user_id;
toDbUser.emoji_status = update.emoji_status;
dbUsers.add(toDbUser);
} else if (baseUpdate instanceof TLRPC.TL_updateUserName) {
TLRPC.TL_updateUserName update = (TLRPC.TL_updateUserName) baseUpdate;
TLRPC.User currentUser = getUser(update.user_id);
@ -14449,7 +14623,9 @@ public class MessagesController extends BaseController implements NotificationCe
} else {
type = MediaDataController.TYPE_IMAGE;
}
getMediaDataController().reorderStickers(type, ((TLRPC.TL_updateStickerSetsOrder) baseUpdate).order);
getMediaDataController().reorderStickers(type, ((TLRPC.TL_updateStickerSetsOrder) baseUpdate).order, false);
} else if (baseUpdate instanceof TLRPC.TL_updateRecentReactions) {
getMediaDataController().loadRecentAndTopReactions(true);
} else if (baseUpdate instanceof TLRPC.TL_updateFavedStickers) {
getMediaDataController().loadRecents(MediaDataController.TYPE_FAVE, false, false, true);
} else if (baseUpdate instanceof TLRPC.TL_updateContactsReset) {
@ -14480,7 +14656,10 @@ public class MessagesController extends BaseController implements NotificationCe
getMediaDataController().markFeaturedStickersAsRead(false, false);
} else if (baseUpdate instanceof TLRPC.TL_updateReadFeaturedEmojiStickers) {
getMediaDataController().markFeaturedStickersAsRead(true, false);
} else if (baseUpdate instanceof TLRPC.TL_updatePhoneCallSignalingData) {
} else if (baseUpdate instanceof TLRPC.TL_updateMoveStickerSetToTop) {
TLRPC.TL_updateMoveStickerSetToTop update = (TLRPC.TL_updateMoveStickerSetToTop) baseUpdate;
getMediaDataController().moveStickerSetToTop(update.stickerset, update.emojis, update.masks);
}else if (baseUpdate instanceof TLRPC.TL_updatePhoneCallSignalingData) {
TLRPC.TL_updatePhoneCallSignalingData data = (TLRPC.TL_updatePhoneCallSignalingData) baseUpdate;
VoIPService svc = VoIPService.getSharedInstance();
if (svc != null) {
@ -14638,6 +14817,9 @@ public class MessagesController extends BaseController implements NotificationCe
TLRPC.TL_updateMessageReactions update = (TLRPC.TL_updateMessageReactions) baseUpdate;
long dialogId = MessageObject.getPeerId(update.peer);
getNotificationCenter().postNotificationName(NotificationCenter.didUpdateReactions, dialogId, update.msg_id, update.reactions);
} else if (baseUpdate instanceof TLRPC.TL_updateMessageExtendedMedia) {
TLRPC.TL_updateMessageExtendedMedia extendedMedia = (TLRPC.TL_updateMessageExtendedMedia) baseUpdate;
getNotificationCenter().postNotificationName(NotificationCenter.didUpdateExtendedMedia, DialogObject.getPeerDialogId(extendedMedia.peer), extendedMedia.msg_id, extendedMedia.extended_media);
} else if (baseUpdate instanceof TLRPC.TL_updateTheme) {
TLRPC.TL_updateTheme update = (TLRPC.TL_updateTheme) baseUpdate;
TLRPC.TL_theme theme = (TLRPC.TL_theme) update.theme;
@ -14648,6 +14830,8 @@ public class MessagesController extends BaseController implements NotificationCe
loadRemoteFilters(true);
} else if (baseUpdate instanceof TLRPC.TL_updateDialogFilters) {
loadRemoteFilters(true);
} else if (baseUpdate instanceof TLRPC.TL_updateRecentEmojiStatuses) {
getNotificationCenter().postNotificationName(NotificationCenter.recentEmojiStatusesUpdate);
} else if (baseUpdate instanceof TLRPC.TL_updateWebViewResultSent) {
TLRPC.TL_updateWebViewResultSent resultSent = (TLRPC.TL_updateWebViewResultSent) baseUpdate;
getNotificationCenter().postNotificationName(NotificationCenter.webViewResultSent, resultSent.query_id);
@ -14998,7 +15182,7 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
}
getNotificationsController().removeDeletedMessagesFromNotifications(deletedMessagesFinal);
getNotificationsController().removeDeletedMessagesFromNotifications(deletedMessagesFinal, false);
}
if (scheduledDeletedMessagesFinal != null) {
for (int a = 0, size = scheduledDeletedMessagesFinal.size(); a < size; a++) {
@ -16200,10 +16384,22 @@ public class MessagesController extends BaseController implements NotificationCe
});
}
public void setChatReactions(long chatId, List<String> reactions) {
public void setChatReactions(long chatId, int type, List<String> reactions) {
TLRPC.TL_messages_setChatAvailableReactions req = new TLRPC.TL_messages_setChatAvailableReactions();
req.peer = getInputPeer(-chatId);
req.available_reactions.addAll(reactions);
if (type == ChatReactionsEditActivity.SELECT_TYPE_NONE) {
req.available_reactions = new TLRPC.TL_chatReactionsNone();
} else if (type == ChatReactionsEditActivity.SELECT_TYPE_ALL) {
req.available_reactions = new TLRPC.TL_chatReactionsAll();
} else {
TLRPC.TL_chatReactionsSome someReactions = new TLRPC.TL_chatReactionsSome();
req.available_reactions = someReactions;
for (int i = 0; i < reactions.size(); i++) {
TLRPC.TL_reactionEmoji emojiReaction = new TLRPC.TL_reactionEmoji();
emojiReaction.emoticon = reactions.get(i);
someReactions.reactions.add(emojiReaction);
}
}
getConnectionsManager().sendRequest(req, (response, error) -> {
if (response != null) {
processUpdates((TLRPC.Updates) response, false);
@ -16215,7 +16411,7 @@ public class MessagesController extends BaseController implements NotificationCe
if (full instanceof TLRPC.TL_channelFull) {
full.flags |= 1073741824;
}
full.available_reactions = new ArrayList<>(reactions);
full.available_reactions = req.available_reactions;
getMessagesStorage().updateChatInfo(full, false);
}
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.chatAvailableReactionsUpdated, chatId));
@ -16337,4 +16533,47 @@ public class MessagesController extends BaseController implements NotificationCe
public interface NewMessageCallback {
boolean onMessageReceived(TLRPC.Message message);
}
public void updateEmojiStatusUntilUpdate(long userId, TLRPC.EmojiStatus status) {
if (status instanceof TLRPC.TL_emojiStatusUntil) {
emojiStatusUntilValues.put(userId, ((TLRPC.TL_emojiStatusUntil) status).until);
} else {
if (!emojiStatusUntilValues.containsKey(userId))
return;
emojiStatusUntilValues.remove(userId);
}
updateEmojiStatusUntil();
}
public void updateEmojiStatusUntil() {
final int now = (int) (System.currentTimeMillis() / 1000L);
Long timeout = null;
for (int i = 0; i < emojiStatusUntilValues.size(); ++i) {
int until = emojiStatusUntilValues.valueAt(i);
if (until > now) {
timeout = Math.min(timeout == null ? Long.MAX_VALUE : timeout, until - now);
} else {
emojiStatusUntilValues.removeAt(i--);
}
}
if (timeout != null) {
timeout += 2;
if (now + timeout != recentEmojiStatusUpdateRunnableTime + recentEmojiStatusUpdateRunnableTimeout) {
AndroidUtilities.cancelRunOnUIThread(recentEmojiStatusUpdateRunnable);
recentEmojiStatusUpdateRunnableTime = now;
recentEmojiStatusUpdateRunnableTimeout = timeout;
AndroidUtilities.runOnUIThread(recentEmojiStatusUpdateRunnable = () -> {
getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_EMOJI_STATUS);
updateEmojiStatusUntil();
}, timeout * 1000);
}
} else if (recentEmojiStatusUpdateRunnable != null) {
recentEmojiStatusUpdateRunnableTime = -1;
recentEmojiStatusUpdateRunnableTimeout = -1;
AndroidUtilities.cancelRunOnUIThread(recentEmojiStatusUpdateRunnable);
}
}
}

View File

@ -48,6 +48,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
@ -89,7 +90,7 @@ public class MessagesStorage extends BaseController {
private static SparseArray<MessagesStorage> Instance = new SparseArray();
private static final Object lockObject = new Object();
private final static int LAST_DB_VERSION = 100;
private final static int LAST_DB_VERSION = 101;
private boolean databaseMigrationInProgress;
public boolean showClearDatabaseAlert;
@ -407,6 +408,7 @@ public class MessagesStorage extends BaseController {
database.executeFast("CREATE TABLE attach_menu_bots(data BLOB, hash INTEGER, date INTEGER);").stepThis().dispose();
database.executeFast("CREATE TABLE premium_promo(data BLOB, date INTEGER);").stepThis().dispose();
database.executeFast("CREATE TABLE emoji_statuses(data BLOB, type INTEGER);").stepThis().dispose();
//version
database.executeFast("PRAGMA user_version = " + LAST_DB_VERSION).stepThis().dispose();
} else {
@ -1617,6 +1619,12 @@ public class MessagesStorage extends BaseController {
version = 100;
}
if (version == 100) {
database.executeFast("CREATE TABLE emoji_statuses(data BLOB, type INTEGER);").stepThis().dispose();
database.executeFast("PRAGMA user_version = 101").stepThis().dispose();
version = 101;
}
FileLog.d("MessagesStorage db migration finished");
AndroidUtilities.runOnUIThread(() -> {
databaseMigrationInProgress = false;
@ -2145,6 +2153,7 @@ public class MessagesStorage extends BaseController {
database.executeFast("DELETE FROM downloading_documents").stepThis().dispose();
database.executeFast("DELETE FROM attach_menu_bots").stepThis().dispose();
database.executeFast("DELETE FROM animated_emoji").stepThis().dispose();
database.executeFast("DELETE FROM stickers_v2").stepThis().dispose();
cursor = database.queryFinalized("SELECT did FROM dialogs WHERE 1");
while (cursor.next()) {
@ -5779,27 +5788,42 @@ public class MessagesStorage extends BaseController {
for (int b = 0; b < inbox.size(); b++) {
long key = inbox.keyAt(b);
int messageId = inbox.get(key);
boolean canCountByMessageId = true;
int stillUnread = stillUnreadMessagesCount == null ? -2 : stillUnreadMessagesCount.get(key, -2);
if (stillUnreadMessagesCount != null && stillUnreadMessagesCount.get(key, -2) != -2) {
SQLiteCursor checkHolesCursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM messages_holes WHERE uid = %d AND end > %d", key, messageId));
while (checkHolesCursor.next()) {
canCountByMessageId = false;
if (stillUnread >= 0) {
dialogsToUpdate.put(key, stillUnread);
if (BuildVars.DEBUG_VERSION) {
FileLog.d(key + " update unread messages count by still unread " + stillUnread);
}
checkHolesCursor.dispose();
}
if (canCountByMessageId) {
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM messages_v2 WHERE uid = %d AND mid > %d AND read_state IN(0,2) AND out = 0", key, messageId));
if (cursor.next()) {
int unread = cursor.intValue(0);
dialogsToUpdate.put(key, unread);
}
cursor.dispose();
} else {
int unread = stillUnreadMessagesCount.get(key, -1);
if (unread >= 0) {
dialogsToUpdate.put(key, unread);
boolean canCountByMessageId = true;
if (stillUnreadMessagesCount != null && stillUnread != -2) {
SQLiteCursor checkHolesCursor = database.queryFinalized(String.format(Locale.US, "SELECT start, end FROM messages_holes WHERE uid = %d AND end > %d", key, messageId));
while (checkHolesCursor.next()) {
canCountByMessageId = false;
}
checkHolesCursor.dispose();
}
if (canCountByMessageId) {
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM messages_v2 WHERE uid = %d AND mid > %d AND read_state IN(0,2) AND out = 0", key, messageId));
if (cursor.next()) {
int unread = cursor.intValue(0);
dialogsToUpdate.put(key, unread);
if (BuildVars.DEBUG_VERSION) {
FileLog.d(key + " update unread messages count " + unread);
}
} else {
if (BuildVars.DEBUG_VERSION) {
FileLog.d(key + " can't update unread messages count cursor trouble");
}
}
cursor.dispose();
} else {
if (BuildVars.DEBUG_VERSION) {
FileLog.d(key + " can't update unread messages count");
}
}
}
@ -6707,6 +6731,40 @@ public class MessagesStorage extends BaseController {
return result[0];
}
public TLRPC.Message getMessage(long dialogId, long msgId) {
CountDownLatch countDownLatch = new CountDownLatch(1);
AtomicReference<TLRPC.Message> ref = new AtomicReference<>();
storageQueue.postRunnable(() -> {
SQLiteCursor cursor = null;
try {
cursor = database.queryFinalized("SELECT data FROM messages_v2 WHERE uid = " + dialogId + " AND mid = " + msgId + " LIMIT 1");
while (cursor.next()) {
NativeByteBuffer data = cursor.byteBufferValue(0);
if (data != null) {
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
data.reuse();
ref.set(message);
}
}
cursor.dispose();
cursor = null;
} catch (Exception e) {
FileLog.e(e);
} finally {
if (cursor != null) {
cursor.dispose();
}
countDownLatch.countDown();
}
});
try {
countDownLatch.await();
} catch (Exception e) {
FileLog.e(e);
}
return ref.get();
}
public boolean hasInviteMeMessage(long chatId) {
CountDownLatch countDownLatch = new CountDownLatch(1);
boolean[] result = new boolean[1];

View File

@ -9,6 +9,7 @@
package org.telegram.messenger;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import androidx.annotation.UiThread;
@ -19,6 +20,7 @@ import java.util.HashSet;
public class NotificationCenter {
private final static long EXPIRE_NOTIFICATIONS_TIME = 5017;
private static int totalEvents = 1;
public static final int didReceiveNewMessages = totalEvents++;
@ -115,6 +117,7 @@ public class NotificationCenter {
public static final int startSpoilers = totalEvents++;
public static final int sendingMessagesChanged = totalEvents++;
public static final int didUpdateReactions = totalEvents++;
public static final int didUpdateExtendedMedia = totalEvents++;
public static final int didVerifyMessagesStickers = totalEvents++;
public static final int scheduledMessagesUpdated = totalEvents++;
public static final int newSuggestionsAvailable = totalEvents++;
@ -127,6 +130,7 @@ public class NotificationCenter {
public static final int webViewResultSent = totalEvents++;
public static final int voiceTranscriptionUpdate = totalEvents++;
public static final int animatedEmojiDocumentLoaded = totalEvents++;
public static final int recentEmojiStatusesUpdate = totalEvents++;
public static final int didGenerateFingerprintKeyPair = totalEvents++;
@ -257,6 +261,9 @@ public class NotificationCenter {
public static final int currentUserShowLimitReachedDialog = totalEvents++;
public static final int billingProductDetailsUpdated = totalEvents++;
public static final int premiumStickersPreviewLoaded = totalEvents++;
public static final int userEmojiStatusUpdated = totalEvents++;
public static final int requestPermissions = totalEvents++;
public static final int permissionsGranted = totalEvents++;
// custom
@ -358,7 +365,7 @@ public class NotificationCenter {
notifications.allowedIds = allowedNotifications;
this.allowedNotifications.put(animationInProgressPointer, notifications);
if (checkForExpiredNotifications == null) {
AndroidUtilities.runOnUIThread(checkForExpiredNotifications = this::checkForExpiredNotifications, 1017);
AndroidUtilities.runOnUIThread(checkForExpiredNotifications = this::checkForExpiredNotifications, EXPIRE_NOTIFICATIONS_TIME);
}
return animationInProgressPointer;
@ -389,7 +396,7 @@ public class NotificationCenter {
}
}
if (minTime != Long.MAX_VALUE) {
long time = 1017 - (currentTime - minTime);
long time = EXPIRE_NOTIFICATIONS_TIME - (currentTime - minTime);
AndroidUtilities.runOnUIThread(() -> checkForExpiredNotifications = this::checkForExpiredNotifications, Math.max(17, time));
}
}
@ -465,7 +472,7 @@ public class NotificationCenter {
long currentTime = SystemClock.elapsedRealtime();
for (HashMap.Entry<Integer, AllowedNotifications> entry : allowedNotifications.entrySet()) {
AllowedNotifications allowedNotification = entry.getValue();
if (currentTime - allowedNotification.time > 1000) {
if (currentTime - allowedNotification.time > EXPIRE_NOTIFICATIONS_TIME) {
if (expiredIndices == null) {
expiredIndices = new ArrayList<>();
}

View File

@ -473,7 +473,7 @@ public class NotificationsController extends BaseController {
});
}
public void removeDeletedMessagesFromNotifications(LongSparseArray<ArrayList<Integer>> deletedMessages) {
public void removeDeletedMessagesFromNotifications(LongSparseArray<ArrayList<Integer>> deletedMessages, boolean isReactions) {
ArrayList<MessageObject> popupArrayRemove = new ArrayList<>(0);
notificationsQueue.postRunnable(() -> {
int old_unread_count = total_unread_count;
@ -489,6 +489,9 @@ public class NotificationsController extends BaseController {
int mid = mids.get(b);
MessageObject messageObject = sparseArray.get(mid);
if (messageObject != null) {
if (isReactions && !messageObject.isReactionPush) {
continue;
}
long dialogId = messageObject.getDialogId();
Integer currentCount = pushDialogs.get(dialogId);
if (currentCount == null) {

View File

@ -3,6 +3,7 @@ package org.telegram.messenger;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Base64;
import android.util.SparseBooleanArray;
import androidx.annotation.IntDef;
import androidx.collection.LongSparseArray;
@ -301,7 +302,7 @@ public class PushListenerController {
TLRPC.TL_updateReadChannelInbox update = new TLRPC.TL_updateReadChannelInbox();
update.channel_id = channel_id;
update.max_id = max_id;
update.still_unread_count = -1;
update.still_unread_count = 0;
updates.add(update);
} else {
TLRPC.TL_updateReadHistoryInbox update = new TLRPC.TL_updateReadHistoryInbox();
@ -325,12 +326,30 @@ public class PushListenerController {
ids.add(Utilities.parseInt(messagesArgs[a]));
}
deletedMessages.put(-channel_id, ids);
NotificationsController.getInstance(currentAccount).removeDeletedMessagesFromNotifications(deletedMessages);
NotificationsController.getInstance(currentAccount).removeDeletedMessagesFromNotifications(deletedMessages, false);
MessagesController.getInstance(currentAccount).deleteMessagesByPush(dialogId, ids, channel_id);
if (BuildVars.LOGS_ENABLED) {
FileLog.d(tag + " received " + loc_key + " for dialogId = " + dialogId + " mids = " + TextUtils.join(",", ids));
}
} else if ("READ_REACTION".equals(loc_key)) {
String messages = custom.getString("messages");
String[] messagesArgs = messages.split(",");
LongSparseArray<ArrayList<Integer>> deletedMessages = new LongSparseArray<>();
ArrayList<Integer> ids = new ArrayList<>();
SparseBooleanArray sparseBooleanArray = new SparseBooleanArray();
for (int a = 0; a < messagesArgs.length; a++) {
int messageId = Utilities.parseInt(messagesArgs[a]);
ids.add(messageId);
sparseBooleanArray.put(messageId, false);
}
deletedMessages.put(-channel_id, ids);
NotificationsController.getInstance(currentAccount).removeDeletedMessagesFromNotifications(deletedMessages, true);
MessagesController.getInstance(currentAccount).checkUnreadReactions(dialogId, sparseBooleanArray);
if (BuildVars.LOGS_ENABLED) {
FileLog.d(tag + " received " + loc_key + " for dialogId = " + dialogId + " mids = " + TextUtils.join(",", ids));
}
} else if (!TextUtils.isEmpty(loc_key)) {
int msg_id;
if (custom.has("msg_id")) {

View File

@ -30,6 +30,7 @@ import android.os.Bundle;
import android.os.SystemClock;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
import android.text.Spannable;
import android.text.TextUtils;
import android.util.Base64;
import android.util.SparseArray;
@ -60,17 +61,19 @@ import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ChatMessageCell;
import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.AnimatedEmojiSpan;
import org.telegram.ui.Components.AnimatedFileDrawable;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.Point;
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.Reactions.ReactionsUtils;
import org.telegram.ui.TwoStepVerificationActivity;
import org.telegram.ui.TwoStepVerificationSetupActivity;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
@ -104,6 +107,18 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
private HashMap<String, ImportingStickers> importingStickersFiles = new HashMap<>();
private HashMap<String, ImportingStickers> importingStickersMap = new HashMap<>();
public static boolean checkUpdateStickersOrder(CharSequence text) {
if (text instanceof Spannable) {
AnimatedEmojiSpan[] spans = ((Spannable)text).getSpans(0, text.length(), AnimatedEmojiSpan.class);
for (int i = 0; i < spans.length; i++) {
if (spans[i].fromEmojiKeyboard) {
return true;
}
}
}
return false;
}
public class ImportingHistory {
public String historyPath;
public ArrayList<Uri> mediaPaths = new ArrayList<>();
@ -498,6 +513,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
public boolean isVideo;
public boolean canDeleteAfter;
public boolean forceImage;
public boolean updateStickersOrder;
}
public static class LocationProvider {
@ -1434,9 +1450,9 @@ public boolean retriedToSend;
params.put("parentObject", "sent_" + messageObject.messageOwner.peer_id.channel_id + "_" + messageObject.getId());
}
if (messageObject.messageOwner.media.photo instanceof TLRPC.TL_photo) {
sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, did, messageObject.replyMessageObject, null, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, true, 0, messageObject.messageOwner.media.ttl_seconds, messageObject);
sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, did, messageObject.replyMessageObject, null, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, true, 0, messageObject.messageOwner.media.ttl_seconds, messageObject, false);
} else if (messageObject.messageOwner.media.document instanceof TLRPC.TL_document) {
sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject, null, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, true, 0, messageObject.messageOwner.media.ttl_seconds, messageObject, null);
sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject, null, messageObject.messageOwner.message, messageObject.messageOwner.entities, null, params, true, 0, messageObject.messageOwner.media.ttl_seconds, messageObject, null, false);
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo) {
sendMessage(messageObject.messageOwner.media, did, messageObject.replyMessageObject, null, null, null, true, 0);
} else if (messageObject.messageOwner.media.phone_number != null) {
@ -1474,7 +1490,7 @@ public boolean retriedToSend;
} else {
entities = null;
}
sendMessage(messageObject.messageOwner.message, did, messageObject.replyMessageObject, null, webPage, true, entities, null, null, true, 0, null);
sendMessage(messageObject.messageOwner.message, did, messageObject.replyMessageObject, null, webPage, true, entities, null, null, true, 0, null, false);
} else if (DialogObject.isEncryptedDialog(did)) {
ArrayList<MessageObject> arrayList = new ArrayList<>();
arrayList.add(messageObject);
@ -1531,7 +1547,7 @@ public boolean retriedToSend;
performSendMessageRequest(req, newMsgObj, null, null, null, null, false);
}
public void sendSticker(TLRPC.Document document, String query, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, Object parentObject, MessageObject.SendAnimationData sendAnimationData, boolean notify, int scheduleDate) {
public void sendSticker(TLRPC.Document document, String query, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, Object parentObject, MessageObject.SendAnimationData sendAnimationData, boolean notify, int scheduleDate, boolean updateStickersOrder) {
if (document == null) {
return;
}
@ -1621,7 +1637,7 @@ public boolean retriedToSend;
if (bitmapFinal[0] != null && keyFinal[0] != null) {
ImageLoader.getInstance().putImageToCache(new BitmapDrawable(bitmapFinal[0]), keyFinal[0], false);
}
sendMessage((TLRPC.TL_document) finalDocument, null, null, peer, replyToMsg, replyToTopMsg, null, null, null, null, notify, scheduleDate, 0, parentObject, sendAnimationData);
sendMessage((TLRPC.TL_document) finalDocument, null, null, peer, replyToMsg, replyToTopMsg, null, null, null, null, notify, scheduleDate, 0, parentObject, sendAnimationData, false);
});
});
} else {
@ -1632,7 +1648,7 @@ public boolean retriedToSend;
} else {
params = null;
}
sendMessage((TLRPC.TL_document) finalDocument, null, null, peer, replyToMsg, replyToTopMsg, null, null, null, params, notify, scheduleDate, 0, parentObject, sendAnimationData);
sendMessage((TLRPC.TL_document) finalDocument, null, null, peer, replyToMsg, replyToTopMsg, null, null, null, params, notify, scheduleDate, 0, parentObject, sendAnimationData, updateStickersOrder);
}
}
@ -1702,7 +1718,7 @@ public boolean retriedToSend;
if (msgObj.getId() <= 0 || msgObj.needDrawBluredPreview()) {
if (msgObj.type == 0 && !TextUtils.isEmpty(msgObj.messageText)) {
TLRPC.WebPage webPage = msgObj.messageOwner.media != null ? msgObj.messageOwner.media.webpage : null;
sendMessage(msgObj.messageText.toString(), peer, null, null, webPage, webPage != null, msgObj.messageOwner.entities, null, null, notify, scheduleDate, null);
sendMessage(msgObj.messageText.toString(), peer, null, null, webPage, webPage != null, msgObj.messageOwner.entities, null, null, notify, scheduleDate, null, false);
}
continue;
}
@ -2298,7 +2314,7 @@ public boolean retriedToSend;
newMsg.attachPath = "";
}
newMsg.local_id = 0;
if ((messageObject.type == 3 || videoEditedInfo != null || messageObject.type == 2) && !TextUtils.isEmpty(newMsg.attachPath)) {
if ((messageObject.type == 3 || videoEditedInfo != null || messageObject.type == MessageObject.TYPE_VOICE) && !TextUtils.isEmpty(newMsg.attachPath)) {
messageObject.attachPathExists = true;
}
if (messageObject.videoEditedInfo != null && videoEditedInfo == null) {
@ -2716,7 +2732,7 @@ public boolean retriedToSend;
return voteSendTime.get(pollId, 0L);
}
public void sendReaction(MessageObject messageObject, CharSequence reaction, boolean big, ChatActivity parentFragment, Runnable callback) {
public void sendReaction(MessageObject messageObject, ArrayList<ReactionsLayoutInBubble.VisibleReaction> visibleReactions, ReactionsLayoutInBubble.VisibleReaction addedReaction, boolean big, boolean addToRecent, ChatActivity parentFragment, Runnable callback) {
if (messageObject == null || parentFragment == null) {
return;
}
@ -2728,9 +2744,25 @@ public boolean retriedToSend;
req.peer = getMessagesController().getInputPeer(messageObject.getDialogId());
req.msg_id = messageObject.getId();
}
if (reaction != null) {
req.reaction = reaction.toString();
req.flags |= 1;
req.add_to_recent = addToRecent;
if (addToRecent && addedReaction != null) {
MediaDataController.getInstance(currentAccount).recentReactions.add(0, ReactionsUtils.toTLReaction(addedReaction));
}
if (visibleReactions != null && !visibleReactions.isEmpty()) {
for (int i = 0; i < visibleReactions.size(); i++ ) {
ReactionsLayoutInBubble.VisibleReaction visibleReaction = visibleReactions.get(i);
if (visibleReaction.documentId != 0) {
TLRPC.TL_reactionCustomEmoji reactionCustomEmoji = new TLRPC.TL_reactionCustomEmoji();
reactionCustomEmoji.document_id = visibleReaction.documentId;
req.reaction.add(reactionCustomEmoji);
req.flags |= 1;
} else if (visibleReaction.emojicon != null) {
TLRPC.TL_reactionEmoji defaultReaction = new TLRPC.TL_reactionEmoji();
defaultReaction.emoticon = visibleReaction.emojicon;
req.reaction.add(defaultReaction);
req.flags |= 1;
}
}
}
if (big) {
req.flags |= 2;
@ -2973,7 +3005,7 @@ public boolean retriedToSend;
TLRPC.TL_account_getPassword getPasswordReq = new TLRPC.TL_account_getPassword();
ConnectionsManager.getInstance(currentAccount).sendRequest(getPasswordReq, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> {
if (error2 == null) {
TLRPC.TL_account_password currentPassword = (TLRPC.TL_account_password) response2;
TLRPC.account_Password currentPassword = (TLRPC.account_Password) response2;
passwordFragment.setCurrentPasswordInfo(null, currentPassword);
TwoStepVerificationActivity.initPasswordNewAlgo(currentPassword);
sendCallback(cache, messageObject, button, passwordFragment.getNewSrpPassword(), passwordFragment, parentFragment);
@ -3109,42 +3141,42 @@ public boolean retriedToSend;
}
public void sendMessage(MessageObject retryMessageObject) {
sendMessage(null, null, null, null, null, null, null, null, null, null, retryMessageObject.getDialogId(), retryMessageObject.messageOwner.attachPath, null, null, null, true, retryMessageObject, null, retryMessageObject.messageOwner.reply_markup, retryMessageObject.messageOwner.params, !retryMessageObject.messageOwner.silent, retryMessageObject.scheduled ? retryMessageObject.messageOwner.date : 0, 0, null, null);
sendMessage(null, null, null, null, null, null, null, null, null, null, retryMessageObject.getDialogId(), retryMessageObject.messageOwner.attachPath, null, null, null, true, retryMessageObject, null, retryMessageObject.messageOwner.reply_markup, retryMessageObject.messageOwner.params, !retryMessageObject.messageOwner.silent, retryMessageObject.scheduled ? retryMessageObject.messageOwner.date : 0, 0, null, null, false);
}
public void sendMessage(TLRPC.User user, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate) {
sendMessage(null, null, null, null, null, user, null, null, null, null, peer, null, replyToMsg, replyToTopMsg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null);
sendMessage(null, null, null, null, null, user, null, null, null, null, peer, null, replyToMsg, replyToTopMsg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null, false);
}
public void sendMessage(TLRPC.TL_messageMediaInvoice invoice, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate) {
sendMessage(null, null, null, null, null, null, null, null, null, invoice, peer, null, replyToMsg, replyToTopMsg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null);
sendMessage(null, null, null, null, null, null, null, null, null, invoice, peer, null, replyToMsg, replyToTopMsg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null, false);
}
public void sendMessage(TLRPC.TL_document document, VideoEditedInfo videoEditedInfo, String path, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, String caption, ArrayList<TLRPC.MessageEntity> entities, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate, int ttl, Object parentObject, MessageObject.SendAnimationData sendAnimationData) {
sendMessage(null, caption, null, null, videoEditedInfo, null, document, null, null, null, peer, path, replyToMsg, replyToTopMsg, null, true, null, entities, replyMarkup, params, notify, scheduleDate, ttl, parentObject, sendAnimationData);
public void sendMessage(TLRPC.TL_document document, VideoEditedInfo videoEditedInfo, String path, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, String caption, ArrayList<TLRPC.MessageEntity> entities, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate, int ttl, Object parentObject, MessageObject.SendAnimationData sendAnimationData, boolean updateStickersOrder) {
sendMessage(null, caption, null, null, videoEditedInfo, null, document, null, null, null, peer, path, replyToMsg, replyToTopMsg, null, true, null, entities, replyMarkup, params, notify, scheduleDate, ttl, parentObject, sendAnimationData, updateStickersOrder);
}
public void sendMessage(String message, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.WebPage webPage, boolean searchLinks, ArrayList<TLRPC.MessageEntity> entities, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate, MessageObject.SendAnimationData sendAnimationData) {
sendMessage(message, null, null, null, null, null, null, null, null, null, peer, null, replyToMsg, replyToTopMsg, webPage, searchLinks, null, entities, replyMarkup, params, notify, scheduleDate, 0, null, sendAnimationData);
public void sendMessage(String message, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.WebPage webPage, boolean searchLinks, ArrayList<TLRPC.MessageEntity> entities, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate, MessageObject.SendAnimationData sendAnimationData, boolean updateStickersOrder) {
sendMessage(message, null, null, null, null, null, null, null, null, null, peer, null, replyToMsg, replyToTopMsg, webPage, searchLinks, null, entities, replyMarkup, params, notify, scheduleDate, 0, null, sendAnimationData, updateStickersOrder);
}
public void sendMessage(TLRPC.MessageMedia location, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate) {
sendMessage(null, null, location, null, null, null, null, null, null, null, peer, null, replyToMsg, replyToTopMsg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null);
sendMessage(null, null, location, null, null, null, null, null, null, null, peer, null, replyToMsg, replyToTopMsg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null, false);
}
public void sendMessage(TLRPC.TL_messageMediaPoll poll, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate) {
sendMessage(null, null, null, null, null, null, null, null, poll, null, peer, null, replyToMsg, replyToTopMsg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null);
sendMessage(null, null, null, null, null, null, null, null, poll, null, peer, null, replyToMsg, replyToTopMsg, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null, false);
}
public void sendMessage(TLRPC.TL_game game, long peer, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate) {
sendMessage(null, null, null, null, null, null, null, game, null, null, peer, null, null, null, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null);
sendMessage(null, null, null, null, null, null, null, game, null, null, peer, null, null, null, null, true, null, null, replyMarkup, params, notify, scheduleDate, 0, null, null, false);
}
public void sendMessage(TLRPC.TL_photo photo, String path, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, String caption, ArrayList<TLRPC.MessageEntity> entities, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate, int ttl, Object parentObject) {
sendMessage(null, caption, null, photo, null, null, null, null, null, null, peer, path, replyToMsg, replyToTopMsg, null, true, null, entities, replyMarkup, params, notify, scheduleDate, ttl, parentObject, null);
public void sendMessage(TLRPC.TL_photo photo, String path, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, String caption, ArrayList<TLRPC.MessageEntity> entities, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate, int ttl, Object parentObject, boolean updateStickersOrder) {
sendMessage(null, caption, null, photo, null, null, null, null, null, null, peer, path, replyToMsg, replyToTopMsg, null, true, null, entities, replyMarkup, params, notify, scheduleDate, ttl, parentObject, null, updateStickersOrder);
}
private void sendMessage(String message, String caption, TLRPC.MessageMedia location, TLRPC.TL_photo photo, VideoEditedInfo videoEditedInfo, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_game game, TLRPC.TL_messageMediaPoll poll, TLRPC.TL_messageMediaInvoice invoice, long peer, String path, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.WebPage webPage, boolean searchLinks, MessageObject retryMessageObject, ArrayList<TLRPC.MessageEntity> entities, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate, int ttl, Object parentObject, MessageObject.SendAnimationData sendAnimationData) {
private void sendMessage(String message, String caption, TLRPC.MessageMedia location, TLRPC.TL_photo photo, VideoEditedInfo videoEditedInfo, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_game game, TLRPC.TL_messageMediaPoll poll, TLRPC.TL_messageMediaInvoice invoice, long peer, String path, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.WebPage webPage, boolean searchLinks, MessageObject retryMessageObject, ArrayList<TLRPC.MessageEntity> entities, TLRPC.ReplyMarkup replyMarkup, HashMap<String, String> params, boolean notify, int scheduleDate, int ttl, Object parentObject, MessageObject.SendAnimationData sendAnimationData, boolean updateStickersOreder) {
if (user != null && user.phone == null) {
return;
}
@ -3246,7 +3278,7 @@ public boolean retriedToSend;
if (retryMessageObject.messageOwner.message != null) {
caption = retryMessageObject.messageOwner.message;
}
} else if (retryMessageObject.type == 2) {
} else if (retryMessageObject.type == MessageObject.TYPE_VOICE) {
document = (TLRPC.TL_document) newMsg.media.document;
type = 8;
if (retryMessageObject.messageOwner.message != null) {
@ -3569,6 +3601,10 @@ public boolean retriedToSend;
if (replyMarkup != null && encryptedChat == null) {
newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_MARKUP;
newMsg.reply_markup = replyMarkup;
String bot = params.get("bot");
if (bot != null) {
newMsg.via_bot_id = Long.parseLong(bot);
}
}
if (!DialogObject.isEncryptedDialog(peer)) {
newMsg.peer_id = getMessagesController().getPeer(peer);
@ -3647,7 +3683,7 @@ public boolean retriedToSend;
newMsgObj.sendAnimationData = sendAnimationData;
newMsgObj.wasJustSent = true;
newMsgObj.scheduled = scheduleDate != 0;
if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == 2) && !TextUtils.isEmpty(newMsg.attachPath)) {
if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == MessageObject.TYPE_VOICE) && !TextUtils.isEmpty(newMsg.attachPath)) {
newMsgObj.attachPathExists = true;
}
if (newMsgObj.videoEditedInfo != null && videoEditedInfo == null) {
@ -3701,6 +3737,9 @@ public boolean retriedToSend;
reqSend.silent = newMsg.silent;
reqSend.peer = sendToPeer;
reqSend.random_id = newMsg.random_id;
if (updateStickersOreder) {
reqSend.update_stickersets_order = true;
}
if (newMsg.from_id != null) {
reqSend.send_as = getMessagesController().getInputPeer(newMsg.from_id);
}
@ -4076,11 +4115,27 @@ public boolean retriedToSend;
request.schedule_date = scheduleDate;
request.flags |= 1024;
}
if (updateStickersOreder) {
request.update_stickersets_order = true;
}
if (delayedMessage != null) {
delayedMessage.sendRequest = request;
}
reqSend = request;
if (updateStickersOreder) {
// if (MessageObject.getStickerSetId(document) != -1) {
// TLRPC.TL_updateMoveStickerSetToTop update = new TLRPC.TL_updateMoveStickerSetToTop();
// update.masks = false;
// update.emojis = false;
// update.stickerset = MessageObject.getStickerSetId(document);
//
// ArrayList<TLRPC.Update> updates = new ArrayList<>();
// updates.add(update);
// getMessagesController().processUpdateArray(updates, null, null, false, 0);
// }
}
}
if (groupId != 0) {
performSendDelayedMessage(delayedMessage);
@ -4526,7 +4581,7 @@ public boolean retriedToSend;
}
if (!file.exists()) {
putToDelayedMessages(FileLoader.getAttachFileName(message.photoSize), message);
getFileLoader().loadFile(ImageLocation.getForObject(message.photoSize, message.locationParent), message.parentObject, "jpg", 2, 0);
getFileLoader().loadFile(ImageLocation.getForObject(message.photoSize, message.locationParent), message.parentObject, "jpg", FileLoader.PRIORITY_HIGH, 0);
return;
}
}
@ -4602,7 +4657,7 @@ public boolean retriedToSend;
File file = new File(location);
if (!file.exists()) {
putToDelayedMessages(FileLoader.getAttachFileName(document), message);
getFileLoader().loadFile(document, message.parentObject, 2, 0);
getFileLoader().loadFile(document, message.parentObject, FileLoader.PRIORITY_HIGH, 0);
return;
}
}
@ -4645,7 +4700,7 @@ public boolean retriedToSend;
File file = new File(location);
if (!file.exists()) {
putToDelayedMessages(FileLoader.getAttachFileName(document), message);
getFileLoader().loadFile(document, message.parentObject, 2, 0);
getFileLoader().loadFile(document, message.parentObject, FileLoader.PRIORITY_HIGH, 0);
return;
}
}
@ -6329,7 +6384,7 @@ public boolean retriedToSend;
if (editingMessageObject != null) {
accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, null, null, documentFinal, pathFinal, params, false, parentFinal);
} else {
accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, 0, parentFinal, null);
accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, 0, parentFinal, null, false);
}
});
return 0;
@ -6442,7 +6497,7 @@ public boolean retriedToSend;
if (editingMessageObject != null) {
accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, null, null, documentFinal, messageObject.messageOwner.attachPath, params, false, parentFinal);
} else {
accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, messageObject.messageOwner.attachPath, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, 0, parentFinal, null);
accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, messageObject.messageOwner.attachPath, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, 0, parentFinal, null, false);
}
});
}
@ -6591,7 +6646,7 @@ public boolean retriedToSend;
info.videoEditedInfo = videoEditedInfo;
ArrayList<SendingMediaInfo> infos = new ArrayList<>();
infos.add(info);
prepareSendingMedia(accountInstance, infos, dialogId, replyToMsg, replyToTopMsg, inputContent, forceDocument, false, editingMessageObject, notify, scheduleDate);
prepareSendingMedia(accountInstance, infos, dialogId, replyToMsg, replyToTopMsg, inputContent, forceDocument, false, editingMessageObject, notify, scheduleDate, false);
}
@UiThread
@ -6867,9 +6922,9 @@ public boolean retriedToSend;
if (precahcedThumb[0] != null && precachedKey[0] != null) {
ImageLoader.getInstance().putImageToCache(new BitmapDrawable(precahcedThumb[0]), precachedKey[0], false);
}
accountInstance.getSendMessagesHelper().sendMessage(finalDocument, null, finalPathFinal, dialogId, replyToMsg, replyToTopMsg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, 0, result, null);
accountInstance.getSendMessagesHelper().sendMessage(finalDocument, null, finalPathFinal, dialogId, replyToMsg, replyToTopMsg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, 0, result, null, false);
} else if (finalPhoto != null) {
accountInstance.getSendMessagesHelper().sendMessage(finalPhoto, result.content != null ? result.content.url : null, dialogId, replyToMsg, replyToTopMsg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, 0, result);
accountInstance.getSendMessagesHelper().sendMessage(finalPhoto, result.content != null ? result.content.url : null, dialogId, replyToMsg, replyToTopMsg, result.send_message.message, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, 0, result, false);
} else if (finalGame != null) {
accountInstance.getSendMessagesHelper().sendMessage(finalGame, dialogId, result.send_message.reply_markup, params, notify, scheduleDate);
}
@ -6887,7 +6942,7 @@ public boolean retriedToSend;
}
}
}
accountInstance.getSendMessagesHelper().sendMessage(result.send_message.message, dialogId, replyToMsg, replyToTopMsg, webPage, !result.send_message.no_webpage, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, null);
accountInstance.getSendMessagesHelper().sendMessage(result.send_message.message, dialogId, replyToMsg, replyToTopMsg, webPage, !result.send_message.no_webpage, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, null, false);
} else if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaVenue) {
TLRPC.TL_messageMediaVenue venue = new TLRPC.TL_messageMediaVenue();
venue.geo = result.send_message.geo;
@ -6968,7 +7023,7 @@ public boolean retriedToSend;
int count = (int) Math.ceil(textFinal.length() / 4096.0f);
for (int a = 0; a < count; a++) {
String mess = textFinal.substring(a * 4096, Math.min((a + 1) * 4096, textFinal.length()));
accountInstance.getSendMessagesHelper().sendMessage(mess, dialogId, null, null, null, true, null, null, null, notify, scheduleDate, null);
accountInstance.getSendMessagesHelper().sendMessage(mess, dialogId, null, null, null, true, null, null, null, notify, scheduleDate, null, false);
}
}
})));
@ -7101,7 +7156,7 @@ public boolean retriedToSend;
}
@UiThread
public static void prepareSendingMedia(AccountInstance accountInstance, ArrayList<SendingMediaInfo> media, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, InputContentInfoCompat inputContent, boolean forceDocument, boolean groupMedia, MessageObject editingMessageObject, boolean notify, int scheduleDate) {
public static void prepareSendingMedia(AccountInstance accountInstance, ArrayList<SendingMediaInfo> media, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, InputContentInfoCompat inputContent, boolean forceDocument, boolean groupMedia, MessageObject editingMessageObject, boolean notify, int scheduleDate, boolean updateStikcersOrder) {
if (media.isEmpty()) {
return;
}
@ -7305,7 +7360,7 @@ public boolean retriedToSend;
if (editingMessageObject != null) {
accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, null, null, documentFinal, pathFinal, params, false, parentFinal);
} else {
accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, 0, parentFinal, null);
accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, 0, parentFinal, null, false);
}
});
} else {
@ -7376,7 +7431,7 @@ public boolean retriedToSend;
if (editingMessageObject != null) {
accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, photoFinal, null, null, needDownloadHttpFinal ? info.searchImage.imageUrl : null, params, false, parentFinal);
} else {
accountInstance.getSendMessagesHelper().sendMessage(photoFinal, needDownloadHttpFinal ? info.searchImage.imageUrl : null, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal);
accountInstance.getSendMessagesHelper().sendMessage(photoFinal, needDownloadHttpFinal ? info.searchImage.imageUrl : null, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal, false);
}
});
}
@ -7439,13 +7494,19 @@ public boolean retriedToSend;
}
TLRPC.PhotoSize size = null;
String localPath = null;
if (thumb != null) {
int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight());
size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted);
thumbKey = getKeyForPhotoSize(accountInstance, size, null, true, false);
String fileName = size.location.volume_id + "_" + size.location.local_id + ".jpg";
File fileDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE);
localPath = new File(fileDir, fileName).getAbsolutePath();
}
document = new TLRPC.TL_document();
document.file_reference = new byte[0];
document.localPath = localPath;
if (size != null) {
document.thumbs.add(size);
document.flags |= 1;
@ -7548,7 +7609,7 @@ public boolean retriedToSend;
if (editingMessageObject != null) {
accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, null, videoEditedInfo, videoFinal, finalPath, params, false, parentFinal);
} else {
accountInstance.getSendMessagesHelper().sendMessage(videoFinal, videoEditedInfo, finalPath, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal, null);
accountInstance.getSendMessagesHelper().sendMessage(videoFinal, videoEditedInfo, finalPath, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal, null, false);
}
});
} else {
@ -7745,7 +7806,7 @@ public boolean retriedToSend;
if (editingMessageObject != null) {
accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, photoFinal, null, null, null, params, false, parentFinal);
} else {
accountInstance.getSendMessagesHelper().sendMessage(photoFinal, null, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal);
accountInstance.getSendMessagesHelper().sendMessage(photoFinal, null, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal, updateStikcersOrder);
}
});
} else {
@ -8190,7 +8251,7 @@ public boolean retriedToSend;
if (editingMessageObject != null) {
accountInstance.getSendMessagesHelper().editMessage(editingMessageObject, null, videoEditedInfo, videoFinal, finalPath, params, false, parentFinal);
} else {
accountInstance.getSendMessagesHelper().sendMessage(videoFinal, videoEditedInfo, finalPath, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, ttl, parentFinal, null);
accountInstance.getSendMessagesHelper().sendMessage(videoFinal, videoEditedInfo, finalPath, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, ttl, parentFinal, null, false);
}
});
} else {

View File

@ -78,7 +78,6 @@ public class SharedConfig {
public final static int PASSCODE_TYPE_PIN = 0,
PASSCODE_TYPE_PASSWORD = 1;
@Retention(RetentionPolicy.SOURCE)
@IntDef({
PASSCODE_TYPE_PIN,
@ -132,6 +131,7 @@ public class SharedConfig {
public static boolean searchMessagesAsListUsed;
public static boolean stickersReorderingHintUsed;
public static boolean disableVoiceAudioEffects;
public static boolean forceDisableTabletMode;
private static int lastLocalId = -210000;
public static String storageCacheDir;
@ -150,6 +150,7 @@ public class SharedConfig {
public static boolean autoplayGifs = true;
public static boolean autoplayVideo = true;
public static boolean raiseToSpeak = false;
public static boolean recordViaSco = false;
public static boolean customTabs = true;
public static boolean directShare = true;
public static boolean inappCamera = true;
@ -175,6 +176,7 @@ public class SharedConfig {
public static int repeatMode;
public static boolean allowBigEmoji;
public static int fontSize = 12;
public static boolean fontSizeIsDefault;
public static int bubbleRadius = 3;
public static int ivFontSize = 12;
public static int messageSeenHintCount;
@ -184,6 +186,9 @@ public class SharedConfig {
public static TLRPC.TL_help_appUpdate pendingAppUpdate;
public static int pendingAppUpdateBuildVersion;
public static long lastUpdateCheckTime;
public static boolean hasEmailLogin;
private static int devicePerformanceClass;
public static boolean drawDialogIcons;
@ -1097,6 +1102,7 @@ public class SharedConfig {
editor.putBoolean("forwardingOptionsHintShown", forwardingOptionsHintShown);
editor.putInt("lockRecordAudioVideoHint", lockRecordAudioVideoHint);
editor.putString("storageCacheDir", !TextUtils.isEmpty(storageCacheDir) ? storageCacheDir : "");
editor.putBoolean("hasEmailLogin", hasEmailLogin);
if (pendingAppUpdate != null) {
try {
@ -1229,6 +1235,7 @@ public class SharedConfig {
autoplayVideo = preferences.getBoolean("autoplay_video", true);
mapPreviewType = preferences.getInt("mapPreviewType", 2);
raiseToSpeak = preferences.getBoolean("raise_to_speak", false);
recordViaSco = preferences.getBoolean("record_via_sco", false);
customTabs = preferences.getBoolean("custom_tabs", true);
directShare = preferences.getBoolean("direct_share", true);
shuffleMusic = preferences.getBoolean("shuffleMusic", false);
@ -1238,6 +1245,7 @@ public class SharedConfig {
roundCamera16to9 = true;//preferences.getBoolean("roundCamera16to9", false);
repeatMode = preferences.getInt("repeatMode", 0);
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 14 : 12);
fontSizeIsDefault = !preferences.contains("fons_size");
bubbleRadius = preferences.getInt("bubbleRadius", 3);
ivFontSize = preferences.getInt("iv_font_size", fontSize);
allowBigEmoji = preferences.getBoolean("allowBigEmoji", true);
@ -1245,8 +1253,8 @@ public class SharedConfig {
saveStreamMedia = preferences.getBoolean("saveStreamMedia", true);
smoothKeyboard = preferences.getBoolean("smoothKeyboard2", true);
pauseMusicOnRecord = preferences.getBoolean("pauseMusicOnRecord", false);
chatBlur = preferences.getBoolean("chatBlur", true);
chatBlur = chatBlur || NekoConfig.forceBlurInChat.Bool();
forceDisableTabletMode = preferences.getBoolean("forceDisableTabletMode", false);
streamAllVideo = preferences.getBoolean("streamAllVideo", BuildVars.DEBUG_VERSION);
streamMkv = preferences.getBoolean("streamMkv", false);
suggestStickers = preferences.getInt("suggestStickers", 0);
@ -1314,6 +1322,7 @@ public class SharedConfig {
mediaColumnsCount = preferences.getInt("mediaColumnsCount", 3);
fastScrollHintCount = preferences.getInt("fastScrollHintCount", 3);
dontAskManageStorage = preferences.getBoolean("dontAskManageStorage", false);
hasEmailLogin = preferences.getBoolean("hasEmailLogin", false);
preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true);
@ -1331,6 +1340,14 @@ public class SharedConfig {
}
public static void updateTabletConfig() {
if (fontSizeIsDefault) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("userconfing", Context.MODE_PRIVATE);
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
ivFontSize = preferences.getInt("iv_font_size", fontSize);
}
}
public static void increaseBadPasscodeTries() {
badPasscodeTries++;
if (badPasscodeTries >= 3) {
@ -1905,6 +1922,14 @@ public class SharedConfig {
editor.commit();
}
public static void toggleForceDisableTabletMode() {
forceDisableTabletMode = !forceDisableTabletMode;
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean("forceDisableTabletMode", forceDisableTabletMode);
editor.commit();
}
public static void toggleInappCamera() {
inappCamera = !inappCamera;
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
@ -2357,7 +2382,7 @@ public class SharedConfig {
devicePerformanceClass = PERFORMANCE_CLASS_HIGH;
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("device performance info selected_class = " + devicePerformanceClass + " (cpu_count = " + cpuCount + ", freq = " + maxCpuFreq + ", memoryClass = " + memoryClass + ", android version " + androidVersion + ")");
FileLog.d("device performance info selected_class = " + devicePerformanceClass + " (cpu_count = " + cpuCount + ", freq = " + maxCpuFreq + ", memoryClass = " + memoryClass + ", android version " + androidVersion + ", manufacture " + Build.MANUFACTURER + ")");
}
}
@ -2403,7 +2428,16 @@ public class SharedConfig {
}
}
private static Boolean animationsEnabled;
public static void setAnimationsEnabled(boolean b) {
animationsEnabled = b;
}
public static boolean animationsEnabled() {
return MessagesController.getGlobalMainSettings().getBoolean("view_animations", true);
if (animationsEnabled == null) {
animationsEnabled = MessagesController.getGlobalMainSettings().getBoolean("view_animations", true);
}
return animationsEnabled;
}
}

View File

@ -72,7 +72,9 @@ public class UserConfig extends BaseController {
public TLRPC.InputStorePaymentPurpose billingPaymentPurpose;
public String premiumGiftsStickerPack;
public String genericAnimationsStickerPack;
public long lastUpdatedPremiumGiftsStickerPack;
public long lastUpdatedGenericAnimations;
public volatile byte[] savedPasswordHash;
public volatile byte[] savedSaltedPassword;
@ -174,6 +176,9 @@ public class UserConfig extends BaseController {
editor.putString("premiumGiftsStickerPack", premiumGiftsStickerPack);
editor.putLong("lastUpdatedPremiumGiftsStickerPack", lastUpdatedPremiumGiftsStickerPack);
editor.putString("genericAnimationsStickerPack", genericAnimationsStickerPack);
editor.putLong("lastUpdatedGenericAnimations", lastUpdatedGenericAnimations);
editor.putInt("6migrateOffsetId", migrateOffsetId);
if (migrateOffsetId != -1) {
editor.putInt("6migrateOffsetDate", migrateOffsetDate);
@ -261,11 +266,11 @@ public class UserConfig extends BaseController {
TLRPC.User oldUser = currentUser;
currentUser = user;
clientUserId = user.id;
checkPremium(oldUser, user);
checkPremiumSelf(oldUser, user);
}
}
private void checkPremium(TLRPC.User oldUser, TLRPC.User newUser) {
private void checkPremiumSelf(TLRPC.User oldUser, TLRPC.User newUser) {
if (oldUser == null || (newUser != null && oldUser.premium != newUser.premium)) {
AndroidUtilities.runOnUIThread(() -> {
getMessagesController().updatePremium(newUser.premium);
@ -273,6 +278,7 @@ public class UserConfig extends BaseController {
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.premiumStatusChangedGlobal);
getMediaDataController().loadPremiumPromo(false);
getMediaDataController().loadReactions(false, true);
});
}
}
@ -326,6 +332,10 @@ public class UserConfig extends BaseController {
premiumGiftsStickerPack = preferences.getString("premiumGiftsStickerPack", null);
lastUpdatedPremiumGiftsStickerPack = preferences.getLong("lastUpdatedPremiumGiftsStickerPack", 0);
genericAnimationsStickerPack = preferences.getString("genericAnimationsStickerPack", null);
lastUpdatedGenericAnimations = preferences.getLong("lastUpdatedGenericAnimations", 0);
try {
String terms = preferences.getString("terms", null);
if (terms != null) {
@ -369,7 +379,7 @@ public class UserConfig extends BaseController {
}
}
if (currentUser != null) {
checkPremium(null, currentUser);
checkPremiumSelf(null, currentUser);
clientUserId = currentUser.id;
}
configLoaded = true;
@ -512,4 +522,17 @@ public class UserConfig extends BaseController {
}
return currentUser.premium;
}
public Long getEmojiStatus() {
if (currentUser == null) {
return null;
}
if (currentUser.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
return ((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).document_id;
}
if (currentUser.emoji_status instanceof TLRPC.TL_emojiStatus) {
return ((TLRPC.TL_emojiStatus) currentUser.emoji_status).document_id;
}
return null;
}
}

View File

@ -37,6 +37,7 @@ public class Utilities {
public static volatile DispatchQueue searchQueue = new DispatchQueue("searchQueue");
public static volatile DispatchQueue phoneBookQueue = new DispatchQueue("phoneBookQueue");
public static volatile DispatchQueue themeQueue = new DispatchQueue("themeQueue");
public static volatile DispatchQueue externalNetworkQueue = new DispatchQueue("externalNetworkQueue");
private final static String RANDOM_STRING_CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

View File

@ -14,10 +14,10 @@ import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import org.telegram.tgnet.TLRPC;
import androidx.core.app.RemoteInput;
import org.telegram.tgnet.TLRPC;
public class WearReplyReceiver extends BroadcastReceiver {
@Override
@ -67,7 +67,7 @@ public class WearReplyReceiver extends BroadcastReceiver {
}
private void sendMessage(AccountInstance accountInstance, CharSequence text, long dialog_id, int max_id) {
accountInstance.getSendMessagesHelper().sendMessage(text.toString(), dialog_id, null, null, null, true, null, null, null, true, 0, null);
accountInstance.getSendMessagesHelper().sendMessage(text.toString(), dialog_id, null, null, null, true, null, null, null, true, 0, null, false);
accountInstance.getMessagesController().markDialogAsRead(dialog_id, max_id, max_id, 0, false, 0, 0, true, 0);
}
}

View File

@ -50,6 +50,7 @@ import org.telegram.ui.LaunchActivity;
import java.lang.ref.WeakReference;
import java.net.URLEncoder;
import java.util.List;
import java.util.regex.Matcher;
public class Browser {
@ -395,6 +396,15 @@ public class Browser {
public static boolean isInternalUri(Uri uri, boolean all, boolean[] forceBrowser) {
String host = uri.getHost();
host = host != null ? host.toLowerCase() : "";
Matcher prefixMatcher = LaunchActivity.PREFIX_T_ME_PATTERN.matcher(host);
if (prefixMatcher.find()) {
uri = Uri.parse("https://t.me/" + prefixMatcher.group(1) + (TextUtils.isEmpty(uri.getPath()) ? "" : "/" + uri.getPath()) + (TextUtils.isEmpty(uri.getQuery()) ? "" : "?" + uri.getQuery()));
host = uri.getHost();
host = host != null ? host.toLowerCase() : "";
}
if ("ton".equals(uri.getScheme())) {
try {
Intent viewIntent = new Intent(Intent.ACTION_VIEW, uri);

View File

@ -258,7 +258,7 @@ public class RingtoneDataStore {
File file = FileLoader.getInstance(currentAccount).getPathToAttach(document);
if (file == null || !file.exists()) {
AndroidUtilities.runOnUIThread(() -> {
FileLoader.getInstance(currentAccount).loadFile(document, document, 0, 0);
FileLoader.getInstance(currentAccount).loadFile(document, document, FileLoader.PRIORITY_LOW, 0);
});
}
}

View File

@ -23,6 +23,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
public class BitmapsCache {
@ -47,7 +48,9 @@ public class BitmapsCache {
final File file;
public BitmapsCache(File sourceFile, Cacheable source, CacheOptions options, int w, int h) {
public AtomicBoolean cancelled = new AtomicBoolean(false);
public BitmapsCache(File sourceFile, Cacheable source, CacheOptions options, int w, int h, boolean noLimit) {
this.source = source;
this.w = w;
this.h = h;
@ -58,7 +61,7 @@ public class BitmapsCache {
}
File fileTmo = new File(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), "acache");
file = new File(fileTmo, fileName + "_" + w + "_" + h + ".pcache2");
file = new File(fileTmo, fileName + "_" + w + "_" + h + (noLimit ? "_nolimit" : " ") + ".pcache2");
}
volatile boolean checkCache;
@ -66,6 +69,7 @@ public class BitmapsCache {
volatile boolean recycled;
RandomAccessFile cachedFile;
BitmapFactory.Options options;
public void createCache() {
try {
@ -107,6 +111,7 @@ public class BitmapsCache {
long writeFileTime = 0;
int framePosition = 0;
AtomicBoolean closed = new AtomicBoolean(false);
source.prepareForGenerateCache();
while (true) {
if (countDownLatch[index] != null) {
@ -117,6 +122,32 @@ public class BitmapsCache {
}
}
if (cancelled.get() || closed.get()) {
if (BuildVars.DEBUG_VERSION) {
FileLog.d("cancelled cache generation");
}
closed.set(true);
for (int i = 0; i < N; i++) {
if (countDownLatch[i] != null) {
try {
countDownLatch[i].await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (bitmap[i] != null) {
try {
bitmap[i].recycle();
} catch (Exception e) {
}
}
}
randomAccessFile.close();
source.releaseForGenerateCache();
return;
}
long time2 = System.currentTimeMillis();
if (source.getNextFrame(bitmap[index]) != 1) {
break;
@ -129,6 +160,10 @@ public class BitmapsCache {
int finalFramePosition = framePosition;
RandomAccessFile finalRandomAccessFile1 = randomAccessFile;
bitmapCompressExecutor.execute(() -> {
if (cancelled.get() || closed.get()) {
return;
}
Bitmap.CompressFormat format = Bitmap.CompressFormat.WEBP;
if (Build.VERSION.SDK_INT <= 26) {
format = Bitmap.CompressFormat.PNG;
@ -149,6 +184,11 @@ public class BitmapsCache {
}
} catch (IOException e) {
e.printStackTrace();
try {
finalRandomAccessFile1.close();
} catch (Exception e2) {} finally {
closed.set(true);
}
}
countDownLatch[finalIndex].countDown();
@ -191,6 +231,7 @@ public class BitmapsCache {
randomAccessFile.seek(0);
randomAccessFile.writeBoolean(true);
randomAccessFile.writeInt(arrayOffset);
closed.set(true);
randomAccessFile.close();
if (BuildVars.DEBUG_VERSION) {
@ -205,6 +246,10 @@ public class BitmapsCache {
}
}
public void cancelCreate() {
// cancelled.set(true);
}
public int getFrame(Bitmap bitmap, Metadata metadata) {
int res = getFrame(frameIndex, bitmap);
metadata.frame = frameIndex;
@ -282,7 +327,7 @@ public class BitmapsCache {
selectedFrame = frameOffsets.get(index);
randomAccessFile.seek(selectedFrame.frameOffset);
if (bufferTmp == null || bufferTmp.length < selectedFrame.frameSize) {
bufferTmp = new byte[selectedFrame.frameSize];
bufferTmp = new byte[(int) (selectedFrame.frameSize * 1.3f)];
}
randomAccessFile.readFully(bufferTmp, 0, selectedFrame.frameSize);
if (!recycled) {
@ -292,13 +337,15 @@ public class BitmapsCache {
randomAccessFile.close();
}
}
BitmapFactory.Options options = new BitmapFactory.Options();
if (options == null) {
options = new BitmapFactory.Options();
}
options.inBitmap = bitmap;
BitmapFactory.decodeByteArray(bufferTmp, 0, selectedFrame.frameSize, options);
return FRAME_RESULT_OK;
} catch (FileNotFoundException e) {
} catch (Exception e) {
} catch (Throwable e) {
FileLog.e(e);
}

View File

@ -3,6 +3,7 @@ package org.telegram.messenger.video;
import com.google.android.exoplayer2.C;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.Components.PhotoViewerWebView;
import org.telegram.ui.Components.VideoForwardDrawable;
import org.telegram.ui.Components.VideoPlayer;
@ -19,14 +20,15 @@ public class VideoPlayerRewinder {
private float playSpeed = 1f;
private VideoPlayer videoPlayer;
private PhotoViewerWebView webView;
private final Runnable backSeek = new Runnable() {
@Override
public void run() {
if (videoPlayer == null) {
if (videoPlayer == null && webView == null) {
return;
}
long duration = videoPlayer.getDuration();
long duration = getDuration();
if (duration == 0 || duration == C.TIME_UNSET) {
rewindLastTime = System.currentTimeMillis();
return;
@ -52,21 +54,19 @@ public class VideoPlayerRewinder {
} else if (rewindBackSeekPlayerPosition > duration) {
rewindBackSeekPlayerPosition = duration;
}
if (rewindByBackSeek && videoPlayer != null && rewindLastTime - rewindLastUpdatePlayerTime > 350) {
if (rewindByBackSeek && rewindLastTime - rewindLastUpdatePlayerTime > 350) {
rewindLastUpdatePlayerTime = rewindLastTime;
videoPlayer.seekTo(rewindBackSeekPlayerPosition);
seekTo(rewindBackSeekPlayerPosition);
}
if (videoPlayer != null) {
long timeDiff = rewindBackSeekPlayerPosition - startRewindFrom;
float progress = rewindBackSeekPlayerPosition / (float) videoPlayer.getDuration();
updateRewindProgressUi(timeDiff, progress, rewindByBackSeek);
}
long timeDiff = rewindBackSeekPlayerPosition - startRewindFrom;
float progress = rewindBackSeekPlayerPosition / (float) getDuration();
updateRewindProgressUi(timeDiff, progress, rewindByBackSeek);
if (rewindBackSeekPlayerPosition == 0 || rewindBackSeekPlayerPosition >= duration) {
if (rewindByBackSeek && videoPlayer != null) {
if (rewindByBackSeek) {
rewindLastUpdatePlayerTime = rewindLastTime;
videoPlayer.seekTo(rewindBackSeekPlayerPosition);
seekTo(rewindBackSeekPlayerPosition);
}
cancelRewind();
}
@ -76,6 +76,14 @@ public class VideoPlayerRewinder {
}
};
public void startRewind(PhotoViewerWebView webView, boolean forward, float playbackSpeed) {
this.webView = webView;
this.playSpeed = playbackSpeed;
rewindForward = forward;
cancelRewind();
incrementRewindCount();
}
public void startRewind(VideoPlayer videoPlayer, boolean forward, float playbackSpeed) {
this.videoPlayer = videoPlayer;
this.playSpeed = playbackSpeed;
@ -88,14 +96,14 @@ public class VideoPlayerRewinder {
if (rewindCount != 0) {
rewindCount = 0;
if (videoPlayer != null) {
if (videoPlayer != null || webView != null) {
if (rewindByBackSeek) {
videoPlayer.seekTo(rewindBackSeekPlayerPosition);
seekTo(rewindBackSeekPlayerPosition);
} else {
long current = videoPlayer.getCurrentPosition();
videoPlayer.seekTo(current);
long current = getCurrentPosition();
seekTo(current);
}
videoPlayer.setPlaybackSpeed(playSpeed);
setPlaybackSpeed(playSpeed);
}
}
AndroidUtilities.cancelRunOnUIThread(backSeek);
@ -109,13 +117,13 @@ public class VideoPlayerRewinder {
}
private void incrementRewindCount() {
if (videoPlayer == null) {
if (videoPlayer == null && webView == null) {
return;
}
rewindCount++;
boolean needUpdate = false;
if (rewindCount == 1) {
if (rewindForward && videoPlayer.isPlaying()) {
if (rewindForward && isPlaying()) {
rewindByBackSeek = false;
} else {
rewindByBackSeek = true;
@ -123,13 +131,13 @@ public class VideoPlayerRewinder {
}
if (rewindForward && !rewindByBackSeek) {
if (rewindCount == 1) {
videoPlayer.setPlaybackSpeed(4);
setPlaybackSpeed(4);
needUpdate = true;
} else if (rewindCount == 2) {
videoPlayer.setPlaybackSpeed(7);
setPlaybackSpeed(7);
needUpdate = true;
} else {
videoPlayer.setPlaybackSpeed(13);
setPlaybackSpeed(13);
}
} else {
if (rewindCount == 1 || rewindCount == 2) {
@ -139,10 +147,10 @@ public class VideoPlayerRewinder {
if (rewindCount == 1) {
rewindBackSeekPlayerPosition = videoPlayer.getCurrentPosition();
rewindBackSeekPlayerPosition = getCurrentPosition();
rewindLastTime = System.currentTimeMillis();
rewindLastUpdatePlayerTime = rewindLastTime;
startRewindFrom = videoPlayer.getCurrentPosition();
startRewindFrom = getCurrentPosition();
onRewindStart(rewindForward);
}
@ -173,7 +181,62 @@ public class VideoPlayerRewinder {
}
private void seekTo(long position) {
if (webView != null) {
webView.seekTo(position);
} else {
if (videoPlayer == null) {
return;
}
videoPlayer.seekTo(position);
}
}
private void setPlaybackSpeed(float speed) {
if (webView != null) {
webView.setPlaybackSpeed(speed);
} else {
if (videoPlayer == null) {
return;
}
videoPlayer.setPlaybackSpeed(speed);
}
}
private long getCurrentPosition() {
if (webView != null) {
return webView.getCurrentPosition();
} else {
if (videoPlayer == null) {
return 0;
}
return videoPlayer.getCurrentPosition();
}
}
private long getDuration() {
if (webView != null) {
return webView.getVideoDuration();
} else {
if (videoPlayer == null) {
return 0;
}
return videoPlayer.getDuration();
}
}
private boolean isPlaying() {
if (webView != null) {
return webView.isPlaying();
} else {
if (videoPlayer == null) {
return false;
}
return videoPlayer.isPlaying();
}
}
public float getVideoProgress() {
return rewindBackSeekPlayerPosition / (float) videoPlayer.getDuration();
return rewindBackSeekPlayerPosition / (float) getDuration();
}
}

View File

@ -78,6 +78,7 @@ import android.widget.RemoteViews;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import org.json.JSONObject;
import org.telegram.messenger.AccountInstance;
@ -361,15 +362,21 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
for (BluetoothDevice device : proxy.getConnectedDevices()) {
if (proxy.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
continue;
try {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
for (BluetoothDevice device : proxy.getConnectedDevices()) {
if (proxy.getConnectionState(device) != BluetoothProfile.STATE_CONNECTED) {
continue;
}
currentBluetoothDeviceName = device.getName();
break;
}
}
currentBluetoothDeviceName = device.getName();
break;
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy);
fetchingBluetoothDeviceName = false;
} catch (Throwable e) {
FileLog.e(e);
}
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(profile, proxy);
fetchingBluetoothDeviceName = false;
}
};

View File

@ -40,6 +40,7 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
@ -318,7 +319,12 @@ SharedPreferences mainPreferences;
if (response != 0) {
NativeByteBuffer buff = NativeByteBuffer.wrap(response);
buff.reused = true;
resp = object.deserializeResponse(buff, buff.readInt32(true), true);
// try {
resp = object.deserializeResponse(buff, buff.readInt32(true), true);
// } catch (Exception e2) {
// FileLog.fatal(e2);
// return;
// }
} else if (errorText != null) {
error = new TLRPC.TL_error();
error.code = errorCode;
@ -327,6 +333,14 @@ SharedPreferences mainPreferences;
FileLog.e(object + " got error " + error.code + " " + error.text);
}
}
if (BuildVars.DEBUG_PRIVATE_VERSION && !getUserConfig().isClientActivated() && error != null && error.code == 400 && Objects.equals(error.text, "CONNECTION_NOT_INITED")) {
if (BuildVars.LOGS_ENABLED) {
FileLog.d("Cleanup keys for " + currentAccount + " because of CONNECTION_NOT_INITED");
}
cleanup(true);
sendRequest(object, onComplete, onCompleteTimestamp, onQuickAck, onWriteToSocket, flags, datacenterId, connetionType, immediate);
return;
}
if (resp != null) {
resp.networkType = networkType;
}

View File

@ -198,6 +198,13 @@ public class NativeByteBuffer extends AbstractSerializedData {
}
public void writeString(String s) {
if (s == null) {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("write string null");
FileLog.e(new Throwable());
}
s = "";
}
try {
writeByteArray(s.getBytes("UTF-8"));
} catch (Exception e) {

View File

@ -21,7 +21,6 @@ public class TLClassStore {
classStore.put(TLRPC.TL_error.constructor, TLRPC.TL_error.class);
classStore.put(TLRPC.TL_decryptedMessageService.constructor, TLRPC.TL_decryptedMessageService.class);
classStore.put(TLRPC.TL_decryptedMessage.constructor, TLRPC.TL_decryptedMessage.class);
classStore.put(TLRPC.TL_config.constructor, TLRPC.TL_config.class);
classStore.put(TLRPC.TL_decryptedMessageLayer.constructor, TLRPC.TL_decryptedMessageLayer.class);
classStore.put(TLRPC.TL_decryptedMessage_layer17.constructor, TLRPC.TL_decryptedMessage.class);
classStore.put(TLRPC.TL_decryptedMessage_layer45.constructor, TLRPC.TL_decryptedMessage_layer45.class);

File diff suppressed because it is too large Load Diff

View File

@ -50,6 +50,7 @@ import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.ui.Adapters.FiltersView;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.EllipsizeSpanAnimator;
import org.telegram.ui.Components.FireworksEffect;
@ -110,6 +111,8 @@ public class ActionBar extends FrameLayout {
private boolean allowOverlayTitle;
private CharSequence lastTitle;
private Drawable lastRightDrawable;
private OnClickListener rightDrawableOnClickListener;
private CharSequence lastOverlayTitle;
private Object[] overlayTitleToSet = new Object[3];
private Runnable lastRunnable;
@ -382,13 +385,16 @@ public class ActionBar extends FrameLayout {
return;
}
titleTextView[i] = new SimpleTextView(getContext());
titleTextView[i].setGravity(Gravity.LEFT);
titleTextView[i].setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
if (titleColorToSet != 0) {
titleTextView[i].setTextColor(titleColorToSet);
} else {
titleTextView[i].setTextColor(getThemedColor(Theme.key_actionBarDefaultTitle));
}
titleTextView[i].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
titleTextView[i].setDrawablePadding(AndroidUtilities.dp(4));
titleTextView[i].setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8));
titleTextView[i].setRightDrawableTopPadding(-AndroidUtilities.dp(1));
addView(titleTextView[i], 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP));
}
@ -397,17 +403,35 @@ public class ActionBar extends FrameLayout {
}
public void setTitle(CharSequence value) {
setTitle(value, null);
}
public void setTitle(CharSequence value, Drawable rightDrawable) {
if (value != null && titleTextView[0] == null) {
createTitleTextView(0);
}
if (titleTextView[0] != null) {
lastTitle = value;
titleTextView[0].setVisibility(value != null && !isSearchFieldVisible ? VISIBLE : INVISIBLE);
titleTextView[0].setText(value);
titleTextView[0].setText(lastTitle = value);
titleTextView[0].setRightDrawable(lastRightDrawable = rightDrawable);
titleTextView[0].setRightDrawableOnClick(rightDrawableOnClickListener);
if (rightDrawable instanceof AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) {
((AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) rightDrawable).setParentView(titleTextView[0]);
}
}
fromBottom = false;
}
public void setRightDrawableOnClick(OnClickListener onClickListener) {
rightDrawableOnClickListener = onClickListener;
if (titleTextView[0] != null) {
titleTextView[0].setRightDrawableOnClick(rightDrawableOnClickListener);
}
if (titleTextView[1] != null) {
titleTextView[1].setRightDrawableOnClick(rightDrawableOnClickListener);
}
}
public void setTitleColor(int color) {
if (titleTextView[0] == null) {
createTitleTextView(0);
@ -462,6 +486,10 @@ public class ActionBar extends FrameLayout {
return titleTextView[0];
}
public SimpleTextView getTitleTextView2() {
return titleTextView[1];
}
public String getTitle() {
if (titleTextView[0] == null) {
return null;
@ -1113,7 +1141,7 @@ public class ActionBar extends FrameLayout {
}
if (titleTextView[i] != null && titleTextView[i].getVisibility() != GONE) {
titleTextView[i].measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.AT_MOST));
titleTextView[i].measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24) + titleTextView[i].getPaddingTop() + titleTextView[i].getPaddingBottom(), MeasureSpec.AT_MOST));
if (centerScale) {
CharSequence text = titleTextView[i].getText();
titleTextView[i].setPivotX(titleTextView[i].getTextPaint().measureText(text, 0, text.length()) / 2f);
@ -1175,7 +1203,7 @@ public class ActionBar extends FrameLayout {
textTop = (getCurrentActionBarHeight() - titleTextView[i].getTextHeight()) / 2;
}
}
titleTextView[i].layout(textLeft, additionalTop + textTop, textLeft + titleTextView[i].getMeasuredWidth(), additionalTop + textTop + titleTextView[i].getTextHeight());
titleTextView[i].layout(textLeft, additionalTop + textTop - titleTextView[i].getPaddingTop(), textLeft + titleTextView[i].getMeasuredWidth(), additionalTop + textTop + titleTextView[i].getTextHeight() - titleTextView[i].getPaddingTop() + titleTextView[i].getPaddingBottom());
}
}
if (subtitleTextView != null && subtitleTextView.getVisibility() != GONE) {
@ -1277,6 +1305,7 @@ public class ActionBar extends FrameLayout {
lastOverlayTitle = title;
CharSequence textToSet = title != null ? LocaleController.getString(title, titleId) : lastTitle;
Drawable rightDrawableToSet = title != null ? null : lastRightDrawable;
boolean ellipsize = false;
if (title != null) {
int index = TextUtils.indexOf(textToSet, "...");
@ -1295,6 +1324,12 @@ public class ActionBar extends FrameLayout {
invalidate();
}
titleTextView[0].setText(textToSet);
titleTextView[0].setDrawablePadding(AndroidUtilities.dp(4));
titleTextView[0].setRightDrawable(rightDrawableToSet);
titleTextView[0].setRightDrawableOnClick(rightDrawableOnClickListener);
if (rightDrawableToSet instanceof AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) {
((AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) rightDrawableToSet).setParentView(titleTextView[0]);
}
if (ellipsize) {
ellipsizeSpanAnimator.addView(titleTextView[0]);
} else {
@ -1309,6 +1344,12 @@ public class ActionBar extends FrameLayout {
createTitleTextView(1);
}
titleTextView[1].setText(textToSet);
titleTextView[1].setDrawablePadding(AndroidUtilities.dp(4));
titleTextView[1].setRightDrawable(rightDrawableToSet);
titleTextView[1].setRightDrawableOnClick(rightDrawableOnClickListener);
if (rightDrawableToSet instanceof AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) {
((AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) rightDrawableToSet).setParentView(titleTextView[1]);
}
if (ellipsize) {
ellipsizeSpanAnimator.addView(titleTextView[1]);
}

View File

@ -738,11 +738,7 @@ public class ActionBarMenuItem extends FrameLayout {
//}
processedPopupClick = false;
popupWindow.setFocusable(true);
if (container.getMeasuredWidth() == 0) {
updateOrShowPopup(true, true);
} else {
updateOrShowPopup(true, false);
}
updateOrShowPopup(true, container.getMeasuredWidth() == 0);
popupLayout.updateRadialSelectors();
if (popupLayout.getSwipeBack() != null) {
popupLayout.getSwipeBack().closeForeground(false);
@ -1966,7 +1962,11 @@ public class ActionBarMenuItem extends FrameLayout {
}
public static ActionBarMenuSubItem addItem(ActionBarPopupWindow.ActionBarPopupWindowLayout windowLayout, int icon, CharSequence text, boolean needCheck, Theme.ResourcesProvider resourcesProvider) {
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(windowLayout.getContext(), needCheck, false, false, resourcesProvider);
return addItem(false, false, windowLayout, icon, text, needCheck, resourcesProvider);
}
public static ActionBarMenuSubItem addItem(boolean first, boolean last, ActionBarPopupWindow.ActionBarPopupWindowLayout windowLayout, int icon, CharSequence text, boolean needCheck, Theme.ResourcesProvider resourcesProvider) {
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(windowLayout.getContext(), needCheck, first, last, resourcesProvider);
cell.setTextAndIcon(text, icon);
cell.setMinimumWidth(AndroidUtilities.dp(196));
windowLayout.addView(cell);

View File

@ -709,6 +709,22 @@ public class ActionBarPopupWindow extends PopupWindow {
wm.updateViewLayout(container, p);
}
public void setFocusableFlag(boolean enable) {
View container = getContentView().getRootView();
Context context = getContentView().getContext();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams p = (WindowManager.LayoutParams) container.getLayoutParams();
if (p != null) {
if (enable) {
p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else {
p.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
wm.updateViewLayout(container, p);
}
}
private void dismissDim() {
View container = getContentView().getRootView();
Context context = getContentView().getContext();
@ -739,6 +755,74 @@ public class ActionBarPopupWindow extends PopupWindow {
}
}
public static AnimatorSet startAnimation(ActionBarPopupWindowLayout content) {
content.startAnimationPending = true;
content.setTranslationY(0);
content.setAlpha(1.0f);
content.setPivotX(content.getMeasuredWidth());
content.setPivotY(0);
final int count = content.getItemsCount();
content.positions.clear();
int visibleCount = 0;
for (int a = 0; a < count; a++) {
View child = content.getItemAt(a);
child.setAlpha(0.0f);
if (child.getVisibility() != View.VISIBLE) {
continue;
}
content.positions.put(child, visibleCount);
visibleCount++;
}
if (content.shownFromBottom) {
content.lastStartedChild = count - 1;
} else {
content.lastStartedChild = 0;
}
float finalScaleY = 1f;
if (content.getSwipeBack() != null) {
content.getSwipeBack().invalidateTransforms();
finalScaleY = content.backScaleY;
}
AnimatorSet windowAnimatorSet = new AnimatorSet();
ValueAnimator childtranslations = ValueAnimator.ofFloat(0, 1);
childtranslations.addUpdateListener(anm -> {
final int count2 = content.getItemsCount();
final float t = (float) anm.getAnimatedValue();
for (int a = 0; a < count2; a++) {
View child = content.getItemAt(a);
if (child instanceof GapView) {
continue;
}
float at = AndroidUtilities.cascade(t, a, count2, 2);
child.setTranslationY((1f - at) * AndroidUtilities.dp(-12));
child.setAlpha(at);
}
});
content.updateAnimation = true;
windowAnimatorSet.playTogether(
ObjectAnimator.ofFloat(content, "backScaleY", 0.0f, finalScaleY),
ObjectAnimator.ofInt(content, "backAlpha", 0, 255),
childtranslations
);
windowAnimatorSet.setDuration(150 + 16 * visibleCount + 1000);
windowAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
content.startAnimationPending = false;
int count = content.getItemsCount();
for (int a = 0; a < count; a++) {
View child = content.getItemAt(a);
if (child instanceof GapView) {
continue;
}
child.setAlpha(child.isEnabled() ? 1f : 0.5f);
}
}
});
windowAnimatorSet.start();
return windowAnimatorSet;
}
public void startAnimation() {
if (animationEnabled) {
if (windowAnimatorSet != null) {

View File

@ -140,6 +140,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
private float aspectRatio;
private boolean dimEnabled = true;
private float dimAlpha = 0.6f;
private boolean dimCustom = false;
private final Theme.ResourcesProvider resourcesProvider;
private boolean topAnimationAutoRepeat = true;
@ -483,7 +484,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
titleContainer = new FrameLayout(getContext());
containerView.addView(titleContainer, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 24, 0, 24, 0));
titleTextView = new TextView(getContext());
titleTextView = new SpoilersTextView(getContext(), false);
titleTextView.setText(title);
titleTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
@ -542,7 +543,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
contentScrollView.addView(scrollContainer, new ScrollView.LayoutParams(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
messageTextView = new SpoilersTextView(getContext());
messageTextView = new SpoilersTextView(getContext(), false);
messageTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack));
messageTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
messageTextView.setMovementMethod(new AndroidUtilities.LinkMovementMethodMy());
@ -871,7 +872,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
if (progressViewStyle == 3) {
params.width = WindowManager.LayoutParams.MATCH_PARENT;
} else {
if (dimEnabled) {
if (dimEnabled && !dimCustom) {
params.dimAmount = dimAlpha;
params.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
} else {
@ -902,6 +903,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
if (Build.VERSION.SDK_INT >= 28) {
params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
}
window.setAttributes(params);
}
@ -1309,6 +1311,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback {
alertDialog.topBackgroundColor = backgroundColor;
return this;
}
public Builder setTopAnimation(int resId, int backgroundColor) {
return setTopAnimation(resId, 94, true, backgroundColor);
}

View File

@ -180,6 +180,7 @@ public class BottomSheet extends Dialog {
private float hideSystemVerticalInsetsProgress;
public boolean useBackgroundTopPadding = true;
protected int customViewGravity = Gravity.LEFT | Gravity.TOP;
protected class ContainerView extends LinearLayout implements NestedScrollingParent {
@ -1105,9 +1106,9 @@ public class BottomSheet extends Dialog {
containerView.setClipChildren(false);
container.setClipToPadding(false);
container.setClipChildren(false);
containerView.addView(customView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, -backgroundPaddingTop + topOffset, 0, 0));
containerView.addView(customView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, customViewGravity, 0, -backgroundPaddingTop + topOffset, 0, 0));
} else {
containerView.addView(customView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, topOffset, 0, 0));
containerView.addView(customView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, customViewGravity, 0, topOffset, 0, 0));
}
} else {
if (items != null) {

View File

@ -318,6 +318,10 @@ public class DrawerLayoutContainer extends FrameLayout {
closeDrawer(false);
}
public void openStatusSelect() {
}
public void closeDrawer() {
if (drawerPosition != 0) {
setDrawerPosition(0);

View File

@ -29,11 +29,14 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.text.method.MovementMethod;
import android.util.Log;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.core.math.MathUtils;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.UserObject;
@ -82,6 +85,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
private int currentScrollDelay;
private Paint fadePaint;
private Paint fadePaintBack;
private Paint fadeEllpsizePaint;
private int lastWidth;
private int offsetX;
@ -93,6 +97,10 @@ public class SimpleTextView extends View implements Drawable.Callback {
public int rightDrawableY;
private boolean wasLayout;
private boolean rightDrawableOutside;
private boolean ellipsizeByGradient;
private int paddingRight;
private int minWidth;
private static final int PIXELS_PER_SECOND = 50;
@ -180,18 +188,33 @@ public class SimpleTextView extends View implements Drawable.Callback {
return;
}
scrollNonFitText = value;
if (scrollNonFitText) {
updateFadePaints();
requestLayout();
}
public void setEllipsizeByGradient(boolean value) {
if (scrollNonFitText == value) {
return;
}
ellipsizeByGradient = value;
updateFadePaints();
}
private void updateFadePaints() {
if ((fadePaint == null || fadePaintBack == null) && scrollNonFitText) {
fadePaint = new Paint();
LinearGradient gradient = new LinearGradient(0, 0, AndroidUtilities.dp(6), 0, new int[]{0xffffffff, 0}, new float[]{0f, 1f}, Shader.TileMode.CLAMP);
fadePaint.setShader(gradient);
fadePaint.setShader(new LinearGradient(0, 0, AndroidUtilities.dp(6), 0, new int[]{0xffffffff, 0}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
fadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
fadePaintBack = new Paint();
gradient = new LinearGradient(0, 0, AndroidUtilities.dp(6), 0, new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP);
fadePaintBack.setShader(gradient);
fadePaintBack.setShader(new LinearGradient(0, 0, AndroidUtilities.dp(6), 0, new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
fadePaintBack.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
requestLayout();
if (fadeEllpsizePaint == null && ellipsizeByGradient) {
fadeEllpsizePaint = new Paint();
fadeEllpsizePaint.setShader(new LinearGradient(0, 0, AndroidUtilities.dp(16), 0, new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
fadeEllpsizePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
}
public void setMaxLines(int value) {
@ -277,7 +300,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
width -= drawablePadding;
}
int rightDrawableWidth = 0;
if (rightDrawable != null) {
if (rightDrawable != null && !rightDrawableOutside) {
rightDrawableWidth = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale);
width -= rightDrawableWidth;
width -= drawablePadding;
@ -293,7 +316,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
width -= drawablePadding;
}
}
if (canHideRightDrawable && rightDrawableWidth != 0) {
if (canHideRightDrawable && rightDrawableWidth != 0 && !rightDrawableOutside) {
CharSequence string = TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END);
if (!text.equals(string)) {
rightDrawableHidden = true;
@ -302,8 +325,11 @@ public class SimpleTextView extends View implements Drawable.Callback {
}
}
if (buildFullLayout) {
CharSequence string = TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END);
if (!string.equals(text)) {
CharSequence string = text;
if (!ellipsizeByGradient) {
string = TextUtils.ellipsize(string, textPaint, width, TextUtils.TruncateAt.END);
}
if (!ellipsizeByGradient && !string.equals(text)) {
fullLayout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, fullTextMaxLines, false);
if (fullLayout != null) {
int end = fullLayout.getLineEnd(0);
@ -326,7 +352,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
fullLayout = StaticLayoutEx.createStaticLayout(full, 0, full.length(), textPaint, width + AndroidUtilities.dp(8) + fullLayoutAdditionalWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width + fullLayoutAdditionalWidth, fullTextMaxLines, false);
}
} else {
layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText || ellipsizeByGradient ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
fullLayout = null;
partLayout = null;
firstLineLayout = null;
@ -335,7 +361,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
layout = StaticLayoutEx.createStaticLayout(text, 0, text.length(), textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, width, maxLines, false);
} else {
CharSequence string;
if (scrollNonFitText) {
if (scrollNonFitText || ellipsizeByGradient) {
string = text;
} else {
string = TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END);
@ -344,7 +370,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
calcOffset(width);
return false;
}*/
layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
layout = new StaticLayout(string, 0, string.length(), textPaint, scrollNonFitText || ellipsizeByGradient ? AndroidUtilities.dp(2000) : width + AndroidUtilities.dp(8), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
}
spoilersPool.addAll(spoilers);
@ -378,18 +404,18 @@ public class SimpleTextView extends View implements Drawable.Callback {
scrollingOffset = 0;
currentScrollDelay = SCROLL_DELAY_MS;
}
createLayout(width - getPaddingLeft() - getPaddingRight() - minusWidth);
createLayout(width - getPaddingLeft() - getPaddingRight() - minusWidth - (rightDrawableOutside && rightDrawable != null ? rightDrawable.getIntrinsicWidth() + drawablePadding : 0));
int finalHeight;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
finalHeight = height;
} else {
finalHeight = textHeight;
finalHeight = getPaddingTop() + textHeight + getPaddingBottom();
}
setMeasuredDimension(width, finalHeight);
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
offsetY = (getMeasuredHeight() - textHeight) / 2 + getPaddingTop();
offsetY = getPaddingTop() + (getMeasuredHeight() - getPaddingTop() - getPaddingBottom() - textHeight) / 2;
} else {
offsetY = getPaddingTop();
}
@ -530,7 +556,9 @@ public class SimpleTextView extends View implements Drawable.Callback {
return false;
}
text = value;
scrollingOffset = 0;
if (!(text == null && value == null || text != null && text.equals(value))) {
scrollingOffset = 0;
}
currentScrollDelay = SCROLL_DELAY_MS;
recreateLayoutMaybe();
return true;
@ -548,9 +576,9 @@ public class SimpleTextView extends View implements Drawable.Callback {
private boolean recreateLayoutMaybe() {
if (wasLayout && getMeasuredHeight() != 0 && !buildFullLayout) {
boolean result = createLayout(getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - minusWidth);
boolean result = createLayout(getMaxTextWidth() - getPaddingLeft() - getPaddingRight() - minusWidth);
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
offsetY = (getMeasuredHeight() - textHeight) / 2 + getPaddingTop();
offsetY = (getMeasuredHeight() - textHeight) / 2;
} else {
offsetY = getPaddingTop();
}
@ -608,6 +636,10 @@ public class SimpleTextView extends View implements Drawable.Callback {
return (int) getY();
}
public void setRightPadding(int padding) {
paddingRight = padding;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@ -615,7 +647,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
boolean fade = scrollNonFitText && (textDoesNotFit || scrollingOffset != 0);
int restore = Integer.MIN_VALUE;
if (fade) {
if (fade || ellipsizeByGradient) {
restore = canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), 255, Canvas.ALL_SAVE_FLAG);
}
@ -629,7 +661,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
y = (getMeasuredHeight() - leftDrawable.getIntrinsicHeight()) / 2 + leftDrawableTopPadding;
} else {
y = (textHeight - leftDrawable.getIntrinsicHeight()) / 2 + leftDrawableTopPadding;
y = getPaddingTop() + (textHeight - leftDrawable.getIntrinsicHeight()) / 2 + leftDrawableTopPadding;
}
leftDrawable.setBounds(x, y, x + leftDrawable.getIntrinsicWidth(), y + leftDrawable.getIntrinsicHeight());
leftDrawable.draw(canvas);
@ -658,16 +690,21 @@ public class SimpleTextView extends View implements Drawable.Callback {
totalWidth += drawablePadding + replacedDrawable.getIntrinsicWidth();
}
}
if (rightDrawable != null && !rightDrawableHidden && rightDrawableScale > 0) {
if (rightDrawable != null && !rightDrawableHidden && rightDrawableScale > 0 && !rightDrawableOutside) {
int x = textOffsetX + textWidth + drawablePadding + (int) -scrollingOffset;
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.CENTER_HORIZONTAL) {
x += offsetX;
} else if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.RIGHT) {
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.CENTER_HORIZONTAL ||
(gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.RIGHT) {
x += offsetX;
}
int dw = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale);
int dh = (int) (rightDrawable.getIntrinsicHeight() * rightDrawableScale);
int y = (textHeight - dh) / 2 + rightDrawableTopPadding;
int y;
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
y = (getMeasuredHeight() - dh) / 2 + rightDrawableTopPadding;
} else {
y = getPaddingTop() + (textHeight - dh) / 2 + rightDrawableTopPadding;
}
rightDrawable.setBounds(x, y, x + dw, y + dh);
rightDrawableX = x + (dw >> 1);
rightDrawableY = y + (dh >> 1);
@ -679,19 +716,35 @@ public class SimpleTextView extends View implements Drawable.Callback {
if (scrollingOffset != 0) {
if (leftDrawable != null) {
int x = (int) -scrollingOffset + nextScrollX;
int y = (textHeight - leftDrawable.getIntrinsicHeight()) / 2 + leftDrawableTopPadding;
int y;
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
y = (getMeasuredHeight() - leftDrawable.getIntrinsicHeight()) / 2 + leftDrawableTopPadding;
} else {
y = getPaddingTop() + (textHeight - leftDrawable.getIntrinsicHeight()) / 2 + leftDrawableTopPadding;
}
leftDrawable.setBounds(x, y, x + leftDrawable.getIntrinsicWidth(), y + leftDrawable.getIntrinsicHeight());
leftDrawable.draw(canvas);
}
if (rightDrawable != null) {
if (rightDrawable != null && !rightDrawableOutside) {
int dw = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale);
int dh = (int) (rightDrawable.getIntrinsicHeight() * rightDrawableScale);
int x = textOffsetX + textWidth + drawablePadding + (int) -scrollingOffset + nextScrollX;
int y = (textHeight - rightDrawable.getIntrinsicHeight()) / 2 + rightDrawableTopPadding;
rightDrawable.setBounds(x, y, x + rightDrawable.getIntrinsicWidth(), y + rightDrawable.getIntrinsicHeight());
int y;
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
y = (getMeasuredHeight() - dh) / 2 + rightDrawableTopPadding;
} else {
y = getPaddingTop() + (textHeight - dh) / 2 + rightDrawableTopPadding;
}
rightDrawable.setBounds(x, y, x + dw, y + dh);
rightDrawable.draw(canvas);
}
}
if (layout != null) {
if (rightDrawableOutside || ellipsizeByGradient) {
canvas.save();
canvas.clipRect(0, 0, getMaxTextWidth() - paddingRight - AndroidUtilities.dp(rightDrawable != null && !(rightDrawable instanceof AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) && rightDrawableOutside ? 2 : 0), getMeasuredHeight());
}
Emoji.emojiDrawingUseAlpha = usaAlphaForEmoji;
if (wrapBackgroundDrawable != null) {
int cx = (int) (offsetX + textOffsetX - scrollingOffset) + textWidth / 2;
@ -752,16 +805,52 @@ public class SimpleTextView extends View implements Drawable.Callback {
}
canvas.drawRect(0, 0, AndroidUtilities.dp(6), getMeasuredHeight(), fadePaint);
canvas.save();
canvas.translate(getMeasuredWidth() - AndroidUtilities.dp(6), 0);
canvas.translate(getMaxTextWidth() - paddingRight - AndroidUtilities.dp(6), 0);
canvas.drawRect(0, 0, AndroidUtilities.dp(6), getMeasuredHeight(), fadePaintBack);
canvas.restore();
} else if (ellipsizeByGradient && fadeEllpsizePaint != null) {
canvas.save();
canvas.translate(getMaxTextWidth() - paddingRight - AndroidUtilities.dp(rightDrawable != null && !(rightDrawable instanceof AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable) && rightDrawableOutside ? 18 : 16), 0);
canvas.drawRect(0, 0, AndroidUtilities.dp(16), getMeasuredHeight(), fadeEllpsizePaint);
canvas.restore();
}
updateScrollAnimation();
Emoji.emojiDrawingUseAlpha = true;
if (rightDrawableOutside) {
canvas.restore();
}
}
if (fade) {
if (fade || ellipsizeByGradient) {
canvas.restoreToCount(restore);
}
if (rightDrawable != null && rightDrawableOutside) {
int x = Math.min(textOffsetX + textWidth + drawablePadding + (scrollingOffset == 0 ? -nextScrollX : (int) -scrollingOffset) + nextScrollX, getMaxTextWidth() - paddingRight + drawablePadding - AndroidUtilities.dp(4));
int dw = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale);
int dh = (int) (rightDrawable.getIntrinsicHeight() * rightDrawableScale);
int y;
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
y = (getMeasuredHeight() - dh) / 2 + rightDrawableTopPadding;
} else {
y = getPaddingTop() + (textHeight - dh) / 2 + rightDrawableTopPadding;
}
rightDrawable.setBounds(x, y, x + dw, y + dh);
rightDrawableX = x + (dw >> 1);
rightDrawableY = y + (dh >> 1);
rightDrawable.draw(canvas);
}
}
public int getRightDrawableX() {
return rightDrawableX;
}
public int getRightDrawableY() {
return rightDrawableY;
}
private int getMaxTextWidth() {
return getMeasuredWidth() - (rightDrawableOutside && rightDrawable != null ? rightDrawable.getIntrinsicWidth() + drawablePadding : 0);
}
private void drawLayout(Canvas canvas) {
@ -868,7 +957,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
if (this.fullLayoutAdditionalWidth != fullLayoutAdditionalWidth || this.fullLayoutLeftOffset != fullLayoutLeftOffset) {
this.fullLayoutAdditionalWidth = fullLayoutAdditionalWidth;
this.fullLayoutLeftOffset = fullLayoutLeftOffset;
createLayout(getMeasuredWidth() - minusWidth);
createLayout(getMaxTextWidth() - getPaddingLeft() - getPaddingRight() - minusWidth);
}
}
@ -884,6 +973,14 @@ public class SimpleTextView extends View implements Drawable.Callback {
canHideRightDrawable = b;
}
public void setRightDrawableOutside(boolean outside) {
rightDrawableOutside = outside;
}
public boolean getRightDrawableOutside() {
return rightDrawableOutside;
}
public void setRightDrawableOnClick(OnClickListener onClickListener) {
rightDrawableOnClickListener = onClickListener;
}

View File

@ -1068,7 +1068,7 @@ public class Theme {
NotificationCenter.getInstance(account).addObserver(this, NotificationCenter.fileLoadFailed);
for (HashMap.Entry<String, LoadingPattern> entry : watingForLoad.entrySet()) {
LoadingPattern loadingPattern = entry.getValue();
FileLoader.getInstance(account).loadFile(ImageLocation.getForDocument(loadingPattern.pattern.document), "wallpaper", null, 0, 1);
FileLoader.getInstance(account).loadFile(ImageLocation.getForDocument(loadingPattern.pattern.document), "wallpaper", null, FileLoader.PRIORITY_LOW, 1);
}
}
} else {
@ -2388,7 +2388,7 @@ public class Theme {
loadingThemeWallpaperName = null;
newPathToWallpaper = null;
addObservers();
FileLoader.getInstance(account).loadFile(info.document, info, 1, 1);
FileLoader.getInstance(account).loadFile(info.document, info, FileLoader.PRIORITY_NORMAL, 1);
}
private void addObservers() {
@ -2681,7 +2681,7 @@ public class Theme {
TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) response;
loadingThemeWallpaperName = FileLoader.getAttachFileName(wallPaper.document);
addObservers();
FileLoader.getInstance(themeInfo.account).loadFile(wallPaper.document, wallPaper, 1, 1);
FileLoader.getInstance(themeInfo.account).loadFile(wallPaper.document, wallPaper, FileLoader.PRIORITY_NORMAL, 1);
} else {
onFinishLoadingRemoteTheme();
}
@ -2937,6 +2937,7 @@ public class Theme {
public static TextPaint chat_msgTextPaint;
public static TextPaint chat_actionTextPaint;
public static TextPaint chat_unlockExtendedMediaTextPaint;
public static TextPaint chat_msgBotButtonPaint;
public static TextPaint chat_msgGameTextPaint;
public static TextPaint[] chat_msgTextPaintEmoji;
@ -2996,6 +2997,7 @@ public class Theme {
public static Drawable chat_msgStickerHalfCheckDrawable;
public static Drawable chat_msgStickerViewsDrawable;
public static Drawable chat_msgStickerRepliesDrawable;
public static Drawable chat_msgUnlockDrawable;
public static Drawable chat_msgInViewsDrawable;
public static Drawable chat_msgInViewsSelectedDrawable;
public static Drawable chat_msgOutViewsDrawable;
@ -7709,7 +7711,7 @@ public class Theme {
}
if (night) {
if (currentTheme != currentNightTheme) {
if (currentTheme != currentNightTheme && (currentTheme == null || currentNightTheme != null && currentTheme.isDark() != currentNightTheme.isDark())) {
isInNigthMode = true;
lastThemeSwitchTime = SystemClock.elapsedRealtime();
switchingNightTheme = true;
@ -7717,7 +7719,7 @@ public class Theme {
switchingNightTheme = false;
}
} else {
if (currentTheme != currentDayTheme) {
if (currentTheme != currentDayTheme && (currentTheme == null || currentNightTheme != null && currentTheme.isDark() != currentNightTheme.isDark())) {
isInNigthMode = false;
lastThemeSwitchTime = SystemClock.elapsedRealtime();
switchingNightTheme = true;
@ -9071,6 +9073,8 @@ public class Theme {
chat_statusRecordPaint.setStrokeCap(Paint.Cap.ROUND);
chat_actionTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
chat_actionTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
chat_unlockExtendedMediaTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
chat_unlockExtendedMediaTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
chat_actionBackgroundGradientDarkenPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
chat_actionBackgroundGradientDarkenPaint.setColor(0x2a000000);
chat_timeBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@ -9135,6 +9139,7 @@ public class Theme {
chat_msgMediaHalfCheckDrawable = resources.getDrawable(R.drawable.msg_halfcheck_s).mutate();
chat_msgStickerHalfCheckDrawable = resources.getDrawable(R.drawable.msg_halfcheck_s).mutate();
chat_msgClockDrawable = new MsgClockDrawable();
chat_msgUnlockDrawable = resources.getDrawable(R.drawable.ic_lock_header).mutate();
chat_msgInViewsDrawable = resources.getDrawable(R.drawable.msg_views).mutate();
chat_msgInViewsSelectedDrawable = resources.getDrawable(R.drawable.msg_views).mutate();
chat_msgOutViewsDrawable = resources.getDrawable(R.drawable.msg_views).mutate();
@ -9398,6 +9403,7 @@ public class Theme {
chat_instantViewRectPaint.setStrokeWidth(AndroidUtilities.dp(1));
chat_pollTimerPaint.setStrokeWidth(AndroidUtilities.dp(1.1f));
chat_actionTextPaint.setTextSize(AndroidUtilities.dp(Math.max(16, SharedConfig.fontSize) - 2));
chat_unlockExtendedMediaTextPaint.setTextSize(AndroidUtilities.dp(Math.max(16, SharedConfig.fontSize)));
chat_contextResult_titleTextPaint.setTextSize(AndroidUtilities.dp(15));
chat_contextResult_descriptionTextPaint.setTextSize(AndroidUtilities.dp(13));
chat_radialProgressPaint.setStrokeWidth(AndroidUtilities.dp(3));
@ -9457,6 +9463,7 @@ public class Theme {
chat_statusRecordPaint.setColor(getColor(key_chat_status));
chat_actionTextPaint.setColor(getColor(key_chat_serviceText));
chat_actionTextPaint.linkColor = getColor(key_chat_serviceLink);
chat_unlockExtendedMediaTextPaint.setColor(getColor(key_chat_serviceText));
chat_contextResult_titleTextPaint.setColor(getColor(key_windowBackgroundWhiteBlackText));
chat_composeBackgroundPaint.setColor(getColor(key_chat_messagePanelBackground));
chat_timeBackgroundPaint.setColor(getColor(key_chat_mediaTimeBackground));
@ -9478,6 +9485,7 @@ public class Theme {
setDrawableColorByKey(chat_msgStickerHalfCheckDrawable, key_chat_serviceText);
setDrawableColorByKey(chat_msgStickerViewsDrawable, key_chat_serviceText);
setDrawableColorByKey(chat_msgStickerRepliesDrawable, key_chat_serviceText);
setDrawableColorByKey(chat_msgUnlockDrawable, key_chat_serviceText);
setDrawableColorByKey(chat_shareIconDrawable, key_chat_serviceIcon);
setDrawableColorByKey(chat_replyIconDrawable, key_chat_serviceIcon);
setDrawableColorByKey(chat_goIconDrawable, key_chat_serviceIcon);
@ -9697,6 +9705,7 @@ public class Theme {
setDrawableColor(chat_msgStickerRepliesDrawable, 0xffffffff);
chat_actionTextPaint.setColor(0xffffffff);
chat_actionTextPaint.linkColor = 0xffffffff;
chat_unlockExtendedMediaTextPaint.setColor(0xffffffff);
chat_botButtonPaint.setColor(0xffffffff);
setDrawableColor(chat_commentStickerDrawable, 0xffffffff);
setDrawableColor(chat_shareIconDrawable, 0xffffffff);
@ -9717,6 +9726,7 @@ public class Theme {
setDrawableColorByKey(chat_msgStickerRepliesDrawable, key_chat_serviceText);
chat_actionTextPaint.setColor(getColor(key_chat_serviceText));
chat_actionTextPaint.linkColor = getColor(key_chat_serviceLink);
chat_unlockExtendedMediaTextPaint.setColor(getColor(key_chat_serviceText));
setDrawableColorByKey(chat_commentStickerDrawable, key_chat_serviceIcon);
setDrawableColorByKey(chat_shareIconDrawable, key_chat_serviceIcon);
setDrawableColorByKey(chat_replyIconDrawable, key_chat_serviceIcon);

View File

@ -163,7 +163,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl
imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (height * 0.399f), MeasureSpec.EXACTLY));
titleTextView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED));
descriptionText.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED));
buttonTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(86), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(42), MeasureSpec.EXACTLY));
buttonTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(72), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY));
}
break;
}
@ -605,7 +605,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl
buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
int buttonRadiusDp = currentType == ACTION_TYPE_SET_PASSCODE || currentType == ACTION_TYPE_CHANGE_PHONE_NUMBER ? 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.filledRect(Theme.key_featuredStickers_addButton, buttonRadiusDp));
viewGroup.addView(buttonTextView);
buttonTextView.setOnClickListener(v -> {

View File

@ -26,6 +26,7 @@ import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.DrawerLayoutContainer;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
@ -56,7 +57,7 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter imple
private ArrayList<Item> items = new ArrayList<>(11);
private ArrayList<Integer> accountNumbers = new ArrayList<>();
private boolean accountsShown;
private DrawerProfileCell profileCell;
public DrawerProfileCell profileCell;
private SideMenultItemAnimator itemAnimator;
private boolean hasGps;
@ -113,6 +114,11 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter imple
return accountsShown;
}
private View.OnClickListener onPremiumDrawableClick;
public void setOnPremiumDrawableClick(View.OnClickListener listener) {
onPremiumDrawableClick = listener;
}
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.updateUserStatus) {
@ -144,7 +150,14 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter imple
View view;
switch (viewType) {
case 0:
view = profileCell = new DrawerProfileCell(mContext, mDrawerLayoutContainer);
view = profileCell = new DrawerProfileCell(mContext, mDrawerLayoutContainer) {
@Override
protected void onPremiumClick() {
if (onPremiumDrawableClick != null) {
onPremiumDrawableClick.onClick(this);
}
}
};
break;
case 2:
view = new DividerCell(mContext);
@ -272,10 +285,81 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter imple
if (!UserConfig.getInstance(UserConfig.selectedAccount).isClientActivated()) {
return;
}
int contactsIcon = R.drawable.baseline_perm_contact_calendar_24;
int savedIcon = R.drawable.baseline_bookmark_24;
int settingsIcon = R.drawable.baseline_settings_24;
int callsIcon = R.drawable.baseline_call_24;
int eventType = Theme.getEventType();
int newGroupIcon;
int newSecretIcon;
int newChannelIcon;
int contactsIcon;
int callsIcon;
int savedIcon;
int settingsIcon;
int inviteIcon;
int helpIcon;
int peopleNearbyIcon;
if (eventType == 0) {
newGroupIcon = R.drawable.msg_groups_ny;
//newSecretIcon = R.drawable.msg_secret_ny;
//newChannelIcon = R.drawable.msg_channel_ny;
contactsIcon = R.drawable.msg_contacts_ny;
callsIcon = R.drawable.msg_calls_ny;
savedIcon = R.drawable.msg_saved_ny;
settingsIcon = R.drawable.msg_settings_ny;
inviteIcon = R.drawable.msg_invite_ny;
helpIcon = R.drawable.msg_help_ny;
peopleNearbyIcon = R.drawable.msg_nearby_ny;
} else if (eventType == 1) {
newGroupIcon = R.drawable.msg_groups_14;
//newSecretIcon = R.drawable.msg_secret_14;
//newChannelIcon = R.drawable.msg_channel_14;
contactsIcon = R.drawable.msg_contacts_14;
callsIcon = R.drawable.msg_calls_14;
savedIcon = R.drawable.msg_saved_14;
settingsIcon = R.drawable.msg_settings_14;
inviteIcon = R.drawable.msg_secret_ny;
helpIcon = R.drawable.msg_help;
peopleNearbyIcon = R.drawable.msg_secret_14;
} else if (eventType == 2) {
newGroupIcon = R.drawable.msg_groups_hw;
//newSecretIcon = R.drawable.msg_secret_hw;
//newChannelIcon = R.drawable.msg_channel_hw;
contactsIcon = R.drawable.msg_contacts_hw;
callsIcon = R.drawable.msg_calls_hw;
savedIcon = R.drawable.msg_saved_hw;
settingsIcon = R.drawable.msg_settings_hw;
inviteIcon = R.drawable.msg_invite_hw;
helpIcon = R.drawable.msg_help_hw;
peopleNearbyIcon = R.drawable.msg_secret_hw;
} else {
newGroupIcon = R.drawable.msg_groups;
//newSecretIcon = R.drawable.msg_secret;
//newChannelIcon = R.drawable.msg_channel;
contactsIcon = R.drawable.msg_contacts;
callsIcon = R.drawable.msg_calls;
savedIcon = R.drawable.msg_saved;
settingsIcon = R.drawable.msg_settings_old;
inviteIcon = R.drawable.msg_invite;
helpIcon = R.drawable.msg_help;
peopleNearbyIcon = R.drawable.msg_nearby;
}
UserConfig me = UserConfig.getInstance(UserConfig.selectedAccount);
if (me != null && me.isPremium()) {
if (me.getEmojiStatus() != null) {
items.add(new Item(15, LocaleController.getString("ChangeEmojiStatus", R.string.ChangeEmojiStatus), 0, R.raw.emoji_status_change_to_set));
} else {
items.add(new Item(15, LocaleController.getString("SetEmojiStatus", R.string.SetEmojiStatus), 0, R.raw.emoji_status_set_to_change));
}
items.add(null); // divider
}
// TODO: NekoX: Fix icon here
// int contactsIcon = R.drawable.baseline_perm_contact_calendar_24;
// int savedIcon = R.drawable.baseline_bookmark_24;
// int settingsIcon = R.drawable.baseline_settings_24;
// int callsIcon = R.drawable.baseline_call_24;
items.add(new Item(2, LocaleController.getString("NewGroup", R.string.NewGroup), newGroupIcon));
//items.add(new Item(3, LocaleController.getString("NewSecretChat", R.string.NewSecretChat), newSecretIcon));
//items.add(new Item(4, LocaleController.getString("NewChannel", R.string.NewChannel), newChannelIcon));
items.add(new Item(6, LocaleController.getString("Contacts", R.string.Contacts), contactsIcon));
items.add(new Item(11, LocaleController.getString("SavedMessages", R.string.SavedMessages), savedIcon));
items.add(new Item(8, LocaleController.getString("Settings", R.string.Settings), settingsIcon));
@ -340,6 +424,7 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter imple
private static class Item {
public int icon;
public int lottieIcon;
public String text;
public int id;
@ -349,8 +434,15 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter imple
this.text = text;
}
public Item(int id, String text, int icon, int lottieIcon) {
this.icon = icon;
this.lottieIcon = lottieIcon;
this.id = id;
this.text = text;
}
public void bind(DrawerActionCell actionCell) {
actionCell.setTextAndIcon(id, text, icon);
actionCell.setTextAndIcon(id, text, icon, lottieIcon);
}
}

View File

@ -279,7 +279,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement
File f = FileLoader.getInstance(currentAccount).getPathToAttach(thumb, "webp", true);
if (!f.exists()) {
stickersToLoad.add(FileLoader.getAttachFileName(thumb, "webp"));
FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(thumb, result.sticker), result.parent, "webp", 1, 1);
FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(thumb, result.sticker), result.parent, "webp", FileLoader.PRIORITY_NORMAL, 1);
}
}
}

View File

@ -138,7 +138,7 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement
ArrayList<TLRPC.TL_messages_stickerSet> sets = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_EMOJI);
File f = FileLoader.getInstance(currentAccount).getPathToAttach(animatedSticker, true);
if (!f.exists()) {
FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(animatedSticker), sets.get(0), null, 1, 1);
FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(animatedSticker), sets.get(0), null, FileLoader.PRIORITY_NORMAL, 1);
}
}
}

View File

@ -530,7 +530,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
sizeBar = new SeekBarView(context);
sizeBar.setReportChanges(true);
// sizeBar.setSeparatorsCount(endFontSize - startFontSize);
sizeBar.setSeparatorsCount(endFontSize - startFontSize + 1);
sizeBar.setDelegate(new SeekBarView.SeekBarViewDelegate() {
@Override
public void onSeekBarDrag(boolean stop, float progress) {
@ -1315,7 +1315,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
deleteView.setOnClickListener(v -> {
if (pressedLinkOwnerLayout != null) {
AndroidUtilities.addToClipboard(pressedLinkOwnerLayout.getText());
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (AndroidUtilities.shouldShowClipboardToast()) {
Toast.makeText(parentActivity, LocaleController.getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show();
}
}
@ -3753,7 +3753,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
@Override
public void onTextCopied() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (AndroidUtilities.shouldShowClipboardToast()) {
BulletinFactory.of(containerView, null).createCopyBulletin(LocaleController.getString("TextCopied", R.string.TextCopied)).show();
}
}
@ -6327,7 +6327,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(currentDocument.thumbs, 40);
imageView.setImage(ImageLocation.getForDocument(currentDocument), null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", currentDocument.size, null, parentAdapter.currentPage, 1);
} else {
FileLoader.getInstance(currentAccount).loadFile(currentDocument, parentAdapter.currentPage, 1, 1);
FileLoader.getInstance(currentAccount).loadFile(currentDocument, parentAdapter.currentPage, FileLoader.PRIORITY_NORMAL, 1);
}
buttonState = 1;
radialProgress.setIcon(getIconForCurrentState(), true, animated);
@ -11289,7 +11289,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
index = 0;
}
final PhotoViewer photoViewer = PhotoViewer.getInstance();
photoViewer.setParentActivity(parentActivity);
photoViewer.setParentActivity(parentFragment);
return photoViewer.openPhoto(index, new RealPageBlocksAdapter(adapter.currentPage, pageBlocks), new PageBlocksPhotoViewerProvider(pageBlocks));
}

View File

@ -29,7 +29,9 @@ public class BasePermissionsActivity extends Activity {
REQUEST_CODE_CALLS = 7,
REQUEST_CODE_OPEN_CAMERA = 20,
REQUEST_CODE_VIDEO_MESSAGE = 150,
REQUEST_CODE_EXTERNAL_STORAGE_FOR_AVATAR = 151;
REQUEST_CODE_EXTERNAL_STORAGE_FOR_AVATAR = 151,
REQUEST_CODE_SIGN_IN_WITH_GOOGLE = 200,
REQUEST_CODE_PAYMENT_FORM = 210;
protected int currentAccount = -1;

View File

@ -287,6 +287,7 @@ public class AboutLinkCell extends FrameLayout {
canvas.translate(0, textY = AndroidUtilities.dp(8));
try {
Theme.profile_aboutTextPaint.linkColor = Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider);
if (firstThreeLinesLayout == null || !shouldExpand) {
if (textLayout != null) {
textLayout.draw(canvas);
@ -410,7 +411,7 @@ public class AboutLinkCell extends FrameLayout {
onLinkClick(pressedLinkFinal);
} else if (which == 1) {
AndroidUtilities.addToClipboard(url);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (AndroidUtilities.shouldShowClipboardToast()) {
if (url.startsWith("@")) {
BulletinFactory.of(parentFragment).createSimpleBulletin(R.raw.copy,
LocaleController.getString("UsernameCopied", R.string.UsernameCopied)).show();

View File

@ -212,7 +212,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown
if (miniButtonState == 0) {
miniButtonState = 1;
radialProgress.setProgress(0, false);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, 1, 0);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, FileLoader.PRIORITY_HIGH, 0);
radialProgress.setMiniIcon(getMiniIconForCurrentState(), false, true);
invalidate();
} else if (miniButtonState == 1) {
@ -229,7 +229,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown
public void didPressedButton() {
if (buttonState == 0) {
if (miniButtonState == 0) {
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, 1, 0);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, FileLoader.PRIORITY_NORMAL, 0);
}
if (MediaController.getInstance().findMessageInPlaylistAndPlay(currentMessageObject)) {
if (hasMiniProgress == 2 && miniButtonState != 1) {
@ -250,7 +250,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown
}
} else if (buttonState == 2) {
radialProgress.setProgress(0, false);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, 1, 0);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, FileLoader.PRIORITY_NORMAL, 0);
buttonState = 4;
radialProgress.setIcon(getIconForCurrentState(), false, true);
invalidate();

View File

@ -26,6 +26,7 @@ import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.Reactions.ReactionsUtils;
import org.telegram.ui.Components.Switch;
public class AvailableReactionCell extends FrameLayout {
@ -91,7 +92,7 @@ public class AvailableReactionCell extends FrameLayout {
this.react = react;
textView.setText(react.title);
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(react.static_icon, Theme.key_windowBackgroundGray, 1.0f);
imageView.setImage(ImageLocation.getForDocument(react.center_icon), "32_32_lastframe", "webp", svgThumb, react);
imageView.setImage(ImageLocation.getForDocument(react.activate_animation), ReactionsUtils.ACTIVATE_ANIMATION_FILTER, "tgs", svgThumb, react);
locked = canLock && react.premium && !UserConfig.getInstance(currentAccount).isPremium();
if (locked) {

View File

@ -327,7 +327,9 @@ public class BotHelpCell extends View {
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setText(textLayout.getText());
if (textLayout != null) {
info.setText(textLayout.getText());
}
}
public boolean animating() {

View File

@ -697,9 +697,9 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
} else if (buttonState == 2) {
radialProgress.setProgress(0, false);
if (documentAttach != null) {
FileLoader.getInstance(currentAccount).loadFile(documentAttach, inlineResult, 1, 0);
FileLoader.getInstance(currentAccount).loadFile(documentAttach, inlineResult, FileLoader.PRIORITY_NORMAL, 0);
} else if (inlineResult.content instanceof TLRPC.TL_webDocument) {
FileLoader.getInstance(currentAccount).loadFile(WebFile.createWithWebDocument(inlineResult.content), 1, 1);
FileLoader.getInstance(currentAccount).loadFile(WebFile.createWithWebDocument(inlineResult.content), FileLoader.PRIORITY_HIGH, 1);
}
buttonState = 4;
radialProgress.setIcon(getIconForCurrentState(), false, true);

View File

@ -14,8 +14,12 @@ import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
@ -72,6 +76,7 @@ import org.telegram.ui.Components.ForegroundColorSpanThemable;
import org.telegram.ui.Components.Premium.PremiumGradient;
import org.telegram.ui.Components.PullForegroundDrawable;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.StaticLayoutEx;
import org.telegram.ui.Components.StatusDrawable;
import org.telegram.ui.Components.SwipeGestureSettingsView;
@ -222,7 +227,14 @@ public class DialogCell extends BaseCell {
private boolean hasCall;
private int nameLeft;
private int nameWidth;
private StaticLayout nameLayout;
private boolean nameLayoutFits;
private float nameLayoutTranslateX;
private boolean nameLayoutEllipsizeLeft;
private boolean nameLayoutEllipsizeByGradient;
private Paint fadePaint;
private Paint fadePaintBack;
private boolean drawNameLock;
private int nameMuteLeft;
private int nameLockLeft;
@ -294,6 +306,7 @@ public class DialogCell extends BaseCell {
private boolean drawVerified;
private boolean drawPremium;
private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emojiStatus;
private int drawScam;
@ -357,6 +370,9 @@ public class DialogCell extends BaseCell {
checkBox.setDrawBackgroundAsArc(3);
addView(checkBox);
}
emojiStatus = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, AndroidUtilities.dp(22));
emojiStatus.center = false;
}
public void setDialog(TLRPC.Dialog dialog, int type, int folder) {
@ -499,6 +515,9 @@ public class DialogCell extends BaseCell {
if (preloader != null) {
preloader.remove(currentDialogId);
}
if (emojiStatus != null) {
emojiStatus.detach();
}
AnimatedEmojiSpan.release(this, animatedEmojiStack);
}
@ -522,6 +541,9 @@ public class DialogCell extends BaseCell {
cornerProgress = 0.0f;
setTranslationX(0);
setTranslationY(0);
if (emojiStatus != null) {
emojiStatus.attach();
}
}
@Override
@ -663,6 +685,7 @@ public class DialogCell extends BaseCell {
drawScam = 0;
drawPinBackground = false;
hasMessageThumb = false;
nameLayoutEllipsizeByGradient = false;
int offsetName = 0;
boolean showChecks = !UserObject.isUserSelf(user) && !useMeForMyMessages;
boolean drawTime = true;
@ -846,6 +869,18 @@ public class DialogCell extends BaseCell {
drawVerified = user.verifiedExtended();
}
drawPremium = MessagesController.getInstance(currentAccount).isPremiumUser(user) && UserConfig.getInstance(currentAccount).clientUserId != user.id && user.id != 0;
if (drawPremium) {
if (user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
nameLayoutEllipsizeByGradient = true;
emojiStatus.set(((TLRPC.TL_emojiStatusUntil) user.emoji_status).document_id, false);
} else if (user.emoji_status instanceof TLRPC.TL_emojiStatus) {
nameLayoutEllipsizeByGradient = true;
emojiStatus.set(((TLRPC.TL_emojiStatus) user.emoji_status).document_id, false);
} else {
nameLayoutEllipsizeByGradient = true;
emojiStatus.set(PremiumGradient.getInstance().premiumStarDrawableMini, false);
}
}
}
}
}
@ -959,7 +994,30 @@ public class DialogCell extends BaseCell {
fromChat = MessagesController.getInstance(currentAccount).getChat(-fromId);
}
drawCount2 = true;
if (dialogsType == 2) {
boolean lastMessageIsReaction = false;
if (currentDialogId > 0 && message.isOutOwner() && message.messageOwner.reactions != null && message.messageOwner.reactions.recent_reactions != null && !message.messageOwner.reactions.recent_reactions.isEmpty()) {
TLRPC.MessagePeerReaction lastReaction = message.messageOwner.reactions.recent_reactions.get(0);
if (lastReaction.peer_id.user_id != 0 &&lastReaction.peer_id.user_id != UserConfig.getInstance(currentAccount).clientUserId) {
lastMessageIsReaction = true;
ReactionsLayoutInBubble.VisibleReaction visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(lastReaction.reaction);
currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex];
if (visibleReaction.emojicon != null) {
messageString = LocaleController.formatString("ReactionInDialog", R.string.ReactionInDialog, visibleReaction.emojicon);
} else {
String string = LocaleController.formatString("ReactionInDialog", R.string.ReactionInDialog, "**reaction**");
int i = string.indexOf("**reaction**");
string = string.replace("**reaction**", "d");
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(string);
spannableStringBuilder.setSpan(new AnimatedEmojiSpan(visibleReaction.documentId, currentMessagePaint == null ? null : currentMessagePaint.getFontMetricsInt()), i, i + 1, 0);
messageString = spannableStringBuilder;
}
}
}
if (lastMessageIsReaction) {
} else if (dialogsType == 2) {
if (chat != null) {
if (ChatObject.isChannel(chat) && !chat.megagroup) {
if (chat.participants_count != 0) {
@ -1462,8 +1520,6 @@ public class DialogCell extends BaseCell {
timeLeft = 0;
}
int nameWidth;
if (!LocaleController.isRTL) {
nameWidth = getMeasuredWidth() - nameLeft - AndroidUtilities.dp(14) - timeWidth;
} else {
@ -1505,7 +1561,13 @@ public class DialogCell extends BaseCell {
}
}
if (dialogMuted && !drawVerified && drawScam == 0) {
if (drawPremium && emojiStatus.getDrawable() != null) {
int w = AndroidUtilities.dp(6 + 24 + 6);
nameWidth -= w;
if (LocaleController.isRTL) {
nameLeft += w;
}
} else if (dialogMuted && !drawVerified && drawScam == 0) {
int w = AndroidUtilities.dp(6) + Theme.dialogs_muteDrawable.getIntrinsicWidth();
nameWidth -= w;
if (LocaleController.isRTL) {
@ -1518,7 +1580,7 @@ public class DialogCell extends BaseCell {
nameLeft += w;
}
} else if (drawPremium) {
int w = AndroidUtilities.dp(6) + PremiumGradient.getInstance().premiumStarDrawableMini.getIntrinsicWidth();
int w = AndroidUtilities.dp(6 + 24 + 6);
nameWidth -= w;
if (LocaleController.isRTL) {
nameLeft += w;
@ -1535,7 +1597,12 @@ public class DialogCell extends BaseCell {
if (ellipsizeWidth < 0) {
ellipsizeWidth = 0;
}
CharSequence nameStringFinal = TextUtils.ellipsize(nameString.replace('\n', ' '), Theme.dialogs_namePaint[paintIndex], ellipsizeWidth, TextUtils.TruncateAt.END);
CharSequence nameStringFinal = nameString.replace('\n', ' ');
if (nameLayoutEllipsizeByGradient) {
nameLayoutFits = nameStringFinal.length() == TextUtils.ellipsize(nameStringFinal, Theme.dialogs_namePaint[paintIndex], ellipsizeWidth, TextUtils.TruncateAt.END).length();
ellipsizeWidth += AndroidUtilities.dp(48);
}
nameStringFinal = TextUtils.ellipsize(nameStringFinal, Theme.dialogs_namePaint[paintIndex], ellipsizeWidth, TextUtils.TruncateAt.END);
nameStringFinal = Emoji.replaceEmoji(nameStringFinal, Theme.dialogs_namePaint[paintIndex].getFontMetricsInt(), AndroidUtilities.dp(20), false);
if (message != null && message.hasHighlightedWords()) {
CharSequence s = AndroidUtilities.highlightText(nameStringFinal, message.highlightedWords, resourcesProvider);
@ -1544,7 +1611,9 @@ public class DialogCell extends BaseCell {
}
}
nameStringFinal = Emoji.replaceEmoji(nameStringFinal, Theme.dialogs_namePaint[paintIndex].getFontMetricsInt(), AndroidUtilities.dp(12), false);
nameLayout = new StaticLayout(nameStringFinal, Theme.dialogs_namePaint[paintIndex], nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
nameLayout = new StaticLayout(nameStringFinal, Theme.dialogs_namePaint[paintIndex], Math.max(ellipsizeWidth, nameWidth), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
nameLayoutTranslateX = nameLayoutEllipsizeByGradient && nameLayout.isRtlCharAt(0) ? -AndroidUtilities.dp(36) : 0;
nameLayoutEllipsizeLeft = nameLayout.isRtlCharAt(0);
} catch (Exception e) {
FileLog.e(e);
}
@ -1786,12 +1855,15 @@ public class DialogCell extends BaseCell {
if (nameLayout != null && nameLayout.getLineCount() > 0) {
left = nameLayout.getLineLeft(0);
widthpx = Math.ceil(nameLayout.getLineWidth(0));
if (nameLayoutEllipsizeByGradient) {
widthpx = Math.min(nameWidth, widthpx);
}
if (dialogMuted && !drawVerified && drawScam == 0) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_muteDrawable.getIntrinsicWidth());
} else if (drawVerified) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_verifiedDrawable.getIntrinsicWidth());
} else if (drawPremium) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - PremiumGradient.getInstance().premiumStarDrawableMini.getIntrinsicWidth());
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx - left) - AndroidUtilities.dp(24));
} else if (drawScam != 0) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth());
}
@ -1832,8 +1904,16 @@ public class DialogCell extends BaseCell {
} else {
if (nameLayout != null && nameLayout.getLineCount() > 0) {
left = nameLayout.getLineRight(0);
if (nameLayoutEllipsizeByGradient) {
left = Math.min(nameWidth, left);
}
if (left == nameWidth) {
widthpx = Math.ceil(nameLayout.getLineWidth(0));
if (nameLayoutEllipsizeByGradient) {
widthpx = Math.min(nameWidth, widthpx);
// widthpx -= AndroidUtilities.dp(36);
// left += AndroidUtilities.dp(36);
}
if (widthpx < nameWidth) {
nameLeft -= (nameWidth - widthpx);
}
@ -2153,6 +2233,20 @@ public class DialogCell extends BaseCell {
user = MessagesController.getInstance(currentAccount).getUser(user.id);
invalidate();
}
if (user != null && (mask & MessagesController.UPDATE_MASK_EMOJI_STATUS) != 0) {
user = MessagesController.getInstance(currentAccount).getUser(user.id);
if (user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
nameLayoutEllipsizeByGradient = true;
emojiStatus.set(((TLRPC.TL_emojiStatusUntil) user.emoji_status).document_id, animated);
} else if (user.emoji_status instanceof TLRPC.TL_emojiStatus) {
nameLayoutEllipsizeByGradient = true;
emojiStatus.set(((TLRPC.TL_emojiStatus) user.emoji_status).document_id, animated);
} else {
nameLayoutEllipsizeByGradient = true;
emojiStatus.set(PremiumGradient.getInstance().premiumStarDrawableMini, animated);
}
invalidate();
}
if (isDialogCell) {
if ((mask & MessagesController.UPDATE_MASK_USER_PRINT) != 0) {
CharSequence printString = MessagesController.getInstance(currentAccount).getPrintingString(currentDialogId, 0, true);
@ -2698,6 +2792,19 @@ public class DialogCell extends BaseCell {
}
if (nameLayout != null) {
if (nameLayoutEllipsizeByGradient && !nameLayoutFits) {
if (nameLayoutEllipsizeLeft && fadePaint == null) {
fadePaint = new Paint();
fadePaint.setShader(new LinearGradient(0, 0, AndroidUtilities.dp(24), 0, new int[]{0xffffffff, 0}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
fadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
} else if (fadePaintBack == null) {
fadePaintBack = new Paint();
fadePaintBack.setShader(new LinearGradient(0, 0, AndroidUtilities.dp(24), 0, new int[]{0, 0xffffffff}, new float[]{0f, 1f}, Shader.TileMode.CLAMP));
fadePaintBack.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), 255, Canvas.ALL_SAVE_FLAG);
canvas.clipRect(nameLeft, 0, nameLeft + nameWidth, getMeasuredHeight());
}
if (currentDialogFolderId != 0) {
Theme.dialogs_namePaint[paintIndex].setColor(Theme.dialogs_namePaint[paintIndex].linkColor = Theme.getColor(Theme.key_chats_nameArchived, resourcesProvider));
} else if (encryptedChat != null || customDialog != null && customDialog.type == 2) {
@ -2706,9 +2813,21 @@ public class DialogCell extends BaseCell {
Theme.dialogs_namePaint[paintIndex].setColor(Theme.dialogs_namePaint[paintIndex].linkColor = Theme.getColor(Theme.key_chats_name, resourcesProvider));
}
canvas.save();
canvas.translate(nameLeft, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 13));
canvas.translate(nameLeft + nameLayoutTranslateX, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 13));
nameLayout.draw(canvas);
canvas.restore();
if (nameLayoutEllipsizeByGradient && !nameLayoutFits) {
canvas.save();
if (nameLayoutEllipsizeLeft) {
canvas.translate(nameLeft , 0);
canvas.drawRect(0, 0, AndroidUtilities.dp(24), getMeasuredHeight(), fadePaint);
} else {
canvas.translate(nameLeft + nameWidth - AndroidUtilities.dp(24), 0);
canvas.drawRect(0, 0, AndroidUtilities.dp(24), getMeasuredHeight(), fadePaintBack);
}
canvas.restore();
canvas.restore();
}
}
if (timeLayout != null && currentDialogFolderId == 0) {
@ -2850,9 +2969,20 @@ public class DialogCell extends BaseCell {
Theme.dialogs_verifiedDrawable.draw(canvas);
Theme.dialogs_verifiedCheckDrawable.draw(canvas);
} else if (drawPremium) {
Drawable premiumDrawable = PremiumGradient.getInstance().premiumStarDrawableMini;
setDrawableBounds(premiumDrawable, nameMuteLeft - AndroidUtilities.dp(1), AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12.5f : 15.5f));
premiumDrawable.draw(canvas);
if (emojiStatus != null) {
emojiStatus.setBounds(
nameMuteLeft - AndroidUtilities.dp(2),
AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12.5f : 15.5f) - AndroidUtilities.dp(4),
nameMuteLeft + AndroidUtilities.dp(20),
AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12.5f : 15.5f) - AndroidUtilities.dp(4) + AndroidUtilities.dp(22)
);
emojiStatus.setColor(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider));
emojiStatus.draw(canvas);
} else {
Drawable premiumDrawable = PremiumGradient.getInstance().premiumStarDrawableMini;
setDrawableBounds(premiumDrawable, nameMuteLeft - AndroidUtilities.dp(1), AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12.5f : 15.5f));
premiumDrawable.draw(canvas);
}
} else if (drawScam != 0) {
setDrawableBounds((drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable), nameMuteLeft, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12 : 15));
(drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).draw(canvas);

View File

@ -16,8 +16,11 @@ import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
@ -25,29 +28,39 @@ import org.telegram.messenger.FileLog;
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.UserConfig;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedTextView;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RLottieImageView;
import java.util.Set;
public class DrawerActionCell extends FrameLayout {
private TextView textView;
private ImageView imageView;
private RLottieImageView lottieImageView;
private AnimatedTextView textView;
private int currentId;
private RectF rect = new RectF();
private int currentLottieId;
public DrawerActionCell(Context context) {
super(context);
textView = new TextView(context);
imageView = new ImageView(context);
addView(imageView, LayoutHelper.createFrame(24, 24, Gravity.LEFT | Gravity.TOP, 19, 12, 0, 0));
lottieImageView = new RLottieImageView(context);
lottieImageView.setAutoRepeat(false);
lottieImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_menuItemIcon), PorterDuff.Mode.SRC_IN));
addView(lottieImageView, LayoutHelper.createFrame(28, 28, Gravity.LEFT | Gravity.TOP, 17, 10, 0, 0));
textView = new AnimatedTextView(context, true, true, true);
textView.setAnimationProperties(.6f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT);
textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
textView.setTextSize(AndroidUtilities.dp(15));
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
textView.setLines(1);
textView.setMaxLines(1);
textView.setSingleLine(true);
textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
textView.setCompoundDrawablePadding(AndroidUtilities.dp(29));
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 19, 0, 16, 0));
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 19 + 24 + 29, 0, 16, 0));
setWillNotDraw(false);
}
@ -87,13 +100,38 @@ public class DrawerActionCell extends FrameLayout {
textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText));
}
public void setTextAndIcon(int id, String text, int resId) {
public void setTextAndIcon(int id, String text, int resId, int lottieId) {
currentId = id;
try {
textView.setText(text);
Drawable drawable = getResources().getDrawable(resId).mutate();
drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_menuItemIcon), PorterDuff.Mode.SRC_IN));
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
textView.setText(text, false);
if (lottieId != 0) {
imageView.setImageDrawable(null);
lottieImageView.setAnimation(currentLottieId = lottieId, 28, 28);
} else {
Drawable drawable = getResources().getDrawable(resId).mutate();
drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_menuItemIcon), PorterDuff.Mode.SRC_IN));
imageView.setImageDrawable(drawable);
lottieImageView.clearAnimationDrawable();
currentLottieId = 0;
}
} catch (Throwable e) {
FileLog.e(e);
}
}
public void updateText(String text) {
textView.setText(text);
}
public void updateIcon(int lottieId) {
try {
if (lottieId != currentLottieId) {
lottieImageView.setOnAnimationEndListener(() -> {
lottieImageView.setAnimation(currentLottieId = lottieId, 28, 28);
lottieImageView.setOnAnimationEndListener(null);
});
lottieImageView.playAnimation();
}
} catch (Throwable e) {
FileLog.e(e);
}
@ -104,5 +142,7 @@ public class DrawerActionCell extends FrameLayout {
super.onInitializeAccessibilityNodeInfo(info);
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
info.setText(textView.getText());
info.setClassName(TextView.class.getName());
}
}

View File

@ -14,7 +14,9 @@ import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
@ -24,11 +26,13 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Build;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
@ -36,7 +40,8 @@ import android.widget.Toast;
import androidx.palette.graphics.Palette;
import androidx.core.content.ContextCompat;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.AndroidUtilities;
@ -46,9 +51,14 @@ import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaDataController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLRPC;
@ -57,10 +67,12 @@ import org.telegram.ui.Components.AudioPlayerAlert;
import org.telegram.ui.ActionBar.ActionBarLayout;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.DrawerLayoutContainer;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AnimatedFloat;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.ColoredImageSpan;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.EmojiTextView;
import org.telegram.ui.Components.FireworksEffect;
@ -69,21 +81,28 @@ import org.telegram.ui.Components.Premium.PremiumGradient;
import org.telegram.ui.Components.Premium.StarParticlesView;
import org.telegram.ui.Components.RLottieDrawable;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.Components.Reactions.AnimatedEmojiEffect;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
import org.telegram.ui.Components.SnowflakesEffect;
import org.telegram.ui.ThemeActivity;
import java.util.ArrayList;
import tw.nekomimi.nekogram.NekoConfig;
public class DrawerProfileCell extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
private BackupImageView avatarImageView;
private TextView nameTextView;
private SimpleTextView nameTextView;
private AudioPlayerAlert.ClippingTextViewSwitcher phoneTextView;
private ImageView shadowView;
protected ImageView arrowView;
private final ImageReceiver imageReceiver;
private RLottieImageView darkThemeView;
private RLottieDrawable sunDrawable;
private boolean updateRightDrawable = true;
private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable status;
private AnimatedStatusView animatedStatus;
private Rect srcRect = new Rect();
private Rect destRect = new Rect();
@ -99,6 +118,8 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
public boolean drawPremium;
public float drawPremiumProgress;
private float stateX, stateY;
StarParticlesView.Drawable starParticlesDrawable;
PremiumGradient.GradientTools gradientTools;
@ -165,14 +186,26 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
avatarImageView.getImageReceiver().setRoundRadius(AndroidUtilities.dp(32));
addView(avatarImageView, LayoutHelper.createFrame(64, 64, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 0, 67));
nameTextView = new EmojiTextView(context);
nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
nameTextView = new SimpleTextView(context) {
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (updateRightDrawable) {
updateRightDrawable = false;
getEmojiStatusLocation(AndroidUtilities.rectTmp2);
animatedStatus.translate(AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY());
}
}
};
nameTextView.setRightDrawableOnClick(e -> {
if (lastUser != null && lastUser.premium) {
onPremiumClick();
}
});
nameTextView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4));
nameTextView.setTextSize(15);
nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
nameTextView.setLines(1);
nameTextView.setMaxLines(1);
nameTextView.setSingleLine(true);
nameTextView.setGravity(Gravity.LEFT);
nameTextView.setEllipsize(TextUtils.TruncateAt.END);
nameTextView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM, 16, 0, 76, 28));
phoneTextView = new AudioPlayerAlert.ClippingTextViewSwitcher(context) {
@ -284,6 +317,184 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
} else if (NekoConfig.actionBarDecoration.Int() == 2) {
fireworksEffect = new FireworksEffect();
}
status = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, AndroidUtilities.dp(20));
nameTextView.setRightDrawable(status);
animatedStatus = new AnimatedStatusView(context, 20, 60);
addView(animatedStatus, LayoutHelper.createFrame(20, 20, Gravity.LEFT | Gravity.TOP));
}
protected void onPremiumClick() {
}
public static class AnimatedStatusView extends View {
private int stateSize;
private int effectsSize;
private int renderedEffectsSize;
private int animationUniq;
private ArrayList<Object> animations = new ArrayList<>();
public AnimatedStatusView(Context context, int stateSize, int effectsSize) {
super(context);
this.stateSize = stateSize;
this.effectsSize = effectsSize;
this.renderedEffectsSize = effectsSize;
}
public AnimatedStatusView(Context context, int stateSize, int effectsSize, int renderedEffectsSize) {
super(context);
this.stateSize = stateSize;
this.effectsSize = effectsSize;
this.renderedEffectsSize = renderedEffectsSize;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(
MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(Math.max(renderedEffectsSize, Math.max(stateSize, effectsSize))), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(Math.max(renderedEffectsSize, Math.max(stateSize, effectsSize))), MeasureSpec.EXACTLY)
);
}
private float y1, y2;
public void translate(float x, float y) {
setTranslationX(x - getMeasuredWidth() / 2f);
setTranslationY((this.y1 = y - getMeasuredHeight() / 2f) + this.y2);
}
public void translateY2(float y) {
setTranslationY(this.y1 + (this.y2 = y));
}
@Override
public void dispatchDraw(@NonNull Canvas canvas) {
final int renderedEffectsSize = AndroidUtilities.dp(this.renderedEffectsSize);
final int effectsSize = AndroidUtilities.dp(this.effectsSize);
for (int i = 0; i < animations.size(); ++i) {
Object animation = animations.get(i);
if (animation instanceof ImageReceiver) {
ImageReceiver imageReceiver = (ImageReceiver) animation;
imageReceiver.setImageCoords(
(getMeasuredWidth() - effectsSize) / 2f,
(getMeasuredHeight() - effectsSize) / 2f,
effectsSize,
effectsSize
);
imageReceiver.draw(canvas);
// if (imageReceiver.getLottieAnimation() != null && imageReceiver.getLottieAnimation().isRunning() && imageReceiver.getLottieAnimation().isLastFrame()) {
// imageReceiver.onDetachedFromWindow();
// animations.remove(imageReceiver);
// }
} else if (animation instanceof AnimatedEmojiEffect) {
AnimatedEmojiEffect effect = (AnimatedEmojiEffect) animation;
effect.setBounds(
(int) ((getMeasuredWidth() - renderedEffectsSize) / 2f),
(int) ((getMeasuredHeight() - renderedEffectsSize) / 2f),
(int) ((getMeasuredWidth() + renderedEffectsSize) / 2f),
(int) ((getMeasuredHeight() + renderedEffectsSize) / 2f)
);
effect.draw(canvas);
if (effect.done()) {
effect.removeView(this);
animations.remove(effect);
}
}
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
detach();
}
private void detach() {
if (!animations.isEmpty()) {
for (Object obj : animations) {
if (obj instanceof ImageReceiver) {
((ImageReceiver) obj).onDetachedFromWindow();
} else if (obj instanceof AnimatedEmojiEffect) {
((AnimatedEmojiEffect) obj).removeView(this);
}
}
}
animations.clear();
}
public void animateChange(ReactionsLayoutInBubble.VisibleReaction react) {
if (react == null) {
detach();
return;
}
TLRPC.Document document = null;
TLRPC.TL_availableReaction r = null;
if (react.emojicon != null) {
r = MediaDataController.getInstance(UserConfig.selectedAccount).getReactionsMap().get(react.emojicon);
}
if (r == null) {
document = AnimatedEmojiDrawable.findDocument(UserConfig.selectedAccount, react.documentId);
if (document != null) {
String emojicon = MessageObject.findAnimatedEmojiEmoticon(document, null);
if (emojicon != null) {
r = MediaDataController.getInstance(UserConfig.selectedAccount).getReactionsMap().get(emojicon);
}
}
}
if (document == null && r != null) {
ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setParentView(this);
imageReceiver.setUniqKeyPrefix(Integer.toString(animationUniq++));
imageReceiver.setImage(ImageLocation.getForDocument(r.around_animation), effectsSize + "_" + effectsSize + "_nolimit", null, "tgs", r, 1);
imageReceiver.setAutoRepeat(0);
imageReceiver.onAttachedToWindow();
animations.add(imageReceiver);
invalidate();
} else {
AnimatedEmojiDrawable drawable;
if (document == null) {
drawable = AnimatedEmojiDrawable.make(AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD, UserConfig.selectedAccount, react.documentId);
} else {
drawable = AnimatedEmojiDrawable.make(AnimatedEmojiDrawable.CACHE_TYPE_KEYBOARD, UserConfig.selectedAccount, document);
}
if (color != null) {
drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY));
}
AnimatedEmojiEffect effect = AnimatedEmojiEffect.createFrom(drawable, false, !drawable.canOverrideColor());
effect.setView(this);
animations.add(effect);
invalidate();
}
}
private Integer color;
public void setColor(int color) {
this.color = color;
final ColorFilter colorFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY);
for (int i = 0; i < animations.size(); ++i) {
Object animation = animations.get(i);
if (animation instanceof ImageReceiver) {
((ImageReceiver) animation).setColorFilter(colorFilter);
} else if (animation instanceof AnimatedEmojiEffect) {
((AnimatedEmojiEffect) animation).animatedEmojiDrawable.setColorFilter(colorFilter);
}
}
}
}
public void animateStateChange(long documentId) {
animatedStatus.animateChange(ReactionsLayoutInBubble.VisibleReaction.fromCustomEmoji(documentId));
updateRightDrawable = true;
}
public void getEmojiStatusLocation(Rect rect) {
if (nameTextView.getRightDrawable() == null) {
rect.set(nameTextView.getWidth() - 1, nameTextView.getHeight() / 2 - 1, nameTextView.getWidth() + 1, nameTextView.getHeight() / 2 + 1);
return;
}
rect.set(nameTextView.getRightDrawable().getBounds());
rect.offset((int) nameTextView.getX(), (int) nameTextView.getY());
animatedStatus.translate(rect.centerX(), rect.centerY());
}
private void switchTheme(Theme.ThemeInfo themeInfo, boolean toDark) {
@ -299,12 +510,30 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
super.onAttachedToWindow();
updateColors();
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){
NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
}
if (lastAccount >= 0) {
NotificationCenter.getInstance(lastAccount).removeObserver(this, NotificationCenter.userEmojiStatusUpdated);
NotificationCenter.getInstance(lastAccount).removeObserver(this, NotificationCenter.updateInterfaces);
lastAccount = -1;
}
if (nameTextView.getRightDrawable() instanceof AnimatedEmojiDrawable.WrapSizeDrawable) {
Drawable drawable = ((AnimatedEmojiDrawable.WrapSizeDrawable) nameTextView.getRightDrawable()).getDrawable();
if (drawable instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawable).removeView(nameTextView);
}
}
}
@Override
@ -476,8 +705,22 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
setArrowState(animated);
}
private int lastAccount = -1;
private TLRPC.User lastUser = null;
private Drawable premiumStar = null;
// called by onBindViewHolder
public void setUser(TLRPC.User user, boolean accounts) {
int account = UserConfig.selectedAccount;
if (account != lastAccount) {
if (lastAccount >= 0) {
NotificationCenter.getInstance(lastAccount).removeObserver(this, NotificationCenter.userEmojiStatusUpdated);
NotificationCenter.getInstance(lastAccount).removeObserver(this, NotificationCenter.updateInterfaces);
}
NotificationCenter.getInstance(lastAccount = account).addObserver(this, NotificationCenter.userEmojiStatusUpdated);
NotificationCenter.getInstance(lastAccount = account).addObserver(this, NotificationCenter.updateInterfaces);
}
lastUser = user;
if (user == null) {
return;
}
@ -489,15 +732,33 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
text = Emoji.replaceEmoji(text, nameTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(22), false);
} catch (Exception ignore) {}
drawPremium = user.premium;
// NekoX: test during merge, official value: false
if (text != null && drawPremium) {
SpannableStringBuilder spannableStringBuilder = SpannableStringBuilder.valueOf(text);
spannableStringBuilder.append(" d");
spannableStringBuilder.setSpan(new ColoredImageSpan(ContextCompat.getDrawable(getContext(), R.drawable.msg_premium_liststar)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0);
text = spannableStringBuilder;
}
drawPremium = false;//user.premium;
nameTextView.setText(text);
if (user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
animatedStatus.animate().alpha(1).setDuration(200).start();
nameTextView.setDrawablePadding(AndroidUtilities.dp(4));
status.set(((TLRPC.TL_emojiStatusUntil) user.emoji_status).document_id, true);
} else if (user.emoji_status instanceof TLRPC.TL_emojiStatus) {
animatedStatus.animate().alpha(1).setDuration(200).start();
nameTextView.setDrawablePadding(AndroidUtilities.dp(4));
status.set(((TLRPC.TL_emojiStatus) user.emoji_status).document_id, true);
} else if (user.premium) {
animatedStatus.animate().alpha(1).setDuration(200).start();
nameTextView.setDrawablePadding(AndroidUtilities.dp(4));
if (premiumStar == null) {
premiumStar = getResources().getDrawable(R.drawable.msg_premium_liststar).mutate();
}
premiumStar.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_menuPhoneCats), PorterDuff.Mode.MULTIPLY));
status.set(premiumStar, true);
} else {
animatedStatus.animateChange(null);
animatedStatus.animate().alpha(0).setDuration(200).start();
status.set((Drawable) null, true);
}
animatedStatus.setColor(Theme.getColor(Theme.isCurrentThemeDark() ? Theme.key_chats_verifiedBackground : Theme.key_chats_menuPhoneCats));
status.setColor(Theme.getColor(Theme.isCurrentThemeDark() ? Theme.key_chats_verifiedBackground : Theme.key_chats_menuPhoneCats));
// NekoX: hidePhone
if (!NekoConfig.hidePhone.Bool()) {
phoneTextView.setText(PhoneFormat.getInstance().format("+" + user.phone));
} else if (!TextUtils.isEmpty(user.username)) {
@ -529,7 +790,7 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
}
applyBackground(true);
updateRightDrawable = true;
}
public String applyBackground(boolean force) {
@ -546,6 +807,12 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
if (snowflakesEffect != null) {
snowflakesEffect.updateColors();
}
if (animatedStatus != null) {
animatedStatus.setColor(Theme.getColor(Theme.isCurrentThemeDark() ? Theme.key_chats_verifiedBackground : Theme.key_chats_menuPhoneCats));
}
if (status != null) {
status.setColor(Theme.getColor(Theme.isCurrentThemeDark() ? Theme.key_chats_verifiedBackground : Theme.key_chats_menuPhoneCats));
}
}
private void setArrowState(boolean animated) {
@ -568,6 +835,18 @@ public class DrawerProfileCell extends FrameLayout implements NotificationCenter
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.emojiLoaded) {
nameTextView.invalidate();
} else if (id == NotificationCenter.userEmojiStatusUpdated) {
setUser((TLRPC.User) args[0], accountsShown);
} else if (id == NotificationCenter.currentUserPremiumStatusChanged || id == NotificationCenter.updateInterfaces) {
setUser(UserConfig.getInstance(UserConfig.selectedAccount).getCurrentUser(), accountsShown);
}
}
public AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable getEmojiStatusDrawable() {
return status;
}
public View getEmojiStatusDrawableParent() {
return nameTextView;
}
}

View File

@ -11,6 +11,8 @@ package org.telegram.ui.Cells;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.view.Gravity;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@ -30,6 +32,7 @@ import org.telegram.messenger.UserObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.EmojiTextView;
@ -43,6 +46,7 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
private BackupImageView imageView;
private AvatarDrawable avatarDrawable;
private GroupCreateCheckBox checkBox;
private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable status;
private int accountNumber;
private RectF rect = new RectF();
@ -58,6 +62,7 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
addView(imageView, LayoutHelper.createFrame(36, 36, Gravity.LEFT | Gravity.TOP, 14, 6, 0, 0));
textView = new SimpleTextView(context);
textView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4));
textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText));
textView.setTextSize(15);
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
@ -65,6 +70,9 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 72, 0, 60, 0));
status = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(textView, AndroidUtilities.dp(20));
textView.setRightDrawable(status);
checkBox = new GroupCreateCheckBox(context);
checkBox.setChecked(true, false);
checkBox.setCheckScale(0.9f);
@ -86,6 +94,7 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText));
for (int i : SharedConfig.activeAccounts) {
NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.updateInterfaces);
}
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
}
@ -95,8 +104,16 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
super.onDetachedFromWindow();
for (int i : SharedConfig.activeAccounts) {
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged);
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.updateInterfaces);
}
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
if (textView.getRightDrawable() instanceof AnimatedEmojiDrawable.WrapSizeDrawable) {
Drawable drawable = ((AnimatedEmojiDrawable.WrapSizeDrawable) textView.getRightDrawable()).getDrawable();
if (drawable instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawable).removeView(textView);
}
}
}
@Override
@ -107,6 +124,10 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
}
} else if (id == NotificationCenter.emojiLoaded) {
textView.invalidate();
} else if (id == NotificationCenter.updateInterfaces) {
if (((int) args[0] & MessagesController.UPDATE_MASK_EMOJI_STATUS) > 0) {
setAccount(accountNumber);
}
}
}
@ -122,12 +143,19 @@ public class DrawerUserCell extends FrameLayout implements NotificationCenter.No
text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
} catch (Exception ignore) {}
textView.setText(text);
if (MessagesController.getInstance(account).isPremiumUser(user)) {
if (user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
textView.setDrawablePadding(AndroidUtilities.dp(4));
status.set(((TLRPC.TL_emojiStatusUntil) user.emoji_status).document_id, true);
} else if (user.emoji_status instanceof TLRPC.TL_emojiStatus) {
textView.setDrawablePadding(AndroidUtilities.dp(4));
status.set(((TLRPC.TL_emojiStatus) user.emoji_status).document_id, true);
} else if (MessagesController.getInstance(account).isPremiumUser(user)) {
textView.setDrawablePadding(AndroidUtilities.dp(6));
textView.setRightDrawable(PremiumGradient.getInstance().premiumStarDrawableMini);
status.set(PremiumGradient.getInstance().premiumStarDrawableMini, true);
} else {
textView.setRightDrawable(null);
status.set((Drawable) null, true);
}
status.setColor(Theme.getColor(Theme.key_chats_verifiedBackground));
imageView.getImageReceiver().setCurrentAccount(account);
imageView.setForUserOrChat(user, avatarDrawable);
checkBox.setVisibility(account == UserConfig.selectedAccount ? VISIBLE : INVISIBLE);

View File

@ -273,6 +273,7 @@ public class FeaturedStickerSetCell2 extends FrameLayout {
isLocked = !UserConfig.getInstance(currentAccount).isPremium() && MessageObject.isPremiumEmojiPack(set);
if (animated) {
if (isLocked) {
unlockButton.setVisibility(VISIBLE);
delButton.setVisibility(VISIBLE);
addButton.setVisibility(VISIBLE);
} else {
@ -300,13 +301,14 @@ public class FeaturedStickerSetCell2 extends FrameLayout {
if (isLocked) {
addButton.setVisibility(INVISIBLE);
delButton.setVisibility(INVISIBLE);
unlockButton.setVisibility(INVISIBLE);
unlockButton.setVisibility(VISIBLE);
} else {
if (isInstalled) {
addButton.setVisibility(INVISIBLE);
} else {
delButton.setVisibility(INVISIBLE);
}
unlockButton.setVisibility(GONE);
}
}
});
@ -327,7 +329,7 @@ public class FeaturedStickerSetCell2 extends FrameLayout {
delButton.setScaleX(0.0f);
delButton.setScaleY(0.0f);
} else {
unlockButton.setVisibility(INVISIBLE);
unlockButton.setVisibility(GONE);
unlockButton.setAlpha(0.0f);
unlockButton.setScaleX(0.0f);
unlockButton.setScaleY(0.0f);

View File

@ -23,6 +23,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
import org.telegram.messenger.AccountInstance;
@ -38,6 +39,7 @@ import org.telegram.messenger.voip.VoIPService;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.BlobDrawable;
@ -62,6 +64,10 @@ public class GroupCallUserCell extends FrameLayout {
private RLottieDrawable muteDrawable;
private RLottieDrawable shakeHandDrawable;
public AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable rightDrawable;
private Drawable verifiedDrawable;
private Drawable premiumDrawable;
private RadialProgressView avatarProgressView;
private AvatarDrawable avatarDrawable;
@ -287,6 +293,7 @@ public class GroupCallUserCell extends FrameLayout {
nameTextView.setDrawablePadding(AndroidUtilities.dp(6));
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 ? 54 : 67, 10, LocaleController.isRTL ? 67 : 54, 0));
rightDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(nameTextView, AndroidUtilities.dp(20), AnimatedEmojiDrawable.CACHE_TYPE_ALERT_EMOJI_STATUS);
speakingDrawable = context.getResources().getDrawable(R.drawable.voice_volume_mini);
speakingDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_voipgroup_speakingText), PorterDuff.Mode.MULTIPLY));
@ -460,7 +467,31 @@ public class GroupCallUserCell extends FrameLayout {
avatarDrawable.setInfo(currentUser);
nameTextView.setText(UserObject.getUserName(currentUser));
nameTextView.setRightDrawable(currentUser != null && currentUser.verifiedExtended() ? new VerifiedDrawable(getContext()) : null);
if (currentUser != null && currentUser.verifiedExtended()) {
rightDrawable.set(verifiedDrawable = (verifiedDrawable == null ? new VerifiedDrawable(getContext()) : verifiedDrawable), animated);
} else if (currentUser != null && currentUser.emoji_status instanceof TLRPC.TL_emojiStatus) {
rightDrawable.set(((TLRPC.TL_emojiStatus) currentUser.emoji_status).document_id, animated);
} else if (currentUser != null && currentUser.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
rightDrawable.set(((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).document_id, animated);
} else if (currentUser != null && currentUser.premium) {
if (premiumDrawable == null) {
premiumDrawable = getContext().getResources().getDrawable(R.drawable.msg_premium_liststar).mutate();
premiumDrawable = new AnimatedEmojiDrawable.WrapSizeDrawable(premiumDrawable, AndroidUtilities.dp(14), AndroidUtilities.dp(14)) {
@Override
public void draw(@NonNull Canvas canvas) {
canvas.save();
canvas.translate(AndroidUtilities.dp(-2), AndroidUtilities.dp(0));
super.draw(canvas);
canvas.restore();
}
};
}
rightDrawable.set(premiumDrawable, animated);
} else {
rightDrawable.set((Drawable) null, animated);
}
rightDrawable.setColor(Theme.getColor(Theme.key_premiumGradient1));
nameTextView.setRightDrawable(rightDrawable);
avatarImageView.getImageReceiver().setCurrentAccount(account.getCurrentAccount());
if (uploadingAvatar != null) {
hasAvatar = true;
@ -477,7 +508,11 @@ public class GroupCallUserCell extends FrameLayout {
if (currentChat != null) {
nameTextView.setText(currentChat.title);
nameTextView.setRightDrawable(currentChat.verifiedExtended() ? new VerifiedDrawable(getContext()) : null);
if (currentChat.verifiedExtended()) {
rightDrawable.set(verifiedDrawable = (verifiedDrawable == null ? new VerifiedDrawable(getContext()) : verifiedDrawable), animated);
} else {
rightDrawable.set((Drawable) null, animated);
}
avatarImageView.getImageReceiver().setCurrentAccount(account.getCurrentAccount());
if (uploadingAvatar != null) {
hasAvatar = true;

View File

@ -118,6 +118,7 @@ public class MentionCell extends LinearLayout {
}
public void setChat(TLRPC.Chat chat) {
resetEmojiSuggestion();
if (chat == null) {
nameTextView.setText("");
usernameTextView.setText("");
@ -155,9 +156,12 @@ public class MentionCell extends LinearLayout {
public void resetEmojiSuggestion() {
nameTextView.setPadding(0, 0, 0, 0);
if (emojiDrawable instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) emojiDrawable).removeView(this);
if (emojiDrawable != null) {
if (emojiDrawable instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) emojiDrawable).removeView(this);
}
emojiDrawable = null;
invalidate();
}
}

View File

@ -18,6 +18,8 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.NonNull;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ChatObject;
@ -35,8 +37,10 @@ import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.Premium.PremiumGradient;
import org.telegram.ui.NotificationsSettingsActivity;
@ -87,6 +91,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
private int statusLeft;
private StaticLayout statusLayout;
private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable statusDrawable;
private RectF rect = new RectF();
@ -109,6 +114,8 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
checkBox.setDrawUnchecked(false);
checkBox.setDrawBackgroundAsArc(3);
addView(checkBox);
statusDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, AndroidUtilities.dp(20));
}
public void setData(TLObject object, TLRPC.EncryptedChat ec, CharSequence n, CharSequence s, boolean needCount, boolean saved) {
@ -267,6 +274,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
nameLeft = AndroidUtilities.dp(11);
}
nameLockTop = AndroidUtilities.dp(22.0f);
updateStatus(false, null, false);
} else {
if (chat != null) {
dialog_id = -chat.id;
@ -276,6 +284,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
} else {
nameLeft = AndroidUtilities.dp(11);
}
updateStatus(drawCheck, null, false);
} else if (user != null) {
dialog_id = user.id;
if (!LocaleController.isRTL) {
@ -286,6 +295,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
nameLockTop = AndroidUtilities.dp(21);
drawCheck = user.verifiedExtended();
drawPremium = !user.self && MessagesController.getInstance(currentAccount).isPremiumUser(user);
updateStatus(drawCheck, user, false);
}
}
@ -490,6 +500,25 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
nameLockLeft += getPaddingLeft();
}
public void updateStatus(boolean verified, TLRPC.User user, boolean animated) {
if (verified) {
statusDrawable.set(new CombinedDrawable(Theme.dialogs_verifiedDrawable, Theme.dialogs_verifiedCheckDrawable, 0, 0), animated);
statusDrawable.setColor(null);
} else if (user != null && !user.self && user.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) user.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
statusDrawable.set(((TLRPC.TL_emojiStatusUntil) user.emoji_status).document_id, animated);
statusDrawable.setColor(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider));
} else if (user != null && !user.self && user.emoji_status instanceof TLRPC.TL_emojiStatus) {
statusDrawable.set(((TLRPC.TL_emojiStatus) user.emoji_status).document_id, animated);
statusDrawable.setColor(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider));
} else if (user != null && !user.self && MessagesController.getInstance(currentAccount).isPremiumUser(user)) {
statusDrawable.set(PremiumGradient.getInstance().premiumStarDrawableMini, animated);
statusDrawable.setColor(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider));
} else {
statusDrawable.set((Drawable) null, animated);
statusDrawable.setColor(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider));
}
}
public void update(int mask) {
TLRPC.FileLocation photo = null;
if (user != null) {
@ -541,6 +570,9 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
continueUpdate = true;
}
}
if (!continueUpdate && (mask & MessagesController.UPDATE_MASK_EMOJI_STATUS) != 0 && user != null) {
updateStatus(user.verified, user, true);
}
if (!continueUpdate && ((mask & MessagesController.UPDATE_MASK_NAME) != 0 && user != null) || (mask & MessagesController.UPDATE_MASK_CHAT_NAME) != 0 && chat != null) {
String newName;
if (user != null) {
@ -609,29 +641,20 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No
canvas.translate(nameLeft, nameTop);
nameLayout.draw(canvas);
canvas.restore();
if (drawCheck || drawPremium) {
int x;
Drawable drawable = drawCheck ? Theme.dialogs_verifiedDrawable : PremiumGradient.getInstance().premiumStarDrawableMini;
if (LocaleController.isRTL) {
if (nameLayout.getLineLeft(0) == 0) {
x = nameLeft - AndroidUtilities.dp(6) - drawable.getIntrinsicWidth();
} else {
float w = nameLayout.getLineWidth(0);
x = (int) (nameLeft + nameWidth - Math.ceil(w) - AndroidUtilities.dp(6) - drawable.getIntrinsicWidth());
}
int x;
if (LocaleController.isRTL) {
if (nameLayout.getLineLeft(0) == 0) {
x = nameLeft - AndroidUtilities.dp(6) - statusDrawable.getIntrinsicWidth();
} else {
x = (int) (nameLeft + nameLayout.getLineRight(0) + AndroidUtilities.dp(6));
}
if (drawCheck) {
setDrawableBounds(Theme.dialogs_verifiedDrawable, x, nameTop + AndroidUtilities.dp(3));
setDrawableBounds(Theme.dialogs_verifiedCheckDrawable, x, nameTop + AndroidUtilities.dp(3));
Theme.dialogs_verifiedDrawable.draw(canvas);
Theme.dialogs_verifiedCheckDrawable.draw(canvas);
} else if (drawPremium) {
setDrawableBounds(drawable, x, nameTop + AndroidUtilities.dp(1.5f));
drawable.draw(canvas);
float w = nameLayout.getLineWidth(0);
x = (int) (nameLeft + nameWidth - Math.ceil(w) - AndroidUtilities.dp(6) - statusDrawable.getIntrinsicWidth());
}
} else {
x = (int) (nameLeft + nameLayout.getLineRight(0) + AndroidUtilities.dp(6));
}
setDrawableBounds(statusDrawable, x, nameTop + (nameLayout.getHeight() - statusDrawable.getIntrinsicHeight()) / 2f);
statusDrawable.draw(canvas);
}
if (statusLayout != null) {

View File

@ -4,9 +4,6 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.text.Layout;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
@ -16,10 +13,7 @@ import android.view.Gravity;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.widget.FrameLayout;
import org.telegram.messenger.AndroidUtilities;
@ -35,7 +29,7 @@ import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.CheckBox2;
@ -46,8 +40,6 @@ import org.telegram.ui.Components.MediaActionDrawable;
import org.telegram.ui.Components.RadialProgress2;
import org.telegram.ui.FilteredSearchView;
import java.util.Locale;
public class SharedAudioCell extends FrameLayout implements DownloadController.FileDownloadProgressListener, NotificationCenter.NotificationCenterDelegate {
private SpannableStringBuilder dotSpan;
@ -91,6 +83,9 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
private TextPaint captionTextPaint;
private final Theme.ResourcesProvider resourcesProvider;
boolean showReorderIcon;
float showReorderIconProgress;
public SharedAudioCell(Context context) {
this(context, VIEW_TYPE_DEFAULT, null);
}
@ -343,7 +338,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
if (miniButtonState == 0) {
miniButtonState = 1;
radialProgress.setProgress(0, false);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, 1, 0);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, FileLoader.PRIORITY_NORMAL, 0);
radialProgress.setMiniIcon(getMiniIconForCurrentState(), false, true);
invalidate();
} else if (miniButtonState == 1) {
@ -361,7 +356,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
if (buttonState == 0) {
if (miniButtonState == 0) {
currentMessageObject.putInDownloadsStore = true;
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, 1, 0);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, FileLoader.PRIORITY_NORMAL, 0);
}
if (needPlayMessage(currentMessageObject)) {
if (hasMiniProgress == 2 && miniButtonState != 1) {
@ -383,7 +378,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
} else if (buttonState == 2) {
radialProgress.setProgress(0, false);
currentMessageObject.putInDownloadsStore = true;
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, 1, 0);
FileLoader.getInstance(currentAccount).loadFile(currentMessageObject.getDocument(), currentMessageObject, FileLoader.PRIORITY_NORMAL, 0);
buttonState = 4;
radialProgress.setIcon(getIconForCurrentState(), false, true);
invalidate();
@ -574,11 +569,37 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
canvas.saveLayerAlpha(0, 0, getMeasuredWidth(), getMeasuredHeight(), (int) (enterAlpha * 255), Canvas.ALL_SAVE_FLAG);
drawInternal(canvas);
super.dispatchDraw(canvas);
drawReorder(canvas);
canvas.restore();
} else {
drawInternal(canvas);
drawReorder(canvas);
super.dispatchDraw(canvas);
}
}
private void drawReorder(Canvas canvas) {
if (showReorderIcon || showReorderIconProgress != 0) {
if (showReorderIcon && showReorderIconProgress != 1f) {
showReorderIconProgress += 16 /150f;
invalidate();
} else if (!showReorderIcon && showReorderIconProgress != 0) {
showReorderIconProgress -= 16 /150f;
invalidate();
}
showReorderIconProgress = Utilities.clamp(showReorderIconProgress, 1f, 0);
int x = getMeasuredWidth() - AndroidUtilities.dp(12) - Theme.dialogs_reorderDrawable.getIntrinsicWidth();
int y = (getMeasuredHeight() - Theme.dialogs_reorderDrawable.getIntrinsicHeight()) >> 1;
canvas.save();
canvas.scale(showReorderIconProgress, showReorderIconProgress, x + Theme.dialogs_reorderDrawable.getIntrinsicWidth() / 2f, y + Theme.dialogs_reorderDrawable.getIntrinsicHeight() / 2f);
Theme.dialogs_reorderDrawable.setBounds(x, y, x + Theme.dialogs_reorderDrawable.getIntrinsicWidth(), y + Theme.dialogs_reorderDrawable.getIntrinsicHeight());
Theme.dialogs_reorderDrawable.draw(canvas);
canvas.restore();
}
}
private void drawInternal(Canvas canvas) {
@ -629,5 +650,17 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
invalidate();
}
}
public void showReorderIcon(boolean show, boolean animated) {
if (showReorderIcon == show) {
return;
}
showReorderIcon = show;
if (!animated) {
showReorderIconProgress = show ? 1f : 0;
}
invalidate();
}
}

View File

@ -39,6 +39,7 @@ import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.BackupImageView;
@ -92,6 +93,8 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
private final Theme.ResourcesProvider resourcesProvider;
FlickerLoadingView globalGradientView;
private long downloadedSize;
boolean showReorderIcon;
float showReorderIconProgress;
public SharedDocumentCell(Context context) {
this(context, VIEW_TYPE_DEFAULT);
@ -631,9 +634,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (viewType != VIEW_TYPE_PICKER && ((nameTextView.getLineCount() > 1 || (captionTextView != null && captionTextView.getVisibility() == View.VISIBLE))))
;
{
if (viewType != VIEW_TYPE_PICKER && ((nameTextView.getLineCount() > 1 || (captionTextView != null && captionTextView.getVisibility() == View.VISIBLE)))) {
int y = nameTextView.getMeasuredHeight() - AndroidUtilities.dp(22);
if (captionTextView != null && captionTextView.getVisibility() == View.VISIBLE) {
captionTextView.layout(captionTextView.getLeft(), y + captionTextView.getTop(), captionTextView.getRight(), y + captionTextView.getBottom());
@ -718,6 +719,26 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
super.dispatchDraw(canvas);
drawDivider(canvas);
}
if (showReorderIcon || showReorderIconProgress != 0) {
if (showReorderIcon && showReorderIconProgress != 1f) {
showReorderIconProgress += 16 /150f;
invalidate();
} else if (!showReorderIcon && showReorderIconProgress != 0) {
showReorderIconProgress -= 16 /150f;
invalidate();
}
showReorderIconProgress = Utilities.clamp(showReorderIconProgress, 1f, 0);
int x = getMeasuredWidth() - AndroidUtilities.dp(12) - Theme.dialogs_reorderDrawable.getIntrinsicWidth();
int y = (getMeasuredHeight() - Theme.dialogs_reorderDrawable.getIntrinsicHeight()) >> 1;
canvas.save();
canvas.scale(showReorderIconProgress, showReorderIconProgress, x + Theme.dialogs_reorderDrawable.getIntrinsicWidth() / 2f, y + Theme.dialogs_reorderDrawable.getIntrinsicHeight() / 2f);
Theme.dialogs_reorderDrawable.setBounds(x, y, x + Theme.dialogs_reorderDrawable.getIntrinsicWidth(), y + Theme.dialogs_reorderDrawable.getIntrinsicHeight());
Theme.dialogs_reorderDrawable.draw(canvas);
canvas.restore();
}
}
private void drawDivider(Canvas canvas) {
@ -732,4 +753,15 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
invalidate();
}
}
public void showReorderIcon(boolean show, boolean animated) {
if (showReorderIcon == show) {
return;
}
showReorderIcon = show;
if (!animated) {
showReorderIconProgress = show ? 1f : 0;
}
invalidate();
}
}

View File

@ -135,7 +135,7 @@ public class SharedPhotoVideoCell2 extends View {
showImageStub = true;
}
}
} else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageObject.messageOwner.media.photo != null && !messageObject.photoThumbs.isEmpty()) {
} else if (MessageObject.getMedia(messageObject.messageOwner) instanceof TLRPC.TL_messageMediaPhoto && MessageObject.getMedia(messageObject.messageOwner).photo != null && !messageObject.photoThumbs.isEmpty()) {
if (messageObject.mediaExists || canAutoDownload(messageObject)) {
if (messageObject.mediaThumb != null) {
if (messageObject.strippedThumb != null) {

View File

@ -237,7 +237,8 @@ public class StickerEmojiCell extends FrameLayout implements NotificationCenter.
if (!UserConfig.getInstance(currentAccount).isPremium()) {
layoutParams.height = layoutParams.width = AndroidUtilities.dp(24);
layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
layoutParams.bottomMargin = layoutParams.rightMargin = 0;
layoutParams.rightMargin = 0;
layoutParams.bottomMargin = AndroidUtilities.dp(8);
premiumIconView.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4));
} else {
layoutParams.height = layoutParams.width = AndroidUtilities.dp(16);

View File

@ -326,7 +326,17 @@ public class StickerSetCell extends FrameLayout {
if (documents != null && !documents.isEmpty()) {
valueTextView.setText(LocaleController.formatPluralString(emojis ? "EmojiCount" : "Stickers", documents.size()));
TLRPC.Document sticker = documents.get(0);
TLRPC.Document sticker = null;
for (int i = 0; i < documents.size(); ++i) {
TLRPC.Document d = documents.get(i);
if (d != null && d.id == set.set.thumb_document_id) {
sticker = d;
break;
}
}
if (sticker == null) {
sticker = documents.get(0);
}
TLObject object = FileLoader.getClosestPhotoSizeWithSize(set.set.thumbs, 90);
if (object == null) {
object = sticker;

View File

@ -27,6 +27,7 @@ import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AnimatedTextView;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.CubicBezierInterpolator;
@ -337,4 +338,12 @@ public class TextSettingsCell extends FrameLayout {
}
return valueBackupImageView;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (valueBackupImageView != null && valueBackupImageView.getImageReceiver() != null && valueBackupImageView.getImageReceiver().getDrawable() instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) valueBackupImageView.getImageReceiver().getDrawable()).removeView(this);
}
}
}

View File

@ -32,6 +32,7 @@ import org.telegram.ui.Components.BackgroundGradientDrawable;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.MotionBackgroundDrawable;
import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay;
import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble;
public class ThemePreviewMessagesCell extends LinearLayout {
@ -190,12 +191,12 @@ public class ThemePreviewMessagesCell extends LinearLayout {
private GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
boolean added = getMessageObject().selectReaction(MediaDataController.getInstance(currentAccount).getDoubleTapReaction(), false, false);
boolean added = getMessageObject().selectReaction(ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(MediaDataController.getInstance(currentAccount).getDoubleTapReaction()), false, false);
setMessageObject(getMessageObject(), null, false, false);
requestLayout();
ReactionsEffectOverlay.removeCurrent(false);
if (added) {
ReactionsEffectOverlay.show(fragment, null, cells[1], e.getX(), e.getY(), MediaDataController.getInstance(currentAccount).getDoubleTapReaction(), currentAccount, ReactionsEffectOverlay.LONG_ANIMATION);
ReactionsEffectOverlay.show(fragment, null, cells[1], null, e.getX(), e.getY(), ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(MediaDataController.getInstance(currentAccount).getDoubleTapReaction()), currentAccount, ReactionsEffectOverlay.LONG_ANIMATION);
ReactionsEffectOverlay.startAnimation();
}
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

View File

@ -32,6 +32,10 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Button;
import android.widget.FrameLayout;
import androidx.annotation.Keep;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.FileLoader;
@ -352,7 +356,7 @@ public class ThemesHorizontalListCell extends RecyclerListView implements Notifi
String name = FileLoader.getAttachFileName(wallPaper.document);
if (!loadingThemes.containsKey(name)) {
loadingThemes.put(name, themeInfo);
FileLoader.getInstance(themeInfo.account).loadFile(wallPaper.document, wallPaper, 1, 1);
FileLoader.getInstance(themeInfo.account).loadFile(wallPaper.document, wallPaper, FileLoader.PRIORITY_NORMAL, 1);
}
} else {
themeInfo.badWallpaper = true;
@ -442,7 +446,7 @@ public class ThemesHorizontalListCell extends RecyclerListView implements Notifi
String name = FileLoader.getAttachFileName(themeInfo.info.document);
if (!loadingThemes.containsKey(name)) {
loadingThemes.put(name, themeInfo);
FileLoader.getInstance(themeInfo.account).loadFile(themeInfo.info.document, themeInfo.info, 1, 1);
FileLoader.getInstance(themeInfo.account).loadFile(themeInfo.info.document, themeInfo.info, FileLoader.PRIORITY_NORMAL, 1);
}
}
} else {

View File

@ -13,6 +13,7 @@ import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.accessibility.AccessibilityNodeInfo;
@ -20,6 +21,8 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji;
import org.telegram.messenger.DialogObject;
@ -34,6 +37,7 @@ import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
import org.telegram.ui.Components.AvatarDrawable;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.CheckBox;
@ -52,6 +56,8 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica
private CheckBoxSquare checkBoxBig;
private TextView adminTextView;
private TextView addButton;
private Drawable premiumDrawable;
private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emojiStatus;
private Theme.ResourcesProvider resourcesProvider;
private AvatarDrawable avatarDrawable;
@ -124,6 +130,8 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica
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 + (checkbox == 2 ? 18 : 0) + additionalPadding : (64 + padding), 10, LocaleController.isRTL ? (64 + padding) : 28 + (checkbox == 2 ? 18 : 0) + additionalPadding, 0));
emojiStatus = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(nameTextView, AndroidUtilities.dp(20));
statusTextView = new SimpleTextView(context);
statusTextView.setTextSize(15);
statusTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
@ -474,7 +482,30 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica
nameTextView.setText(name);
}
if (currentUser != null && MessagesController.getInstance(currentAccount).isPremiumUser(currentUser)) {
nameTextView.setRightDrawable(PremiumGradient.getInstance().premiumStarDrawableMini);
if (currentUser.emoji_status instanceof TLRPC.TL_emojiStatusUntil && ((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).until > (int) (System.currentTimeMillis() / 1000)) {
emojiStatus.set(((TLRPC.TL_emojiStatusUntil) currentUser.emoji_status).document_id, false);
emojiStatus.setColor(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider));
nameTextView.setRightDrawable(emojiStatus);
} else if (currentUser.emoji_status instanceof TLRPC.TL_emojiStatus) {
emojiStatus.set(((TLRPC.TL_emojiStatus) currentUser.emoji_status).document_id, false);
emojiStatus.setColor(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider));
nameTextView.setRightDrawable(emojiStatus);
} else {
if (premiumDrawable == null) {
premiumDrawable = getContext().getResources().getDrawable(R.drawable.msg_premium_liststar).mutate();
premiumDrawable = new AnimatedEmojiDrawable.WrapSizeDrawable(premiumDrawable, AndroidUtilities.dp(14), AndroidUtilities.dp(14)) {
@Override
public void draw(@NonNull Canvas canvas) {
canvas.save();
canvas.translate(0, AndroidUtilities.dp(1));
super.draw(canvas);
canvas.restore();
}
};
premiumDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider), PorterDuff.Mode.MULTIPLY));
}
nameTextView.setRightDrawable(premiumDrawable);
}
nameTextView.setRightDrawableTopPadding(-AndroidUtilities.dp(0.5f));
} else {
nameTextView.setRightDrawable(null);
@ -563,11 +594,13 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica
protected void onAttachedToWindow() {
super.onAttachedToWindow();
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
emojiStatus.attach();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded);
emojiStatus.detach();
}
}

View File

@ -2167,7 +2167,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
MessageObject messageObject = cell.getMessageObject();
if (url instanceof URLSpanMono) {
((URLSpanMono) url).copyToClipboard();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (AndroidUtilities.shouldShowClipboardToast()) {
Toast.makeText(getParentActivity(), LocaleController.getString("TextCopied", R.string.TextCopied), Toast.LENGTH_SHORT).show();
}
} else if (url instanceof URLSpanUserMention) {
@ -2240,7 +2240,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
@Override
public void needOpenWebView(MessageObject message, String url, String title, String description, String originalUrl, int w, int h) {
EmbedBottomSheet.show(getParentActivity(), message, provider, title, description, originalUrl, url, w, h, false);
EmbedBottomSheet.show(ChannelAdminLogActivity.this, message, provider, title, description, originalUrl, url, w, h, false);
}
@Override
@ -2259,7 +2259,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
if (message.getInputStickerSet() != null) {
showDialog(new StickersAlert(getParentActivity(), ChannelAdminLogActivity.this, message.getInputStickerSet(), null, null));
} else if (message.isVideo() || message.type == 1 || message.type == 0 && !message.isWebpageDocument() || message.isGif()) {
PhotoViewer.getInstance().setParentActivity(getParentActivity());
PhotoViewer.getInstance().setParentActivity(ChannelAdminLogActivity.this);
PhotoViewer.getInstance().openPhoto(message, null, 0, 0, provider);
} else if (message.type == 3) {
try {
@ -2365,7 +2365,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
@Override
public void didClickImage(ChatActionCell cell) {
MessageObject message = cell.getMessageObject();
PhotoViewer.getInstance().setParentActivity(getParentActivity());
PhotoViewer.getInstance().setParentActivity(ChannelAdminLogActivity.this);
TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs, 640);
if (photoSize != null) {
ImageLocation imageLocation = ImageLocation.getForPhoto(photoSize, message.messageOwner.action.photo);

View File

@ -584,8 +584,8 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
avatarEditor.setAnimation(cameraDrawable);
avatarEditor.setEnabled(false);
avatarEditor.setClickable(false);
avatarEditor.setPadding(AndroidUtilities.dp(2), 0, 0, AndroidUtilities.dp(1));
frameLayout.addView(avatarEditor, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 16, 12, LocaleController.isRTL ? 16 : 0, 12));
avatarEditor.setPadding(AndroidUtilities.dp(0), 0, 0, AndroidUtilities.dp(1));
frameLayout.addView(avatarEditor, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 15, 12, LocaleController.isRTL ? 15 : 0, 12));
avatarProgressView = new RadialProgressView(context);
avatarProgressView.setSize(AndroidUtilities.dp(30));

File diff suppressed because it is too large Load Diff

View File

@ -72,8 +72,6 @@ import org.telegram.ui.Components.SizeNotifierFrameLayout;
import org.telegram.ui.Components.UndoView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import tw.nekomimi.nekogram.utils.VibrateUtil;
@ -136,7 +134,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
private boolean isChannel;
private boolean historyHidden;
private List<String> availableReactions = Collections.emptyList();
private TLRPC.ChatReactions availableReactions;
private boolean createAfterUpload;
private boolean donePressed;
@ -530,7 +528,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
}
TLRPC.Chat chat = getMessagesController().getChat(chatId);
if (chat.photo != null && chat.photo.photo_big != null) {
PhotoViewer.getInstance().setParentActivity(getParentActivity());
PhotoViewer.getInstance().setParentActivity(ChatEditActivity.this);
if (chat.photo.dc_id != 0) {
chat.photo.photo_big.dc_id = chat.photo.dc_id;
}
@ -1530,16 +1528,31 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
}
private void updateReactionsCell() {
int count = 0;
for (int i = 0; i < availableReactions.size(); i++) {
TLRPC.TL_availableReaction reaction = getMediaDataController().getReactionsMap().get(availableReactions.get(i));
if (reaction != null && !reaction.inactive) {
count++;
String finalString;
if (availableReactions == null || availableReactions instanceof TLRPC.TL_chatReactionsNone) {
finalString = LocaleController.getString("ReactionsOff", R.string.ReactionsOff);
} else if (availableReactions instanceof TLRPC.TL_chatReactionsSome) {
TLRPC.TL_chatReactionsSome someReactions = (TLRPC.TL_chatReactionsSome) availableReactions;
int count = 0;
for (int i = 0; i < someReactions.reactions.size(); i++) {
TLRPC.Reaction someReaction = someReactions.reactions.get(i);
if (someReaction instanceof TLRPC.TL_reactionEmoji) {
TLRPC.TL_reactionEmoji tl_reactionEmoji = (TLRPC.TL_reactionEmoji) someReaction;
TLRPC.TL_availableReaction reaction = getMediaDataController().getReactionsMap().get(tl_reactionEmoji.emoticon);
if (reaction != null && !reaction.inactive) {
count++;
}
}
}
int reacts = Math.min(getMediaDataController().getEnabledReactionsList().size(), count);
finalString = reacts == 0 ? LocaleController.getString("ReactionsOff", R.string.ReactionsOff) :
LocaleController.formatString("ReactionsCount", R.string.ReactionsCount, reacts, getMediaDataController().getEnabledReactionsList().size());
} else {
finalString = LocaleController.getString("ReactionsAll", R.string.ReactionsAll);
}
int reacts = Math.min(getMediaDataController().getEnabledReactionsList().size(), count);
reactionsCell.setTextAndValue(LocaleController.getString("Reactions", R.string.Reactions), reacts == 0 ? LocaleController.getString("ReactionsOff", R.string.ReactionsOff) :
LocaleController.formatString("ReactionsCount", R.string.ReactionsCount, reacts, getMediaDataController().getEnabledReactionsList().size()), true);
reactionsCell.setTextAndValue(LocaleController.getString("Reactions", R.string.Reactions), finalString, true);
}
@Override

View File

@ -5,6 +5,7 @@ import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
@ -24,6 +25,7 @@ import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.AvailableReactionCell;
import org.telegram.ui.Cells.HeaderCell;
import org.telegram.ui.Cells.RadioCell;
import org.telegram.ui.Cells.TextCheckCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Components.LayoutHelper;
@ -35,7 +37,7 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
public class ChatReactionsEditActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
private final static int TYPE_INFO = 0, TYPE_HEADER = 1, TYPE_REACTION = 2;
private final static int TYPE_INFO = 0, TYPE_HEADER = 1, TYPE_REACTION = 2, TYPE_CONTROLS_CONTAINER = 3;
public final static String KEY_CHAT_ID = "chat_id";
@ -51,6 +53,17 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
private TextCheckCell enableReactionsCell;
private ArrayList<TLRPC.TL_availableReaction> availableReactions = new ArrayList();
LinearLayout contorlsLayout;
public final static int SELECT_TYPE_NONE = 2, SELECT_TYPE_SOME = 1, SELECT_TYPE_ALL = 0;
int selectedType = -1;
int startFromType;
private RadioCell allReactions;
private RadioCell someReactions;
private RadioCell disableReactions;
ArrayList<RadioCell> radioCells = new ArrayList();
boolean isChannel;
public ChatReactionsEditActivity(Bundle args) {
super(args);
@ -81,6 +94,8 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
@Override
public View createView(Context context) {
isChannel = ChatObject.isChannelAndNotMegaGroup(chatId, currentAccount);
actionBar.setTitle(LocaleController.getString("Reactions", R.string.Reactions));
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
@ -99,15 +114,49 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
availableReactions.addAll(getMediaDataController().getEnabledReactionsList());
enableReactionsCell = new TextCheckCell(context);
enableReactionsCell.setHeight(56);
enableReactionsCell.setTextAndCheck(LocaleController.getString("EnableReactions", R.string.EnableReactions), !chatReactions.isEmpty(), false);
enableReactionsCell.setBackgroundColor(Theme.getColor(enableReactionsCell.isChecked() ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked));
enableReactionsCell.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
enableReactionsCell.setOnClickListener(v -> {
setCheckedEnableReactionCell(!enableReactionsCell.isChecked());
});
ll.addView(enableReactionsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
if (isChannel) {
enableReactionsCell = new TextCheckCell(context);
enableReactionsCell.setHeight(56);
enableReactionsCell.setTextAndCheck(LocaleController.getString("EnableReactions", R.string.EnableReactions), !chatReactions.isEmpty(), false);
enableReactionsCell.setBackgroundColor(Theme.getColor(enableReactionsCell.isChecked() ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked));
enableReactionsCell.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
enableReactionsCell.setOnClickListener(v -> {
setCheckedEnableReactionCell(enableReactionsCell.isChecked() ? SELECT_TYPE_NONE : SELECT_TYPE_SOME, true);
});
ll.addView(enableReactionsCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
}
HeaderCell headerCell = new HeaderCell(context);
headerCell.setText(LocaleController.getString("AvailableReactions", R.string.AvailableReactions));
contorlsLayout = new LinearLayout(context);
contorlsLayout.setOrientation(LinearLayout.VERTICAL);
allReactions = new RadioCell(context);
allReactions.setText(LocaleController.getString("AllReactions", R.string.AllReactions), false, true);
someReactions = new RadioCell(context);
someReactions.setText(LocaleController.getString("SomeReactions", R.string.SomeReactions), false, true);
disableReactions = new RadioCell(context);
disableReactions.setText(LocaleController.getString("NoReactions", R.string.NoReactions), false, false);
contorlsLayout.addView(headerCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
contorlsLayout.addView(allReactions, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
contorlsLayout.addView(someReactions, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
contorlsLayout.addView(disableReactions, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
radioCells.clear();
radioCells.add(allReactions);
radioCells.add(someReactions);
radioCells.add(disableReactions);
allReactions.setOnClickListener(v -> AndroidUtilities.runOnUIThread(() -> setCheckedEnableReactionCell(SELECT_TYPE_ALL, true)));
someReactions.setOnClickListener(v -> AndroidUtilities.runOnUIThread(() -> setCheckedEnableReactionCell(SELECT_TYPE_SOME, true)));
disableReactions.setOnClickListener(v -> AndroidUtilities.runOnUIThread(() -> setCheckedEnableReactionCell(SELECT_TYPE_NONE, true)));
headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
allReactions.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_windowBackgroundWhite), Theme.getColor(Theme.key_listSelector)));
someReactions.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_windowBackgroundWhite), Theme.getColor(Theme.key_listSelector)));
disableReactions.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_windowBackgroundWhite), Theme.getColor(Theme.key_listSelector)));
setCheckedEnableReactionCell(startFromType, false);
listView = new RecyclerListView(context);
listView.setLayoutManager(new LinearLayoutManager(context));
@ -127,6 +176,16 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
case TYPE_HEADER: {
return new RecyclerListView.Holder(new HeaderCell(context, 23));
}
case TYPE_CONTROLS_CONTAINER:
FrameLayout frameLayout = new FrameLayout(context);
if (contorlsLayout.getParent() != null) {
((ViewGroup) contorlsLayout.getParent()).removeView(contorlsLayout);
}
frameLayout.addView(contorlsLayout);
frameLayout.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
return new RecyclerListView.Holder(frameLayout);
}
}
@ -136,17 +195,27 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
case TYPE_INFO:
TextInfoPrivacyCell infoCell = (TextInfoPrivacyCell) holder.itemView;
infoCell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4));
infoCell.setText(ChatObject.isChannelAndNotMegaGroup(currentChat) ? LocaleController.getString("EnableReactionsChannelInfo", R.string.EnableReactionsChannelInfo) :
LocaleController.getString("EnableReactionsGroupInfo", R.string.EnableReactionsGroupInfo));
if (isChannel) {
infoCell.setText(ChatObject.isChannelAndNotMegaGroup(currentChat) ? LocaleController.getString("EnableReactionsChannelInfo", R.string.EnableReactionsChannelInfo) :
LocaleController.getString("EnableReactionsGroupInfo", R.string.EnableReactionsGroupInfo));
} else {
if (selectedType == SELECT_TYPE_SOME) {
infoCell.setText(LocaleController.getString("EnableSomeReactionsInfo", R.string.EnableSomeReactionsInfo));
} else if (selectedType == SELECT_TYPE_ALL) {
infoCell.setText(LocaleController.getString("EnableAllReactionsInfo", R.string.EnableAllReactionsInfo));
} else if (selectedType == SELECT_TYPE_NONE) {
infoCell.setText(LocaleController.getString("DisableReactionsInfo", R.string.DisableReactionsInfo));
}
}
break;
case TYPE_HEADER:
HeaderCell headerCell = (HeaderCell) holder.itemView;
headerCell.setText(LocaleController.getString("AvailableReactions", R.string.AvailableReactions));
headerCell.setText(LocaleController.getString("OnlyAllowThisReactions", R.string.OnlyAllowThisReactions));
headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
break;
case TYPE_REACTION:
AvailableReactionCell reactionCell = (AvailableReactionCell) holder.itemView;
TLRPC.TL_availableReaction react = availableReactions.get(position - 2);
TLRPC.TL_availableReaction react = availableReactions.get(position - (isChannel ? 2 : 3));
reactionCell.bind(react, chatReactions.contains(react.reaction), currentAccount);
break;
}
@ -154,26 +223,35 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
@Override
public int getItemCount() {
return 1 + (!chatReactions.isEmpty() ? 1 + availableReactions.size() : 0);
if (isChannel) {
return 1 + (!chatReactions.isEmpty() ? 1 + availableReactions.size() : 0);
}
return 1 + 1 + (!chatReactions.isEmpty() ? 1 + availableReactions.size() : 0);
}
@Override
public int getItemViewType(int position) {
return position == 0 ? TYPE_INFO : position == 1 ? TYPE_HEADER : TYPE_REACTION;
if (isChannel) {
return position == 0 ? TYPE_INFO : position == 1 ? TYPE_HEADER : TYPE_REACTION;
}
if (position == 0) {
return TYPE_CONTROLS_CONTAINER;
}
return position == 1 ? TYPE_INFO : position == 2 ? TYPE_HEADER : TYPE_REACTION;
}
});
listView.setOnItemClickListener((view, position) -> {
if (position <= 1) return;
if (position <= (isChannel ? 1 : 2)) return;
AvailableReactionCell cell = (AvailableReactionCell) view;
TLRPC.TL_availableReaction react = availableReactions.get(position - 2);
TLRPC.TL_availableReaction react = availableReactions.get(position - (isChannel ? 2 : 3));
boolean nc = !chatReactions.contains(react.reaction);
if (nc) {
chatReactions.add(react.reaction);
} else {
chatReactions.remove(react.reaction);
if (chatReactions.isEmpty()) {
setCheckedEnableReactionCell(false);
setCheckedEnableReactionCell(SELECT_TYPE_NONE, true);
}
}
@ -187,45 +265,68 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
return contentView;
}
private void setCheckedEnableReactionCell(boolean c) {
if (enableReactionsCell.isChecked() == c) {
private void setCheckedEnableReactionCell(int selectType, boolean animated) {
if (selectedType == selectType) {
return;
}
enableReactionsCell.setChecked(c);
int clr = Theme.getColor(c ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked);
if (c) {
enableReactionsCell.setBackgroundColorAnimated(c, clr);
} else {
enableReactionsCell.setBackgroundColorAnimatedReverse(clr);
}
if (c) {
for (TLRPC.TL_availableReaction a : availableReactions) {
chatReactions.add(a.reaction);
if (enableReactionsCell != null) {
boolean checked = selectType == SELECT_TYPE_SOME;
enableReactionsCell.setChecked(checked);
int clr = Theme.getColor(checked ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked);
if (checked) {
enableReactionsCell.setBackgroundColorAnimated(checked, clr);
} else {
enableReactionsCell.setBackgroundColorAnimatedReverse(clr);
}
}
this.selectedType = selectType;
for (int i = 0; i < radioCells.size(); i++) {
radioCells.get(i).setChecked(selectType == i, animated);
}
if (selectType == SELECT_TYPE_SOME) {
if (animated) {
chatReactions.clear();
for (TLRPC.TL_availableReaction a : availableReactions) {
if (a.reaction.equals("\uD83D\uDC4D") || a.reaction.equals("\uD83D\uDC4E")) {
chatReactions.add(a.reaction);
}
}
if (chatReactions.isEmpty() && availableReactions.size() >= 2) {
chatReactions.add(availableReactions.get(0).reaction);
chatReactions.add(availableReactions.get(1).reaction);
}
}
if (listAdapter != null && animated) {
listAdapter.notifyItemRangeInserted((isChannel ? 1 : 2), 1 + availableReactions.size());
}
listAdapter.notifyItemRangeInserted(1, 1 + availableReactions.size());
} else {
chatReactions.clear();
listAdapter.notifyItemRangeRemoved(1, 1 + availableReactions.size());
if (!chatReactions.isEmpty()) {
chatReactions.clear();
if (listAdapter != null && animated) {
listAdapter.notifyItemRangeRemoved((isChannel ? 1 : 2), 1 + availableReactions.size());
}
}
}
if (!isChannel && listAdapter != null && animated) {
listAdapter.notifyItemChanged(1);
}
if (listAdapter != null && !animated) {
listAdapter.notifyDataSetChanged();
}
}
@Override
public void onFragmentDestroy() {
super.onFragmentDestroy();
boolean changed = true;
if (info != null) {
changed = !info.available_reactions.equals(chatReactions);
}
if (changed) {
getMessagesController().setChatReactions(chatId, chatReactions);
}
getMessagesController().setChatReactions(chatId, selectedType, chatReactions);
getNotificationCenter().removeObserver(this, NotificationCenter.reactionsDidLoad);
}
/**
* Sets chat full info
*
* @param info Info to use
*/
public void setInfo(TLRPC.ChatFull info) {
@ -234,8 +335,21 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
if (currentChat == null) {
currentChat = getMessagesController().getChat(chatId);
}
chatReactions = new ArrayList<>();
if (info.available_reactions instanceof TLRPC.TL_chatReactionsAll) {
startFromType = SELECT_TYPE_ALL;
} else if (info.available_reactions instanceof TLRPC.TL_chatReactionsNone) {
startFromType = SELECT_TYPE_NONE;
} else if (info.available_reactions instanceof TLRPC.TL_chatReactionsSome) {
TLRPC.TL_chatReactionsSome reactionsSome = (TLRPC.TL_chatReactionsSome) info.available_reactions;
for (int i = 0; i < reactionsSome.reactions.size(); i++) {
if (reactionsSome.reactions.get(i) instanceof TLRPC.TL_reactionEmoji) {
chatReactions.add(((TLRPC.TL_reactionEmoji) reactionsSome.reactions.get(i)).emoticon);
}
}
startFromType = SELECT_TYPE_SOME;
}
chatReactions = new ArrayList<>(info.available_reactions);
}
}
@ -261,7 +375,9 @@ public class ChatReactionsEditActivity extends BaseFragment implements Notificat
@SuppressLint("NotifyDataSetChanged")
private void updateColors() {
contentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
enableReactionsCell.setColors(Theme.key_windowBackgroundCheckText, Theme.key_switchTrackBlue, Theme.key_switchTrackBlueChecked, Theme.key_switchTrackBlueThumb, Theme.key_switchTrackBlueThumbChecked);
if (enableReactionsCell != null) {
enableReactionsCell.setColors(Theme.key_windowBackgroundCheckText, Theme.key_switchTrackBlue, Theme.key_switchTrackBlueChecked, Theme.key_switchTrackBlueThumb, Theme.key_switchTrackBlueThumbChecked);
}
listAdapter.notifyDataSetChanged();
}

View File

@ -951,7 +951,7 @@ public class ChatRightsEditActivity extends BaseFragment {
TLRPC.TL_account_getPassword getPasswordReq = new TLRPC.TL_account_getPassword();
ConnectionsManager.getInstance(currentAccount).sendRequest(getPasswordReq, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> {
if (error2 == null) {
TLRPC.TL_account_password currentPassword = (TLRPC.TL_account_password) response2;
TLRPC.account_Password currentPassword = (TLRPC.account_Password) response2;
passwordFragment.setCurrentPasswordInfo(null, currentPassword);
TwoStepVerificationActivity.initPasswordNewAlgo(currentPassword);
initTransfer(passwordFragment.getNewSrpPassword(), passwordFragment);

View File

@ -1679,7 +1679,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
return;
}
TLRPC.User user = getMessagesController().getUser(userId);
getMessagesController().deleteParticipantFromChat(chatId, user, null);
getMessagesController().deleteParticipantFromChat(chatId, user);
if (delegate != null) {
delegate.didKickParticipant(userId);
}
@ -1869,7 +1869,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setItems(items.toArray(new CharSequence[actions.size()]), AndroidUtilities.toIntArray(icons), (dialogInterface, i) -> {
if (actions.get(i) == 2) {
getMessagesController().deleteParticipantFromChat(chatId, user, null);
getMessagesController().deleteParticipantFromChat(chatId, user);
removeParticipants(peerId);
if (currentChat != null && user != null && BulletinFactory.canShowBulletin(this)) {
BulletinFactory.createRemoveFromChatBulletin(this, user, currentChat.title).show();
@ -2026,7 +2026,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente
user = null;
chat = getMessagesController().getChat(-peerId);
}
getMessagesController().deleteParticipantFromChat(chatId, user, chat, null, false, false);
getMessagesController().deleteParticipantFromChat(chatId, user, chat, false, false);
}
}
});

View File

@ -129,6 +129,7 @@ import tw.nekomimi.nekogram.utils.VibrateUtil;
public class AlertsCreator {
public final static int PERMISSIONS_REQUEST_TOP_ICON_SIZE = 72;
public final static int NEW_DENY_DIALOG_TOP_ICON_SIZE = 52;
public static Dialog createForgotPasscodeDialog(Context ctx) {
return new AlertDialog.Builder(ctx)
@ -830,7 +831,7 @@ public class AlertsCreator {
if (ChatObject.isNotInChat(currentChat)) {
accountInstance.getMessagesController().deleteDialog(dialog_id, 0);
} else {
accountInstance.getMessagesController().deleteParticipantFromChat(-dialog_id, accountInstance.getMessagesController().getUser(accountInstance.getUserConfig().getClientUserId()), null);
accountInstance.getMessagesController().deleteParticipantFromChat(-dialog_id, accountInstance.getMessagesController().getUser(accountInstance.getUserConfig().getClientUserId()));
}
} else {
accountInstance.getMessagesController().deleteDialog(dialog_id, 0);
@ -2631,7 +2632,6 @@ public class AlertsCreator {
return builder;
}
public static BottomSheet.Builder createDatePickerDialog(Context context, long currentDate, final ScheduleDatePickerDelegate datePickerDelegate) {
if (context == null) {
return null;
@ -2814,6 +2814,194 @@ public class AlertsCreator {
return builder;
}
public interface StatusUntilDatePickerDelegate {
void didSelectDate(int date);
}
public static BottomSheet.Builder createStatusUntilDatePickerDialog(Context context, long currentDate, final StatusUntilDatePickerDelegate delegate) {
if (context == null) {
return null;
}
ScheduleDatePickerColors datePickerColors = new ScheduleDatePickerColors();
BottomSheet.Builder builder = new BottomSheet.Builder(context, false);
builder.setApplyBottomPadding(false);
final NumberPicker dayPicker = new NumberPicker(context);
dayPicker.setTextColor(datePickerColors.textColor);
dayPicker.setTextOffset(AndroidUtilities.dp(10));
dayPicker.setItemCount(5);
final NumberPicker hourPicker = new NumberPicker(context) {
@Override
protected CharSequence getContentDescription(int value) {
return LocaleController.formatPluralString("Hours", value);
}
};
hourPicker.setItemCount(5);
hourPicker.setTextColor(datePickerColors.textColor);
hourPicker.setTextOffset(-AndroidUtilities.dp(10));
final NumberPicker minutePicker = new NumberPicker(context) {
@Override
protected CharSequence getContentDescription(int value) {
return LocaleController.formatPluralString("Minutes", value);
}
};
minutePicker.setItemCount(5);
minutePicker.setTextColor(datePickerColors.textColor);
minutePicker.setTextOffset(-AndroidUtilities.dp(34));
LinearLayout container = new LinearLayout(context) {
boolean ignoreLayout = false;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
ignoreLayout = true;
int count;
if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) {
count = 3;
} else {
count = 5;
}
dayPicker.setItemCount(count);
hourPicker.setItemCount(count);
minutePicker.setItemCount(count);
dayPicker.getLayoutParams().height = AndroidUtilities.dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count;
hourPicker.getLayoutParams().height = AndroidUtilities.dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count;
minutePicker.getLayoutParams().height = AndroidUtilities.dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count;
ignoreLayout = false;
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public void requestLayout() {
if (ignoreLayout) {
return;
}
super.requestLayout();
}
};
container.setOrientation(LinearLayout.VERTICAL);
FrameLayout titleLayout = new FrameLayout(context);
container.addView(titleLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 22, 0, 0, 4));
TextView titleView = new TextView(context);
titleView.setText(LocaleController.getString("SetEmojiStatusUntilTitle", R.string.SetEmojiStatusUntilTitle));
titleView.setTextColor(datePickerColors.textColor);
titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
titleLayout.addView(titleView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 12, 0, 0));
titleView.setOnTouchListener((v, event) -> true);
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
linearLayout.setWeightSum(1.0f);
container.addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 1f, 0, 0, 12, 0, 12));
long currentTime = System.currentTimeMillis();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(currentTime);
int currentYear = calendar.get(Calendar.YEAR);
int currentDayYear = calendar.get(Calendar.DAY_OF_YEAR);
TextView buttonTextView = new TextView(context) {
@Override
public CharSequence getAccessibilityClassName() {
return Button.class.getName();
}
};
linearLayout.addView(dayPicker, LayoutHelper.createLinear(0, 54 * 5, 0.5f));
dayPicker.setMinValue(0);
dayPicker.setMaxValue(365);
dayPicker.setWrapSelectorWheel(false);
dayPicker.setFormatter(value -> {
if (value == 0) {
return LocaleController.getString("MessageScheduleToday", R.string.MessageScheduleToday);
} else {
long date = currentTime + (long) value * 86400000L;
calendar.setTimeInMillis(date);
int year = calendar.get(Calendar.YEAR);
int yearDay = calendar.get(Calendar.DAY_OF_YEAR);
if (year == currentYear && yearDay < currentDayYear + 7) {
return LocaleController.getInstance().formatterWeek.format(date) + ", " + LocaleController.getInstance().formatterScheduleDay.format(date);
} else if (year == currentYear) {
return LocaleController.getInstance().formatterScheduleDay.format(date);
} else {
return LocaleController.getInstance().formatterScheduleYear.format(date);
}
}
});
final NumberPicker.OnValueChangeListener onValueChangeListener = (picker, oldVal, newVal) -> {
try {
container.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
} catch (Exception ignore) {
}
checkScheduleDate(null, null, 0, dayPicker, hourPicker, minutePicker);
};
dayPicker.setOnValueChangedListener(onValueChangeListener);
hourPicker.setMinValue(0);
hourPicker.setMaxValue(23);
linearLayout.addView(hourPicker, LayoutHelper.createLinear(0, 54 * 5, 0.2f));
hourPicker.setFormatter(value -> String.format("%02d", value));
hourPicker.setOnValueChangedListener(onValueChangeListener);
minutePicker.setMinValue(0);
minutePicker.setMaxValue(59);
minutePicker.setValue(0);
minutePicker.setFormatter(value -> String.format("%02d", value));
linearLayout.addView(minutePicker, LayoutHelper.createLinear(0, 54 * 5, 0.3f));
minutePicker.setOnValueChangedListener(onValueChangeListener);
if (currentDate > 0 && currentDate != 0x7FFFFFFE) {
currentDate *= 1000;
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
int days = (int) ((currentDate - calendar.getTimeInMillis()) / (24 * 60 * 60 * 1000));
calendar.setTimeInMillis(currentDate);
if (days >= 0) {
minutePicker.setValue(calendar.get(Calendar.MINUTE));
hourPicker.setValue(calendar.get(Calendar.HOUR_OF_DAY));
dayPicker.setValue(days);
}
}
checkScheduleDate(null, null, 0, dayPicker, hourPicker, minutePicker);
buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0);
buttonTextView.setGravity(Gravity.CENTER);
buttonTextView.setTextColor(datePickerColors.buttonTextColor);
buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), datePickerColors.buttonBackgroundColor, datePickerColors.buttonBackgroundPressedColor));
buttonTextView.setText(LocaleController.getString("SetEmojiStatusUntilButton", R.string.SetEmojiStatusUntilButton));
container.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16));
buttonTextView.setOnClickListener(v -> {
boolean setSeconds = checkScheduleDate(null, null, 0, dayPicker, hourPicker, minutePicker);
calendar.setTimeInMillis(System.currentTimeMillis() + (long) dayPicker.getValue() * 24 * 3600 * 1000);
calendar.set(Calendar.HOUR_OF_DAY, hourPicker.getValue());
calendar.set(Calendar.MINUTE, minutePicker.getValue());
if (setSeconds) {
calendar.set(Calendar.SECOND, 0);
}
delegate.didSelectDate((int) (calendar.getTimeInMillis() / 1000));
builder.getDismissRunnable().run();
});
builder.setCustomView(container);
BottomSheet bottomSheet = builder.show();
bottomSheet.setBackgroundColor(datePickerColors.backgroundColor);
bottomSheet.fixNavigationBar(datePickerColors.backgroundColor);
return builder;
}
public static BottomSheet.Builder createAutoDeleteDatePickerDialog(Context context, Theme.ResourcesProvider resourcesProvider, final ScheduleDatePickerDelegate datePickerDelegate) {
if (context == null) {
return null;
@ -5113,7 +5301,7 @@ public class AlertsCreator {
}
if (userFinal != null || chatFinal != null) {
if (checks[0]) {
MessagesController.getInstance(currentAccount).deleteParticipantFromChat(chat.id, userFinal, chatFinal, chatInfo, false, false);
MessagesController.getInstance(currentAccount).deleteParticipantFromChat(chat.id, userFinal, chatFinal, false, false);
}
if (checks[1]) {
TLRPC.TL_channels_reportSpam req = new TLRPC.TL_channels_reportSpam();

View File

@ -4,12 +4,15 @@ import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.text.TextUtils;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -30,6 +33,7 @@ import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesStorage;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.SvgHelper;
import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.TLRPC;
@ -47,12 +51,12 @@ public class AnimatedEmojiDrawable extends Drawable {
public static final int CACHE_TYPE_MESSAGES_LARGE = 1;
public static final int CACHE_TYPE_KEYBOARD = 2;
public static final int CACHE_TYPE_ALERT_PREVIEW = 3;
public static final int CACHE_TYPE_TAB_STRIP = 4;
public static final int STANDARD_LOTTIE_FRAME = 5;
private Paint debugCacheType;
private static final boolean DEBUG_CACHE_TYPE = false;
public static final int CACHE_TYPE_ALERT_PREVIEW_LARGE = 4;
public static final int CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP = 5;
public static final int CACHE_TYPE_TAB_STRIP = 6;
public static final int CACHE_TYPE_EMOJI_STATUS = 7;
public static final int STANDARD_LOTTIE_FRAME = 8;
public static final int CACHE_TYPE_ALERT_EMOJI_STATUS = 9;
private static HashMap<Integer, HashMap<Long, AnimatedEmojiDrawable>> globalEmojiCache;
@NonNull
@ -325,7 +329,7 @@ public class AnimatedEmojiDrawable extends Drawable {
private boolean attached;
private ArrayList<View> views;
private ArrayList<AnimatedEmojiSpan.AnimatedEmojiHolder> holders;
private ArrayList<AnimatedEmojiSpan.InvalidateHolder> holders;
public int sizedp;
@ -340,18 +344,7 @@ public class AnimatedEmojiDrawable extends Drawable {
public AnimatedEmojiDrawable(int cacheType, int currentAccount, long documentId) {
this.currentAccount = currentAccount;
this.cacheType = cacheType;
if (this.cacheType == CACHE_TYPE_MESSAGES) {
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaint.ascent()) + Math.abs(Theme.chat_msgTextPaint.descent())) * 1.15f / AndroidUtilities.density);
} else if (this.cacheType == CACHE_TYPE_MESSAGES_LARGE) {
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaintEmoji[2].ascent()) + Math.abs(Theme.chat_msgTextPaintEmoji[2].descent())) * 1.15f / AndroidUtilities.density);
} else if (this.cacheType == CACHE_TYPE_KEYBOARD || this.cacheType == CACHE_TYPE_TAB_STRIP || this.cacheType == CACHE_TYPE_ALERT_PREVIEW) {
sizedp = 34;
} else if (this.cacheType == STANDARD_LOTTIE_FRAME) {
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaintEmoji[0].ascent()) + Math.abs(Theme.chat_msgTextPaintEmoji[0].descent())) * 1.15f / AndroidUtilities.density);
} else {
sizedp = 34;
}
updateSize();
this.documentId = documentId;
getDocumentFetcher(currentAccount).fetchDocument(documentId, document -> {
this.document = document;
@ -363,21 +356,21 @@ public class AnimatedEmojiDrawable extends Drawable {
this.cacheType = cacheType;
this.currentAccount = currentAccount;
this.document = document;
updateSize();
this.initDocument();
}
private void updateSize() {
if (this.cacheType == CACHE_TYPE_MESSAGES) {
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaint.ascent()) + Math.abs(Theme.chat_msgTextPaint.descent())) * 1.15f / AndroidUtilities.density);
} else if (this.cacheType == CACHE_TYPE_MESSAGES_LARGE) {
} else if (this.cacheType == CACHE_TYPE_MESSAGES_LARGE || this.cacheType == CACHE_TYPE_ALERT_PREVIEW_LARGE) {
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaintEmoji[2].ascent()) + Math.abs(Theme.chat_msgTextPaintEmoji[2].descent())) * 1.15f / AndroidUtilities.density);
} else if (this.cacheType == CACHE_TYPE_KEYBOARD || this.cacheType == CACHE_TYPE_TAB_STRIP || this.cacheType == CACHE_TYPE_ALERT_PREVIEW) {
sizedp = 34;
} else if (this.cacheType == STANDARD_LOTTIE_FRAME) {
sizedp = (int) ((Math.abs(Theme.chat_msgTextPaintEmoji[0].ascent()) + Math.abs(Theme.chat_msgTextPaintEmoji[0].descent())) * 1.15f / AndroidUtilities.density);
} else {
sizedp = 34;
}
this.initDocument();
}
public long getDocumentId() {
return this.document != null ? this.document.id : this.documentId;
}
@ -403,10 +396,14 @@ public class AnimatedEmojiDrawable extends Drawable {
return super.setImageBitmapByKey(drawable, key, type, memCache, guid);
}
};
if (colorFilterToSet != null && canOverrideColor()) {
imageReceiver.setColorFilter(colorFilterToSet);
}
if (cacheType != 0) {
imageReceiver.setUniqKeyPrefix(cacheType + "_");
}
boolean onlyStaticPreview = SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW && (cacheType == CACHE_TYPE_KEYBOARD || cacheType == CACHE_TYPE_ALERT_PREVIEW);
imageReceiver.setVideoThumbIsSame(true);
boolean onlyStaticPreview = SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW && (cacheType == CACHE_TYPE_KEYBOARD || cacheType == CACHE_TYPE_ALERT_PREVIEW || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP);
String filter = sizedp + "_" + sizedp;
if (cacheType != STANDARD_LOTTIE_FRAME && (cacheType != CACHE_TYPE_MESSAGES_LARGE || SharedConfig.getDevicePerformanceClass() < SharedConfig.PERFORMANCE_CLASS_HIGH)) {
@ -428,17 +425,25 @@ public class AnimatedEmojiDrawable extends Drawable {
mediaFilter = filter + "_" + ImageLoader.AUTOPLAY_FILTER;
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f);
thumbDrawable = svgThumb;
} else {
} else if ("application/x-tgsticker".equals(document.mime_type)) {
String probableCacheKey = (cacheType != 0 ? cacheType + "_" : "") + documentId + "@" + filter;
if (cacheType == CACHE_TYPE_KEYBOARD || !ImageLoader.getInstance().hasLottieMemCache(probableCacheKey)) {
if (SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW || (cacheType == CACHE_TYPE_KEYBOARD || !ImageLoader.getInstance().hasLottieMemCache(probableCacheKey))) {
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f);
if (svgThumb != null && MessageObject.isAnimatedStickerDocument(document, false)) {
if (svgThumb != null && MessageObject.isAnimatedStickerDocument(document, true)) {
svgThumb.overrideWidthAndHeight(512, 512);
}
thumbDrawable = svgThumb;
}
mediaLocation = ImageLocation.getForDocument(document);
mediaFilter = filter;
} else {
SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_windowBackgroundWhiteGrayIcon, 0.2f);
if (svgThumb != null && MessageObject.isAnimatedStickerDocument(document, true)) {
svgThumb.overrideWidthAndHeight(512, 512);
}
thumbDrawable = svgThumb;
mediaLocation = null;
mediaFilter = filter;
}
if (onlyStaticPreview) {
mediaLocation = null;
@ -449,9 +454,16 @@ public class AnimatedEmojiDrawable extends Drawable {
imageReceiver.setImage(mediaLocation, mediaFilter, ImageLocation.getForDocument(thumb, document), sizedp + "_" + sizedp, null, null, thumbDrawable, document.size, null, document, 1);
}
if (cacheType == CACHE_TYPE_ALERT_PREVIEW) {
if (cacheType == CACHE_TYPE_EMOJI_STATUS || cacheType == CACHE_TYPE_ALERT_EMOJI_STATUS) {
imageReceiver.setAutoRepeatCount(2);
}
if (cacheType == CACHE_TYPE_ALERT_PREVIEW || cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP || cacheType == CACHE_TYPE_ALERT_PREVIEW_LARGE) {
imageReceiver.setLayerNum(7);
}
if (cacheType == CACHE_TYPE_ALERT_EMOJI_STATUS) {
imageReceiver.setLayerNum(6656);
}
imageReceiver.setAspectFit(true);
if (cacheType != STANDARD_LOTTIE_FRAME) {
imageReceiver.setAllowStartLottieAnimation(true);
@ -463,6 +475,11 @@ public class AnimatedEmojiDrawable extends Drawable {
imageReceiver.setAutoRepeat(0);
}
imageReceiver.setAllowDecodeSingleFrame(true);
int roundRadius = 0;
if (cacheType == CACHE_TYPE_ALERT_PREVIEW_TAB_STRIP || cacheType == CACHE_TYPE_TAB_STRIP) {
roundRadius = AndroidUtilities.dp(6);
}
imageReceiver.setRoundRadius(roundRadius);
updateAttachState();
invalidate();
}
@ -478,7 +495,7 @@ public class AnimatedEmojiDrawable extends Drawable {
}
if (holders != null) {
for (int i = 0; i < holders.size(); ++i) {
AnimatedEmojiSpan.AnimatedEmojiHolder holder = holders.get(i);
AnimatedEmojiSpan.InvalidateHolder holder = holders.get(i);
if (holder != null) {
holder.invalidate();
}
@ -500,7 +517,10 @@ public class AnimatedEmojiDrawable extends Drawable {
@Override
public void draw(@NonNull Canvas canvas) {
drawDebugCacheType(canvas);
draw(canvas, true);
}
public void draw(@NonNull Canvas canvas, boolean canTranslate) {
if (imageReceiver != null) {
imageReceiver.setImageCoords(getBounds());
imageReceiver.setAlpha(alpha);
@ -512,7 +532,6 @@ public class AnimatedEmojiDrawable extends Drawable {
}
public void draw(Canvas canvas, Rect drawableBounds, float alpha) {
drawDebugCacheType(canvas);
if (imageReceiver != null) {
imageReceiver.setImageCoords(drawableBounds);
imageReceiver.setAlpha(alpha);
@ -524,8 +543,8 @@ public class AnimatedEmojiDrawable extends Drawable {
drawPlaceholder(canvas, drawableBounds.centerX(), drawableBounds.centerY(), drawableBounds.width() / 2f);
}
}
public void draw(Canvas canvas, ImageReceiver.BackgroundThreadDrawHolder backgroundThreadDrawHolder) {
drawDebugCacheType(canvas);
public void draw(Canvas canvas, ImageReceiver.BackgroundThreadDrawHolder backgroundThreadDrawHolder, boolean canTranslate) {
if (imageReceiver != null) {
imageReceiver.setAlpha(alpha);
imageReceiver.draw(canvas, backgroundThreadDrawHolder);
@ -537,16 +556,6 @@ public class AnimatedEmojiDrawable extends Drawable {
}
}
private void drawDebugCacheType(Canvas canvas) {
if (DEBUG_CACHE_TYPE) {
if (debugCacheType == null) {
debugCacheType = new Paint(Paint.ANTI_ALIAS_FLAG);
}
debugCacheType.setColor(0xff000000 | (cacheType % 2 == 0 ? 0x00ff0000 : 0x0000ff00) | (cacheType % 3 == 0 ? 0x000000ff : 0x00ff0000));
canvas.drawRect(getBounds(), debugCacheType);
}
}
private AnimatedFloat placeholderAlpha = new AnimatedFloat(1f, this::invalidate, 0, 150, new LinearInterpolator());
private boolean shouldDrawPlaceholder = false;
private void drawPlaceholder(Canvas canvas, float cx, float cy, float r) {
@ -580,7 +589,7 @@ public class AnimatedEmojiDrawable extends Drawable {
updateAttachState();
}
public void addView(AnimatedEmojiSpan.AnimatedEmojiHolder holder) {
public void addView(AnimatedEmojiSpan.InvalidateHolder holder) {
if (holders == null) {
holders = new ArrayList<>(10);
}
@ -590,7 +599,7 @@ public class AnimatedEmojiDrawable extends Drawable {
updateAttachState();
}
public void removeView(AnimatedEmojiSpan.AnimatedEmojiHolder holder) {
public void removeView(AnimatedEmojiSpan.InvalidateHolder holder) {
if (holders != null) {
holders.remove(holder);
}
@ -604,7 +613,6 @@ public class AnimatedEmojiDrawable extends Drawable {
updateAttachState();
}
int count;
private void updateAttachState() {
if (imageReceiver == null) {
return;
@ -613,15 +621,13 @@ public class AnimatedEmojiDrawable extends Drawable {
if (attach != attached) {
attached = attach;
if (attached) {
count++;
imageReceiver.onAttachedToWindow();
} else {
count--;
imageReceiver.onDetachedFromWindow();
}
}
// if (globalEmojiCache != null && (views == null || views.size() <= 0) && (holders == null || holders.size() <= 0) && globalEmojiCache.size() > 300) {
// if (globalEmojiCache != null && (views == null || views.size() <= 0) && (holders == null || holders.size() <= 0) && globalEmojiCache.size() > 50) {
// HashMap<Long, AnimatedEmojiDrawable> cache = globalEmojiCache.get(currentAccount);
// if (cache != null) {
// cache.remove(documentId);
@ -629,6 +635,26 @@ public class AnimatedEmojiDrawable extends Drawable {
// }
}
private Boolean canOverrideColorCached = null;
public boolean canOverrideColor() {
if (canOverrideColorCached != null) {
return canOverrideColorCached;
}
if (document != null) {
TLRPC.InputStickerSet set = MessageObject.getInputStickerSet(document);
return canOverrideColorCached = (
set instanceof TLRPC.TL_inputStickerSetEmojiDefaultStatuses ||
set instanceof TLRPC.TL_inputStickerSetID && (set.id == 773947703670341676L || set.id == 2964141614563343L)
);
}
return false;
}
@Override
public int getAlpha() {
return (int) (255 * this.alpha);
}
@Override
public void setAlpha(int alpha) {
this.alpha = alpha / 255f;
@ -637,9 +663,15 @@ public class AnimatedEmojiDrawable extends Drawable {
}
}
private ColorFilter colorFilterToSet;
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
if (imageReceiver == null) {
colorFilterToSet = colorFilter;
} else if (canOverrideColor()) {
imageReceiver.setColorFilter(colorFilter);
}
}
@Override
@ -651,4 +683,350 @@ public class AnimatedEmojiDrawable extends Drawable {
return imageReceiver;
}
public static class WrapSizeDrawable extends Drawable {
private Drawable drawable;
int width, height;
public WrapSizeDrawable(Drawable drawable, int width, int height) {
this.drawable = drawable;
this.width = width;
this.height = height;
}
public Drawable getDrawable() {
return drawable;
}
@Override
public void draw(@NonNull Canvas canvas) {
if (this.drawable != null) {
this.drawable.setBounds(getBounds());
this.drawable.setAlpha(this.alpha);
this.drawable.draw(canvas);
}
}
@Override
public int getIntrinsicWidth() {
return this.width;
}
@Override
public int getIntrinsicHeight() {
return this.height;
}
private int alpha = 255;
@Override
public void setAlpha(int alpha) {
this.alpha = alpha;
if (this.drawable != null) {
this.drawable.setAlpha(alpha);
}
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {
if (this.drawable != null) {
this.drawable.setColorFilter(colorFilter);
}
}
@Override
public int getOpacity() {
if (this.drawable != null) {
return this.drawable.getOpacity();
}
return PixelFormat.TRANSPARENT;
}
}
public static class SwapAnimatedEmojiDrawable extends Drawable {
public boolean center = false;
private int cacheType;
private OvershootInterpolator overshootInterpolator = new OvershootInterpolator(2f);
private AnimatedFloat changeProgress = new AnimatedFloat((View) null, 300, CubicBezierInterpolator.EASE_OUT);
private Drawable[] drawables = new Drawable[2];
private View parentView;
private int size;
private int alpha = 255;
public SwapAnimatedEmojiDrawable(View parentView, int size) {
this(parentView, size, CACHE_TYPE_EMOJI_STATUS);
}
public SwapAnimatedEmojiDrawable(View parentView, int size, int cacheType) {
changeProgress.setParent(this.parentView = parentView);
this.size = size;
this.cacheType = cacheType;
}
public void setParentView(View parentView) {
removeParentView(this.parentView);
addParentView(this.parentView = parentView);
changeProgress.setParent(parentView);
this.parentView = parentView;
}
public void addParentView(View parentView) {
if (drawables[0] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[0]).addView(parentView);
}
if (drawables[1] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[1]).addView(parentView);
}
}
public void removeParentView(View parentView) {
if (drawables[0] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[0]).removeView(parentView);
}
if (drawables[1] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[1]).removeView(parentView);
}
}
public void play() {
if (getDrawable() instanceof AnimatedEmojiDrawable) {
AnimatedEmojiDrawable drawable = (AnimatedEmojiDrawable) getDrawable();
ImageReceiver imageReceiver = drawable.getImageReceiver();
if (imageReceiver != null) {
if (drawable.cacheType == CACHE_TYPE_EMOJI_STATUS || drawable.cacheType == CACHE_TYPE_ALERT_EMOJI_STATUS) {
imageReceiver.setAutoRepeatCount(2);
}
imageReceiver.startAnimation();
}
}
}
private Integer lastColor;
private ColorFilter colorFilter;
public void setColor(Integer color) {
if (lastColor == null && color == null || lastColor != null && lastColor.equals(color)) {
return;
}
lastColor = color;
colorFilter = color != null ? new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY) : null;
}
public Integer getColor() {
return lastColor;
}
@Override
public void draw(@NonNull Canvas canvas) {
float progress = changeProgress.set(1);
Rect bounds = getBounds();
if (drawables[1] != null && progress < 1) {
drawables[1].setAlpha((int) (alpha * (1f - progress)));
if (drawables[1] instanceof AnimatedEmojiDrawable) {
drawables[1].setBounds(bounds);
} else if (center) {
drawables[1].setBounds(
bounds.centerX() - drawables[1].getIntrinsicWidth() / 2,
bounds.centerY() - drawables[1].getIntrinsicHeight() / 2,
bounds.centerX() + drawables[1].getIntrinsicWidth() / 2,
bounds.centerY() + drawables[1].getIntrinsicHeight() / 2
);
} else { // left
drawables[1].setBounds(
bounds.left,
bounds.centerY() - drawables[1].getIntrinsicHeight() / 2,
bounds.left + drawables[1].getIntrinsicWidth(),
bounds.centerY() + drawables[1].getIntrinsicHeight() / 2
);
}
drawables[1].setColorFilter(colorFilter);
drawables[1].draw(canvas);
drawables[1].setColorFilter(null);
}
if (drawables[0] != null) {
canvas.save();
if (drawables[0] instanceof AnimatedEmojiDrawable) {
if (((AnimatedEmojiDrawable) drawables[0]).imageReceiver != null) {
((AnimatedEmojiDrawable) drawables[0]).imageReceiver.setRoundRadius(AndroidUtilities.dp(4));
}
if (progress < 1) {
float scale = overshootInterpolator.getInterpolation(progress);
canvas.scale(scale, scale, bounds.centerX(), bounds.centerY());
}
drawables[0].setBounds(bounds);
} else if (center) {
if (progress < 1) {
float scale = overshootInterpolator.getInterpolation(progress);
canvas.scale(scale, scale, bounds.centerX(), bounds.centerY());
}
drawables[0].setBounds(
bounds.centerX() - drawables[0].getIntrinsicWidth() / 2,
bounds.centerY() - drawables[0].getIntrinsicHeight() / 2,
bounds.centerX() + drawables[0].getIntrinsicWidth() / 2,
bounds.centerY() + drawables[0].getIntrinsicHeight() / 2
);
} else { // left
if (progress < 1) {
float scale = overshootInterpolator.getInterpolation(progress);
canvas.scale(scale, scale, bounds.left + drawables[0].getIntrinsicWidth() / 2f, bounds.centerY());
}
drawables[0].setBounds(
bounds.left,
bounds.centerY() - drawables[0].getIntrinsicHeight() / 2,
bounds.left + drawables[0].getIntrinsicWidth(),
bounds.centerY() + drawables[0].getIntrinsicHeight() / 2
);
}
drawables[0].setAlpha(alpha);
drawables[0].setColorFilter(colorFilter);
drawables[0].draw(canvas);
drawables[0].setColorFilter(null);
canvas.restore();
}
}
public Drawable getDrawable() {
return drawables[0];
}
public void set(long documentId, boolean animated) {
set(documentId, cacheType, animated);
}
public void set(long documentId, int cacheType, boolean animated) {
if (drawables[0] instanceof AnimatedEmojiDrawable && ((AnimatedEmojiDrawable) drawables[0]).getDocumentId() == documentId) {
return;
}
if (animated) {
changeProgress.set(0, true);
if (drawables[1] != null) {
if (drawables[1] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[1]).removeView(parentView);
}
drawables[1] = null;
}
drawables[1] = drawables[0];
drawables[0] = AnimatedEmojiDrawable.make(UserConfig.selectedAccount, cacheType, documentId);
((AnimatedEmojiDrawable) drawables[0]).addView(parentView);
} else {
changeProgress.set(1, true);
detach();
drawables[0] = AnimatedEmojiDrawable.make(UserConfig.selectedAccount, cacheType, documentId);
((AnimatedEmojiDrawable) drawables[0]).addView(parentView);
}
lastColor = 0xffffffff;
colorFilter = null;
play();
if (parentView != null) {
parentView.invalidate();
}
}
public void set(TLRPC.Document document, boolean animated) {
set(document, cacheType, animated);
}
public void set(TLRPC.Document document, int cacheType, boolean animated) {
if (drawables[0] instanceof AnimatedEmojiDrawable && document != null && ((AnimatedEmojiDrawable) drawables[0]).getDocumentId() == document.id) {
return;
}
if (animated) {
changeProgress.set(0, true);
if (drawables[1] != null) {
if (drawables[1] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[1]).removeView(parentView);
}
drawables[1] = null;
}
drawables[1] = drawables[0];
if (document != null) {
drawables[0] = AnimatedEmojiDrawable.make(UserConfig.selectedAccount, cacheType, document);
((AnimatedEmojiDrawable) drawables[0]).addView(parentView);
} else {
drawables[0] = null;
}
} else {
changeProgress.set(1, true);
detach();
if (document != null) {
drawables[0] = AnimatedEmojiDrawable.make(UserConfig.selectedAccount, cacheType, document);
((AnimatedEmojiDrawable) drawables[0]).addView(parentView);
} else {
drawables[0] = null;
}
}
lastColor = 0xffffffff;
colorFilter = null;
play();
if (parentView != null) {
parentView.invalidate();
}
}
public void set(Drawable drawable, boolean animated) {
if (drawables[0] == drawable) {
return;
}
if (animated) {
changeProgress.set(0, true);
if (drawables[1] != null) {
if (drawables[1] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[1]).removeView(parentView);
}
drawables[1] = null;
}
drawables[1] = drawables[0];
drawables[0] = drawable;
} else {
changeProgress.set(1, true);
detach();
drawables[0] = drawable;
}
lastColor = 0xffffffff;
colorFilter = null;
play();
if (parentView != null) {
parentView.invalidate();
}
}
public void detach() {
if (drawables[0] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[0]).removeView(parentView);
}
if (drawables[1] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[1]).removeView(parentView);
}
}
public void attach() {
if (drawables[0] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[0]).addView(parentView);
}
if (drawables[1] instanceof AnimatedEmojiDrawable) {
((AnimatedEmojiDrawable) drawables[1]).addView(parentView);
}
}
@Override
public int getIntrinsicWidth() {
return size;
}
@Override
public int getIntrinsicHeight() {
return size;
}
@Override
public void setAlpha(int i) {
alpha = i;
}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
}
}

View File

@ -1,6 +1,7 @@
package org.telegram.ui.Components;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.Layout;
@ -32,6 +33,7 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
public TLRPC.Document document;
private float scale;
public boolean standard;
public boolean full = false;
private Paint.FontMetricsInt fontMetrics;
private float size = AndroidUtilities.dp(20);
@ -43,6 +45,7 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
float lastDrawnCx;
float lastDrawnCy;
private boolean recordPositions = true;
public boolean fromEmojiKeyboard;
public AnimatedEmojiSpan(@NonNull TLRPC.Document document, Paint.FontMetricsInt fontMetrics) {
this(document.id, 1.2f, fontMetrics);
@ -99,16 +102,27 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
measuredSize = (int) (sz * scale);
} else {
if (fm != null) {
fm.ascent = (int) (fontMetrics.ascent);
fm.descent = (int) (fontMetrics.descent);
fm.top = (int) (fontMetrics.top);
fm.bottom = (int) (fontMetrics.bottom);
}
measuredSize = (int) (size * scale);
if (fm != null) {
if (!full) {
fm.ascent = (int) (fontMetrics.ascent);
fm.descent = (int) (fontMetrics.descent);
fm.top = (int) (fontMetrics.top);
fm.bottom = (int) (fontMetrics.bottom);
} else {
float height = Math.abs(fontMetrics.bottom) + Math.abs(fontMetrics.top);
fm.ascent = (int) Math.ceil(fontMetrics.top / height * measuredSize);
fm.descent = (int) Math.ceil(fontMetrics.bottom / height * measuredSize);
fm.top = (int) Math.ceil(fontMetrics.top / height * measuredSize);
fm.bottom = (int) Math.ceil(fontMetrics.bottom / height * measuredSize);
}
}
}
return measuredSize;
return measuredSize - 1;
}
private int asizeDp;
@ -131,6 +145,10 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
}
public static void drawAnimatedEmojis(Canvas canvas, Layout layout, EmojiGroupedSpans stack, float offset, List<SpoilerEffect> spoilers, float boundTop, float boundBottom, float drawingYOffset, float alpha) {
drawAnimatedEmojis(canvas, layout, stack, offset, spoilers, boundTop, boundBottom, drawingYOffset, alpha, null);
}
public static void drawAnimatedEmojis(Canvas canvas, Layout layout, EmojiGroupedSpans stack, float offset, List<SpoilerEffect> spoilers, float boundTop, float boundBottom, float drawingYOffset, float alpha, ColorFilter colorFilter) {
if (canvas == null || layout == null || stack == null) {
return;
}
@ -147,7 +165,7 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
for (int k = 0; k < stack.backgroundDrawingArray.size(); k++) {
SpansChunk chunk = stack.backgroundDrawingArray.get(k);
if (chunk.layout == layout) {
chunk.draw(canvas, spoilers, time, boundTop, boundBottom, drawingYOffset, alpha);
chunk.draw(canvas, spoilers, time, boundTop, boundBottom, drawingYOffset, alpha, colorFilter);
break;
}
}
@ -175,7 +193,7 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
// stack
// ===
public static class AnimatedEmojiHolder {
public static class AnimatedEmojiHolder implements InvalidateHolder {
private final View view;
private final boolean invalidateInParent;
public Layout layout;
@ -293,9 +311,9 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
for (int l = 0; l < layouts.length; ++l) {
Layout textLayout = layouts[l];
AnimatedEmojiSpan[] spans = null;
if (textLayout != null && textLayout.getText() instanceof Spannable) {
if (textLayout != null && textLayout.getText() instanceof Spanned) {
Spannable spanned = (Spannable) textLayout.getText();
Spanned spanned = (Spanned) textLayout.getText();
spans = spanned.getSpans(0, spanned.length(), AnimatedEmojiSpan.class);
for (int i = 0; spans != null && i < spans.length; ++i) {
@ -303,10 +321,10 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
if (span == null) {
continue;
}
if (clone) {
if (clone && textLayout.getText() instanceof Spannable) {
int start = spanned.getSpanStart(span), end = spanned.getSpanEnd(span);
spanned.removeSpan(span);
spanned.setSpan(span = cloneSpan(span), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
((Spannable) spanned).removeSpan(span);
((Spannable) spanned).setSpan(span = cloneSpan(span), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
AnimatedEmojiHolder holder = null;
if (prev == null) {
@ -632,20 +650,20 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
for (int i = 0; i < backgroundHolders.size(); i++) {
AnimatedEmojiHolder holder = backgroundHolders.get(i);
if (holder != null && holder.backgroundDrawHolder != null) {
holder.drawable.draw(canvas, holder.backgroundDrawHolder);
holder.drawable.draw(canvas, holder.backgroundDrawHolder, true);
}
}
}
@Override
public void drawInUiThread(Canvas canvas) {
public void drawInUiThread(Canvas canvas, float alpha) {
long time = System.currentTimeMillis();
for (int i = 0; i < holders.size(); ++i) {
AnimatedEmojiHolder holder = holders.get(i);
if (!holder.span.spanDrawn) {
continue;
}
holder.draw(canvas, time, 0, 0, 1f);
holder.draw(canvas, time, 0, 0, alpha);
}
}
@ -704,7 +722,7 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
checkBackgroundRendering();
}
public void draw(Canvas canvas, List<SpoilerEffect> spoilers, long time, float boundTop, float boundBottom, float drawingYOffset, float alpha) {
public void draw(Canvas canvas, List<SpoilerEffect> spoilers, long time, float boundTop, float boundBottom, float drawingYOffset, float alpha, ColorFilter colorFilter) {
for (int i = 0; i < holders.size(); ++i) {
AnimatedEmojiHolder holder = holders.get(i);
if (holder == null) {
@ -714,6 +732,7 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
if (drawable == null) {
continue;
}
drawable.setColorFilter(colorFilter);
if (!holder.span.spanDrawn) {
continue;
}
@ -742,11 +761,14 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
}
public static AnimatedEmojiSpan cloneSpan(AnimatedEmojiSpan span) {
AnimatedEmojiSpan animatedEmojiSpan;
if (span.document != null) {
return new AnimatedEmojiSpan(span.document, span.fontMetrics);
animatedEmojiSpan = new AnimatedEmojiSpan(span.document, span.fontMetrics);
} else {
return new AnimatedEmojiSpan(span.documentId, span.scale, span.fontMetrics);
animatedEmojiSpan = new AnimatedEmojiSpan(span.documentId, span.scale, span.fontMetrics);
}
animatedEmojiSpan.fromEmojiKeyboard = span.fromEmojiKeyboard;
return animatedEmojiSpan;
}
public static CharSequence cloneSpans(CharSequence text) {
@ -781,4 +803,8 @@ public class AnimatedEmojiSpan extends ReplacementSpan {
}
return newText;
}
public interface InvalidateHolder {
void invalidate();
}
}

View File

@ -12,6 +12,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
@ -112,12 +113,16 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
private BitmapShader nextRenderingShader;
private BitmapShader backgroundShader;
private BitmapShader renderingShaderBackgroundDraw;
private int[] roundRadius = new int[4];
private int[] roundRadiusBackup;
private Matrix shaderMatrix = new Matrix();
private Path roundPath = new Path();
private static float[] radii = new float[8];
private Matrix shaderMatrixBackgroundDraw;
private float scaleX = 1.0f;
private float scaleY = 1.0f;
private boolean applyTransformation;
@ -312,8 +317,12 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
cacheMetadata = new BitmapsCache.Metadata();
}
lastFrameDecodeTime = System.currentTimeMillis();
int lastFrame = cacheMetadata.frame;
int result = bitmapsCache.getFrame(backgroundBitmap, cacheMetadata);
metaData[3] = backgroundBitmapTime = cacheMetadata.frame * 33;
if (result != -1 && cacheMetadata.frame < lastFrame) {
isRestarted = true;
}
metaData[3] = backgroundBitmapTime = cacheMetadata.frame * Math.max(16, metaData[4] / Math.max(1, bitmapsCache.getFrameCount()));
if (bitmapsCache.needGenCache()) {
AndroidUtilities.runOnUIThread(uiRunnableGenerateCache);
@ -357,7 +366,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
AndroidUtilities.runOnUIThread(uiRunnableNoFrame);
return;
}
if (lastTimeStamp != 0 && metaData[3] == 0) {
if (metaData[3] < lastTimeStamp) {
isRestarted = true;
}
if (seekWas) {
@ -431,7 +440,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
destroyDecoder(nativePtr);
nativePtr = 0;
} else {
bitmapsCache = new BitmapsCache(file, this, cacheOptions, renderingWidth, renderingHeight);
bitmapsCache = new BitmapsCache(file, this, cacheOptions, renderingWidth, renderingHeight, !limitFps);
}
}
if (seekTo != 0) {
@ -487,6 +496,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
scheduleNextGetFrame();
}
}
checkCacheCancel();
}
public void removeParent(ImageReceiver imageReceiver) {
@ -494,6 +504,25 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
if (parents.size() == 0) {
repeatCount = 0;
}
checkCacheCancel();
}
private Runnable cancelCache;
public void checkCacheCancel() {
if (bitmapsCache == null) {
return;
}
boolean mustCancel = parents.isEmpty();
if (mustCancel && cancelCache == null) {
AndroidUtilities.runOnUIThread(cancelCache = () -> {
if (bitmapsCache != null) {
bitmapsCache.cancelCreate();
}
}, 600);
} else if (!mustCancel && cancelCache != null) {
AndroidUtilities.cancelRunOnUIThread(cancelCache);
cancelCache = null;
}
}
public void setInvalidateParentViewWithSecond(boolean value) {
@ -725,13 +754,14 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
drawInternal(canvas, false, System.currentTimeMillis());
}
public void drawInBackground(Canvas canvas, float x, float y, float w, float h, int alpha) {
public void drawInBackground(Canvas canvas, float x, float y, float w, float h, int alpha, ColorFilter colorFilter) {
if (dstRectBackground == null) {
dstRectBackground = new RectF();
backgroundPaint = new Paint();
backgroundPaint.setFilterBitmap(true);
}
backgroundPaint.setAlpha(alpha);
backgroundPaint.setColorFilter(colorFilter);
dstRectBackground.set(x, y, x + w, y + h);
drawInternal(canvas, true, 0);
}
@ -780,7 +810,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
}
if (hasRoundRadius()) {
if (renderingShader == null) {
renderingShader = new BitmapShader(backgroundBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
renderingShader = new BitmapShader(renderingBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
}
paint.setShader(renderingShader);
shaderMatrix.reset();
@ -805,7 +835,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable,
radii[a * 2 + 1] = roundRadius[a];
}
roundPath.reset();
roundPath.addRoundRect(actualDrawRect, radii, Path.Direction.CW);
roundPath.addRoundRect(drawInBackground ? rect : actualDrawRect, radii, Path.Direction.CW);
roundPath.close();
}
canvas.drawPath(roundPath, paint);

View File

@ -121,7 +121,7 @@ public class AnimatedFloat {
public float set(float mustBe, boolean force) {
final long now = SystemClock.elapsedRealtime();
if (force || firstSet) {
if (force || transitionDuration <= 0 || firstSet) {
value = targetValue = mustBe;
transition = false;
firstSet = false;

View File

@ -26,6 +26,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.ActionBar.Theme;
import java.util.ArrayList;
import java.util.Arrays;
@ -110,12 +111,11 @@ public class AnimatedTextView extends View {
canvas.save();
int lwidth = j >= 0 ? width : currentWidth;
if (isRTL) {
x = lwidth - x - currentLayout[i].getWidth();
x -= fullWidth - lwidth;
x = -x + 2 * lwidth - currentLayout[i].getWidth() - fullWidth;
}
if ((gravity & Gravity.CENTER_HORIZONTAL) > 0) {
x += (fullWidth - lwidth) / 2f;
} else if ((gravity & Gravity.RIGHT) > 0) {
} else if ((gravity & Gravity.RIGHT) > 0 || isRTL) {
x += fullWidth - lwidth;
}
canvas.translate(x, y);
@ -132,12 +132,11 @@ public class AnimatedTextView extends View {
textPaint.setAlpha((int) (alpha * (1f - t)));
canvas.save();
if (isRTL) {
x = oldWidth - x - oldLayout[i].getWidth();
x -= fullWidth - oldWidth;
x = -x + 2 * oldWidth - oldLayout[i].getWidth() - fullWidth;
}
if ((gravity & Gravity.CENTER_HORIZONTAL) > 0) {
x += (fullWidth - oldWidth) / 2f;
} else if ((gravity & Gravity.RIGHT) > 0) {
} else if ((gravity & Gravity.RIGHT) > 0 || isRTL) {
x += fullWidth - oldWidth;
}
canvas.translate(x, y);
@ -152,12 +151,11 @@ public class AnimatedTextView extends View {
canvas.save();
float x = currentLayoutOffsets[i];
if (isRTL) {
x = currentWidth - x - currentLayout[i].getWidth();
x -= fullWidth - currentWidth;
x = -x + 2 * currentWidth - currentLayout[i].getWidth() - fullWidth;
}
if ((gravity & Gravity.CENTER_HORIZONTAL) > 0) {
x += (fullWidth - currentWidth) / 2f;
} else if ((gravity & Gravity.RIGHT) > 0) {
} else if ((gravity & Gravity.RIGHT) > 0 || isRTL) {
x += fullWidth - currentWidth;
}
canvas.translate(x, 0);

View File

@ -1399,7 +1399,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
for (int a = 0; a < dids.size(); a++) {
long did = dids.get(a);
if (message != null) {
SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, null, true, null, null, null, true, 0, null);
SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, null, true, null, null, null, true, 0, null, false);
}
SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did, false, false, true, 0);
}
@ -2027,7 +2027,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter.
if (thumbImageLocation.path != null) {
ImageLoader.getInstance().preloadArtwork(thumbImageLocation.path);
} else {
FileLoader.getInstance(currentAccount).loadFile(thumbImageLocation, messageObject, null, 0, 1);
FileLoader.getInstance(currentAccount).loadFile(thumbImageLocation, messageObject, null, FileLoader.PRIORITY_LOW, 1);
}
}
}

View File

@ -28,6 +28,8 @@ public class BackupImageView extends View {
protected ImageReceiver imageReceiver;
protected int width = -1;
protected int height = -1;
public AnimatedEmojiDrawable animatedEmojiDrawable;
boolean attached;
public boolean shouldInvalidate = true;
public BackupImageView(Context context) {
@ -176,17 +178,29 @@ public class BackupImageView extends View {
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
attached = false;
imageReceiver.onDetachedFromWindow();
if (animatedEmojiDrawable != null) {
animatedEmojiDrawable.removeView(this);
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
attached = true;
imageReceiver.onAttachedToWindow();
if (animatedEmojiDrawable != null) {
animatedEmojiDrawable.addView(this);
}
}
@Override
protected void onDraw(Canvas canvas) {
ImageReceiver imageReceiver = animatedEmojiDrawable != null ? animatedEmojiDrawable.getImageReceiver() : this.imageReceiver;
if (imageReceiver == null) {
return;
}
if (width != -1 && height != -1) {
imageReceiver.setImageCoords((getWidth() - width) / 2, (getHeight() - height) / 2, width, height);
} else {
@ -199,6 +213,19 @@ public class BackupImageView extends View {
imageReceiver.setColorFilter(colorFilter);
}
public void setAnimatedEmojiDrawable(AnimatedEmojiDrawable animatedEmojiDrawable) {
if (this.animatedEmojiDrawable == animatedEmojiDrawable) {
return;
}
if (attached && this.animatedEmojiDrawable != null) {
this.animatedEmojiDrawable.removeView(this);
}
this.animatedEmojiDrawable = animatedEmojiDrawable;
if (attached && animatedEmojiDrawable != null) {
animatedEmojiDrawable.addView(this);
}
}
@Override
public void invalidate() {
if (shouldInvalidate) super.invalidate();

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