mirror of
https://github.com/DrKLO/Telegram.git
synced 2024-12-22 14:35:03 +01:00
Update to 5.10.0
This commit is contained in:
parent
9f48ec7ea2
commit
53e04b55fb
252 changed files with 11412 additions and 5153 deletions
|
@ -242,7 +242,7 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
defaultConfig.versionCode = 1648
|
||||
defaultConfig.versionCode = 1684
|
||||
|
||||
applicationVariants.all { variant ->
|
||||
variant.outputs.all { output ->
|
||||
|
@ -276,7 +276,7 @@ android {
|
|||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
versionName "5.9.0"
|
||||
versionName "5.10.0"
|
||||
|
||||
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.CALL_PHONE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.READ_CALL_LOG" />
|
||||
|
||||
<permission android:name="org.telegram.messenger.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.CALL_PHONE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.READ_CALL_LOG" />
|
||||
|
||||
<permission android:name="org.telegram.messenger.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ LOCAL_PATH := $(MY_LOCAL_PATH) # restore local path after include
|
|||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -frtti -DHAVE_PTHREAD -finline-functions -ffast-math -Os
|
||||
LOCAL_CPPFLAGS := -Wall -std=c++14 -DANDROID -frtti -DHAVE_PTHREAD -finline-functions -ffast-math -Os
|
||||
|
||||
LOCAL_C_INCLUDES += ./jni/boringssl/include/
|
||||
LOCAL_ARM_MODE := arm
|
||||
|
@ -351,7 +351,7 @@ LOCAL_MODULE := tmessages.30
|
|||
LOCAL_CFLAGS := -w -std=c11 -Os -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1
|
||||
LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno
|
||||
LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math -D__STDC_CONSTANT_MACROS
|
||||
LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -Os -funroll-loops -std=c++11
|
||||
LOCAL_CPPFLAGS := -DBSD=1 -ffast-math -Os -funroll-loops -std=c++14
|
||||
LOCAL_LDLIBS := -ljnigraphics -llog -lz -lEGL -lGLESv2 -landroid
|
||||
LOCAL_STATIC_LIBRARIES := webp sqlite lz4 rlottie tgnet swscale avformat avcodec avresample avutil voip flac
|
||||
|
||||
|
|
|
@ -215,10 +215,10 @@ void setPushConnectionEnabled(JNIEnv *env, jclass c, jint instanceNum, jboolean
|
|||
ConnectionsManager::getInstance(instanceNum).setPushConnectionEnabled(value);
|
||||
}
|
||||
|
||||
void applyDnsConfig(JNIEnv *env, jclass c, jint instanceNum, jlong address, jstring phone) {
|
||||
void applyDnsConfig(JNIEnv *env, jclass c, jint instanceNum, jlong address, jstring phone, jint date) {
|
||||
const char *phoneStr = env->GetStringUTFChars(phone, 0);
|
||||
|
||||
ConnectionsManager::getInstance(instanceNum).applyDnsConfig((NativeByteBuffer *) (intptr_t) address, phoneStr);
|
||||
ConnectionsManager::getInstance(instanceNum).applyDnsConfig((NativeByteBuffer *) (intptr_t) address, phoneStr, date);
|
||||
if (phoneStr != 0) {
|
||||
env->ReleaseStringUTFChars(phone, phoneStr);
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ static JNINativeMethod ConnectionsManagerMethods[] = {
|
|||
{"native_setNetworkAvailable", "(IZIZ)V", (void *) setNetworkAvailable},
|
||||
{"native_setPushConnectionEnabled", "(IZ)V", (void *) setPushConnectionEnabled},
|
||||
{"native_setJava", "(Z)V", (void *) setJava},
|
||||
{"native_applyDnsConfig", "(IJLjava/lang/String;)V", (void *) applyDnsConfig},
|
||||
{"native_applyDnsConfig", "(IJLjava/lang/String;I)V", (void *) applyDnsConfig},
|
||||
{"native_checkProxy", "(ILjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/telegram/tgnet/RequestTimeDelegate;)J", (void *) checkProxy},
|
||||
{"native_onHostNameResolved", "(Ljava/lang/String;JLjava/lang/String;)V", (void *) onHostNameResolved}
|
||||
};
|
||||
|
|
|
@ -338,7 +338,7 @@ void Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoInfo(JNIEnv *e
|
|||
}
|
||||
}
|
||||
|
||||
jlong Java_org_telegram_ui_Components_AnimatedFileDrawable_createDecoder(JNIEnv *env, jclass clazz, jstring src, jintArray data, jint account, jlong streamFileSize, jobject stream) {
|
||||
jlong Java_org_telegram_ui_Components_AnimatedFileDrawable_createDecoder(JNIEnv *env, jclass clazz, jstring src, jintArray data, jint account, jlong streamFileSize, jobject stream, jboolean preview) {
|
||||
VideoInfo *info = new VideoInfo();
|
||||
|
||||
char const *srcString = env->GetStringUTFChars(src, 0);
|
||||
|
@ -377,6 +377,9 @@ jlong Java_org_telegram_ui_Components_AnimatedFileDrawable_createDecoder(JNIEnv
|
|||
return 0;
|
||||
}
|
||||
info->fmt_ctx->flags |= AVFMT_FLAG_FAST_SEEK;
|
||||
if (preview) {
|
||||
info->fmt_ctx->flags |= AVFMT_FLAG_NOBUFFER;
|
||||
}
|
||||
} else {
|
||||
if ((ret = avformat_open_input(&info->fmt_ctx, info->src, NULL, NULL)) < 0) {
|
||||
LOGE("can't open source file %s, %s", info->src, av_err2str(ret));
|
||||
|
@ -478,7 +481,7 @@ void Java_org_telegram_ui_Components_AnimatedFileDrawable_prepareToSeek(JNIEnv *
|
|||
info->seeking = true;
|
||||
}
|
||||
|
||||
void Java_org_telegram_ui_Components_AnimatedFileDrawable_seekToMs(JNIEnv *env, jclass clazz, jlong ptr, jlong ms) {
|
||||
void Java_org_telegram_ui_Components_AnimatedFileDrawable_seekToMs(JNIEnv *env, jclass clazz, jlong ptr, jlong ms, jboolean precise) {
|
||||
if (ptr == NULL) {
|
||||
return;
|
||||
}
|
||||
|
@ -491,6 +494,9 @@ void Java_org_telegram_ui_Components_AnimatedFileDrawable_seekToMs(JNIEnv *env,
|
|||
return;
|
||||
} else {
|
||||
avcodec_flush_buffers(info->video_dec_ctx);
|
||||
if (!precise) {
|
||||
return;
|
||||
}
|
||||
int got_frame = 0;
|
||||
int32_t tries = 1000;
|
||||
while (tries > 0) {
|
||||
|
@ -544,7 +550,7 @@ void Java_org_telegram_ui_Components_AnimatedFileDrawable_seekToMs(JNIEnv *env,
|
|||
}
|
||||
}
|
||||
|
||||
jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *env, jclass clazz, jlong ptr, jobject bitmap, jintArray data, jint stride) {
|
||||
jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *env, jclass clazz, jlong ptr, jobject bitmap, jintArray data, jint stride, jboolean preview) {
|
||||
if (ptr == NULL || bitmap == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -552,7 +558,8 @@ jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *
|
|||
VideoInfo *info = (VideoInfo *) (intptr_t) ptr;
|
||||
int ret = 0;
|
||||
int got_frame = 0;
|
||||
int32_t triesCount = 6;
|
||||
int32_t triesCount = preview ? 50 : 6;
|
||||
//info->has_decoded_frames = false;
|
||||
while (!info->stopped && triesCount != 0) {
|
||||
if (info->pkt.size == 0) {
|
||||
ret = av_read_frame(info->fmt_ctx, &info->pkt);
|
||||
|
@ -586,7 +593,7 @@ jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *
|
|||
LOGE("can't decode packet flushed %s", info->src);
|
||||
return 0;
|
||||
}
|
||||
if (got_frame == 0) {
|
||||
if (!preview && got_frame == 0) {
|
||||
if (info->has_decoded_frames) {
|
||||
if ((ret = av_seek_frame(info->fmt_ctx, info->video_stream_idx, 0, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME)) < 0) {
|
||||
LOGE("can't seek to begin of file %s, %s", info->src, av_err2str(ret));
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <lz4.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <map>
|
||||
#include <tgnet/ConnectionsManager.h>
|
||||
#include <tgnet/FileLog.h>
|
||||
#include "c_utils.h"
|
||||
|
@ -35,12 +36,24 @@ typedef struct LottieInfo {
|
|||
bool nextFrameIsCacheFrame = false;
|
||||
};
|
||||
|
||||
jlong Java_org_telegram_ui_Components_RLottieDrawable_create(JNIEnv *env, jclass clazz, jstring src, jintArray data, jboolean precache) {
|
||||
jlong Java_org_telegram_ui_Components_RLottieDrawable_create(JNIEnv *env, jclass clazz, jstring src, jintArray data, jboolean precache, jintArray colorReplacement) {
|
||||
LottieInfo *info = new LottieInfo();
|
||||
|
||||
std::map<int32_t, int32_t> colors;
|
||||
if (colorReplacement != nullptr) {
|
||||
jint *arr = env->GetIntArrayElements(colorReplacement, 0);
|
||||
if (arr != nullptr) {
|
||||
jsize len = env->GetArrayLength(colorReplacement);
|
||||
for (int32_t a = 0; a < len / 2; a++) {
|
||||
colors[arr[a * 2]] = arr[a * 2 + 1];
|
||||
}
|
||||
env->ReleaseIntArrayElements(colorReplacement, arr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
char const *srcString = env->GetStringUTFChars(src, 0);
|
||||
info->path = srcString;
|
||||
info->animation = rlottie::Animation::loadFromFile(info->path);
|
||||
info->animation = rlottie::Animation::loadFromFile(info->path, colors);
|
||||
if (srcString != 0) {
|
||||
env->ReleaseStringUTFChars(src, srcString);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <future>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef LOT_BUILD
|
||||
|
@ -257,7 +258,7 @@ public:
|
|||
* @internal
|
||||
*/
|
||||
static std::unique_ptr<Animation>
|
||||
loadFromFile(const std::string &path);
|
||||
loadFromFile(const std::string &path, std::map<int32_t, int32_t> &colorReplacement);
|
||||
|
||||
/**
|
||||
* @brief Constructs an animation object from JSON string data.
|
||||
|
|
|
@ -136,7 +136,7 @@ std::unique_ptr<Animation> Animation::loadFromData(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Animation> Animation::loadFromFile(const std::string &path)
|
||||
std::unique_ptr<Animation> Animation::loadFromFile(const std::string &path, std::map<int32_t, int32_t> &colorReplacement)
|
||||
{
|
||||
if (path.empty()) {
|
||||
vWarning << "File path is empty";
|
||||
|
@ -144,7 +144,7 @@ std::unique_ptr<Animation> Animation::loadFromFile(const std::string &path)
|
|||
}
|
||||
|
||||
LottieLoader loader;
|
||||
if (loader.load(path)) {
|
||||
if (loader.load(path, colorReplacement)) {
|
||||
auto animation = std::unique_ptr<Animation>(new Animation);
|
||||
animation->d->init(loader.model());
|
||||
return animation;
|
||||
|
|
|
@ -75,7 +75,7 @@ static std::string dirname(const std::string &path)
|
|||
return std::string(path, 0, len);
|
||||
}
|
||||
|
||||
bool LottieLoader::load(const std::string &path)
|
||||
bool LottieLoader::load(const std::string &path, std::map<int32_t, int32_t> &colorReplacement)
|
||||
{
|
||||
mModel = LottieFileCache::instance().find(path);
|
||||
if (mModel) return true;
|
||||
|
@ -90,7 +90,7 @@ bool LottieLoader::load(const std::string &path)
|
|||
std::stringstream buf;
|
||||
buf << f.rdbuf();
|
||||
|
||||
LottieParser parser(const_cast<char *>(buf.str().data()), dirname(path).c_str());
|
||||
LottieParser parser(const_cast<char *>(buf.str().data()), dirname(path).c_str(), colorReplacement);
|
||||
if (parser.hasParsingError()) {
|
||||
f.close();
|
||||
return false;
|
||||
|
@ -110,8 +110,8 @@ bool LottieLoader::loadFromData(std::string &&jsonData, const std::string &key,
|
|||
mModel = LottieFileCache::instance().find(key);
|
||||
if (mModel) return true;
|
||||
|
||||
LottieParser parser(const_cast<char *>(jsonData.c_str()),
|
||||
resourcePath.c_str());
|
||||
std::map<int32_t, int32_t> colors;
|
||||
LottieParser parser(const_cast<char *>(jsonData.c_str()), resourcePath.c_str(), colors);
|
||||
mModel = parser.model();
|
||||
LottieFileCache::instance().add(key, mModel);
|
||||
|
||||
|
|
|
@ -19,14 +19,15 @@
|
|||
#ifndef LOTTIELOADER_H
|
||||
#define LOTTIELOADER_H
|
||||
|
||||
#include<sstream>
|
||||
#include<memory>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
class LOTModel;
|
||||
class LottieLoader
|
||||
{
|
||||
public:
|
||||
bool load(const std::string &filePath);
|
||||
bool load(const std::string &filePath, std::map<int32_t, int32_t> &colorReplacement);
|
||||
bool loadFromData(std::string &&jsonData, const std::string &key, const std::string &resourcePath);
|
||||
std::shared_ptr<LOTModel> model();
|
||||
private:
|
||||
|
|
|
@ -210,7 +210,7 @@ void LOTGradient::populate(VGradientStops &stops, int frameNo)
|
|||
int j = 0;
|
||||
for (int i = 0; i < colorPoints; i++) {
|
||||
float colorStop = ptr[0];
|
||||
LottieColor color = LottieColor(ptr[1], ptr[2], ptr[3]);
|
||||
LottieColor color = LottieColor(ptr[3], ptr[2], ptr[1]);
|
||||
if (opacityArraySize) {
|
||||
if (j == opacityArraySize) {
|
||||
// already reached the end
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
|
||||
#include <array>
|
||||
#include <sstream>
|
||||
#include <tgnet/FileLog.h>
|
||||
|
||||
#include "lottiemodel.h"
|
||||
#include "rapidjson/document.h"
|
||||
|
@ -181,8 +182,8 @@ protected:
|
|||
|
||||
class LottieParserImpl : protected LookaheadParserHandler {
|
||||
public:
|
||||
LottieParserImpl(char *str, const char *dir_path)
|
||||
: LookaheadParserHandler(str), mDirPath(dir_path)
|
||||
LottieParserImpl(char *str, const char *dir_path, std::map<int32_t, int32_t> &colorReplacement)
|
||||
: LookaheadParserHandler(str), mDirPath(dir_path), colorMap(colorReplacement)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -286,6 +287,8 @@ protected:
|
|||
std::vector<std::shared_ptr<LOTLayerData>> mLayersToUpdate;
|
||||
std::string mDirPath;
|
||||
std::vector<LayerInfo> mLayerInfoList;
|
||||
std::map<int32_t, int32_t> colorMap;
|
||||
|
||||
void SkipOut(int depth);
|
||||
bool parsingError{false};
|
||||
};
|
||||
|
@ -840,17 +843,31 @@ LottieColor LottieParserImpl::toColor(const char *str)
|
|||
}
|
||||
|
||||
char tmp[3] = {'\0', '\0', '\0'};
|
||||
|
||||
tmp[0] = str[1];
|
||||
tmp[1] = str[2];
|
||||
color.b = std::strtol(tmp, NULL, 16) / 255.0;
|
||||
|
||||
long b = std::strtol(tmp, NULL, 16);
|
||||
tmp[0] = str[3];
|
||||
tmp[1] = str[4];
|
||||
color.g = std::strtol(tmp, NULL, 16) / 255.0;
|
||||
|
||||
long g = std::strtol(tmp, NULL, 16);
|
||||
tmp[0] = str[5];
|
||||
tmp[1] = str[6];
|
||||
color.r = std::strtol(tmp, NULL, 16) / 255.0;
|
||||
long r = std::strtol(tmp, NULL, 16);
|
||||
|
||||
if (!colorMap.empty()) {
|
||||
int32_t c = (int32_t) (((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff));
|
||||
std::map<int32_t, int32_t>::iterator iter = colorMap.find(c);
|
||||
if (iter != colorMap.end()) {
|
||||
c = iter->second;
|
||||
b = (c >> 16) & 0xff;
|
||||
g = (c >> 8) & 0xff;
|
||||
r = (c) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
color.r = r / 255.0f;
|
||||
color.g = g / 255.0f;
|
||||
color.b = b / 255.0f;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
@ -1095,6 +1112,10 @@ std::shared_ptr<LOTMaskData> LottieParserImpl::parseMaskObject()
|
|||
obj->mInv = GetBool();
|
||||
} else if (0 == strcmp(key, "mode")) {
|
||||
const char *str = GetString();
|
||||
if (str == nullptr) {
|
||||
parsingError = true;
|
||||
return sharedMask;
|
||||
}
|
||||
switch (str[0]) {
|
||||
case 'n':
|
||||
obj->mMode = LOTMaskData::Mode::None;
|
||||
|
@ -1260,7 +1281,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGroupObject() {
|
|||
staticFlag &= child.get()->isStatic();
|
||||
}
|
||||
|
||||
group->setStatic(staticFlag && group->mTransform->isStatic());
|
||||
if (group->mTransform) {
|
||||
group->setStatic(staticFlag && group->mTransform->isStatic());
|
||||
}
|
||||
|
||||
return sharedGroup;
|
||||
}
|
||||
|
@ -2005,6 +2028,20 @@ void LottieParserImpl::getValue(LottieColor &color)
|
|||
parsingError = true;
|
||||
return;
|
||||
}
|
||||
if (!colorMap.empty()) {
|
||||
int32_t r = (int32_t) (val[2] * 255);
|
||||
int32_t g = (int32_t) (val[1] * 255);
|
||||
int32_t b = (int32_t) (val[0] * 255);
|
||||
|
||||
int32_t c = (int32_t) (((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff));
|
||||
std::map<int32_t, int32_t>::iterator iter = colorMap.find(c);
|
||||
if (iter != colorMap.end()) {
|
||||
c = iter->second;
|
||||
val[0] = ((c >> 16) & 0xff) / 255.0f;
|
||||
val[1] = ((c >> 8) & 0xff) / 255.0f;
|
||||
val[2] = ((c) & 0xff) / 255.0f;
|
||||
}
|
||||
}
|
||||
color.r = val[2];
|
||||
color.g = val[1];
|
||||
color.b = val[0];
|
||||
|
@ -2590,8 +2627,8 @@ LottieParser::~LottieParser()
|
|||
delete d;
|
||||
}
|
||||
|
||||
LottieParser::LottieParser(char *str, const char *dir_path)
|
||||
: d(new LottieParserImpl(str, dir_path))
|
||||
LottieParser::LottieParser(char *str, const char *dir_path, std::map<int32_t, int32_t> &colorReplacement)
|
||||
: d(new LottieParserImpl(str, dir_path, colorReplacement))
|
||||
{
|
||||
d->parseComposition();
|
||||
if (d->hasParsingError()) {
|
||||
|
|
|
@ -20,12 +20,13 @@
|
|||
#define LOTTIEPARSER_H
|
||||
|
||||
#include "lottiemodel.h"
|
||||
#include <map>
|
||||
|
||||
class LottieParserImpl;
|
||||
class LottieParser {
|
||||
public:
|
||||
~LottieParser();
|
||||
LottieParser(char* str, const char *dir_path);
|
||||
LottieParser(char* str, const char *dir_path, std::map<int32_t, int32_t> &colorReplacement);
|
||||
std::shared_ptr<LOTModel> model();
|
||||
bool hasParsingError();
|
||||
private:
|
||||
|
|
|
@ -209,6 +209,9 @@ VPath VDasher::dashed(const VPath &path)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (mResult.points().size() > SHRT_MAX) {
|
||||
mResult.reset();
|
||||
}
|
||||
return std::move(mResult);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "vraster.h"
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <tgnet/FileLog.h>
|
||||
#include "config.h"
|
||||
#include "v_ft_raster.h"
|
||||
#include "v_ft_stroker.h"
|
||||
|
@ -102,6 +103,9 @@ void FTOutline::convert(const VPath &path)
|
|||
{
|
||||
const std::vector<VPath::Element> &elements = path.elements();
|
||||
const std::vector<VPointF> & points = path.points();
|
||||
if (points.size() > SHRT_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
grow(points.size(), path.segments());
|
||||
|
||||
|
|
|
@ -443,17 +443,537 @@ void TL_user::serializeToStream(NativeByteBuffer *stream) {
|
|||
}
|
||||
}
|
||||
|
||||
TL_auth_authorization *TL_auth_authorization::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||
if (TL_auth_authorization::constructor != constructor) {
|
||||
error = true;
|
||||
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_auth_authorization", constructor);
|
||||
return nullptr;
|
||||
InputPeer *InputPeer::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||
InputPeer *result = nullptr;
|
||||
switch (constructor) {
|
||||
case 0x7da07ec9:
|
||||
result = new TL_inputPeerSelf();
|
||||
break;
|
||||
case 0x7b8e7de6:
|
||||
result = new TL_inputPeerUser();
|
||||
break;
|
||||
case 0x179be863:
|
||||
result = new TL_inputPeerChat();
|
||||
break;
|
||||
case 0x17bae2e6:
|
||||
result = new TL_inputPeerUserFromMessage();
|
||||
break;
|
||||
case 0x9c95f7bb:
|
||||
result = new TL_inputPeerChannelFromMessage();
|
||||
break;
|
||||
case 0x20adaef8:
|
||||
result = new TL_inputPeerChannel();
|
||||
break;
|
||||
case 0x7f3b18ea:
|
||||
result = new TL_inputPeerEmpty();
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in InputPeer", constructor);
|
||||
return nullptr;
|
||||
}
|
||||
TL_auth_authorization *result = new TL_auth_authorization();
|
||||
result->readParams(stream, instanceNum, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TL_inputPeerSelf::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
}
|
||||
|
||||
void TL_inputPeerUser::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
user_id = stream->readInt32(&error);
|
||||
access_hash = stream->readInt64(&error);
|
||||
}
|
||||
|
||||
void TL_inputPeerUser::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(user_id);
|
||||
stream->writeInt64(access_hash);
|
||||
}
|
||||
|
||||
void TL_inputPeerChat::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
chat_id = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_inputPeerChat::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(chat_id);
|
||||
}
|
||||
|
||||
void TL_inputPeerUserFromMessage::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
peer = std::unique_ptr<InputPeer>(InputPeer::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
|
||||
msg_id = stream->readInt32(&error);
|
||||
user_id = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_inputPeerUserFromMessage::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
peer->serializeToStream(stream);
|
||||
stream->writeInt32(msg_id);
|
||||
stream->writeInt32(user_id);
|
||||
}
|
||||
|
||||
void TL_inputPeerChannelFromMessage::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
peer = std::unique_ptr<InputPeer>(InputPeer::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
|
||||
msg_id = stream->readInt32(&error);
|
||||
channel_id = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_inputPeerChannelFromMessage::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
peer->serializeToStream(stream);
|
||||
stream->writeInt32(msg_id);
|
||||
stream->writeInt32(channel_id);
|
||||
}
|
||||
|
||||
void TL_inputPeerChannel::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
channel_id = stream->readInt32(&error);
|
||||
access_hash = stream->readInt64(&error);
|
||||
}
|
||||
|
||||
void TL_inputPeerChannel::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(channel_id);
|
||||
stream->writeInt64(access_hash);
|
||||
}
|
||||
|
||||
void TL_inputPeerEmpty::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
}
|
||||
|
||||
InputUser *InputUser::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||
InputUser *result = nullptr;
|
||||
switch (constructor) {
|
||||
case 0xf7c1b13f:
|
||||
result = new TL_inputUserSelf();
|
||||
break;
|
||||
case 0xd8292816:
|
||||
result = new TL_inputUser();
|
||||
break;
|
||||
case 0xb98886cf:
|
||||
result = new TL_inputUserEmpty();
|
||||
break;
|
||||
case 0x2d117597:
|
||||
result = new TL_inputUserFromMessage();
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in InputUser", constructor);
|
||||
return nullptr;
|
||||
}
|
||||
result->readParams(stream, instanceNum, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TL_inputUserSelf::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
}
|
||||
|
||||
void TL_inputUser::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
user_id = stream->readInt32(&error);
|
||||
access_hash = stream->readInt64(&error);
|
||||
}
|
||||
|
||||
void TL_inputUser::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(user_id);
|
||||
stream->writeInt64(access_hash);
|
||||
}
|
||||
|
||||
void TL_inputUserEmpty::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
}
|
||||
|
||||
void TL_inputUserFromMessage::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
peer = std::unique_ptr<InputPeer>(InputPeer::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
|
||||
msg_id = stream->readInt32(&error);
|
||||
user_id = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_inputUserFromMessage::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
peer->serializeToStream(stream);
|
||||
stream->writeInt32(msg_id);
|
||||
stream->writeInt32(user_id);
|
||||
}
|
||||
|
||||
MessageEntity *MessageEntity::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||
MessageEntity *result = nullptr;
|
||||
switch (constructor) {
|
||||
case 0x76a6d327:
|
||||
result = new TL_messageEntityTextUrl();
|
||||
break;
|
||||
case 0x6cef8ac7:
|
||||
result = new TL_messageEntityBotCommand();
|
||||
break;
|
||||
case 0x64e475c2:
|
||||
result = new TL_messageEntityEmail();
|
||||
break;
|
||||
case 0x73924be0:
|
||||
result = new TL_messageEntityPre();
|
||||
break;
|
||||
case 0xbb92ba95:
|
||||
result = new TL_messageEntityUnknown();
|
||||
break;
|
||||
case 0x6ed02538:
|
||||
result = new TL_messageEntityUrl();
|
||||
break;
|
||||
case 0x826f8b60:
|
||||
result = new TL_messageEntityItalic();
|
||||
break;
|
||||
case 0xfa04579d:
|
||||
result = new TL_messageEntityMention();
|
||||
break;
|
||||
case 0x352dca58:
|
||||
result = new TL_messageEntityMentionName();
|
||||
break;
|
||||
case 0x208e68c9:
|
||||
result = new TL_inputMessageEntityMentionName();
|
||||
break;
|
||||
case 0x4c4e743f:
|
||||
result = new TL_messageEntityCashtag();
|
||||
break;
|
||||
case 0xbd610bc9:
|
||||
result = new TL_messageEntityBold();
|
||||
break;
|
||||
case 0x6f635b0d:
|
||||
result = new TL_messageEntityHashtag();
|
||||
break;
|
||||
case 0x28a20571:
|
||||
result = new TL_messageEntityCode();
|
||||
break;
|
||||
case 0xbf0693d4:
|
||||
result = new TL_messageEntityStrike();
|
||||
break;
|
||||
case 0x20df5d0:
|
||||
result = new TL_messageEntityBlockquote();
|
||||
break;
|
||||
case 0x9c4e7e8b:
|
||||
result = new TL_messageEntityUnderline();
|
||||
break;
|
||||
case 0x9b69e34b:
|
||||
result = new TL_messageEntityPhone();
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in MessageEntity", constructor);
|
||||
return nullptr;
|
||||
}
|
||||
result->readParams(stream, instanceNum, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TL_messageEntityTextUrl::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
url = stream->readString(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityTextUrl::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
stream->writeString(url);
|
||||
}
|
||||
|
||||
void TL_messageEntityBotCommand::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityBotCommand::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityEmail::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityEmail::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityPre::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
language = stream->readString(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityPre::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
stream->writeString(language);
|
||||
}
|
||||
|
||||
void TL_messageEntityUnknown::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityUnknown::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityUrl::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityUrl::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityItalic::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityItalic::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityMention::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityMention::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityMentionName::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
user_id = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityMentionName::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
stream->writeInt32(user_id);
|
||||
}
|
||||
|
||||
void TL_inputMessageEntityMentionName::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
user_id = std::unique_ptr<InputUser>(InputUser::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
|
||||
}
|
||||
|
||||
void TL_inputMessageEntityMentionName::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
user_id->serializeToStream(stream);
|
||||
}
|
||||
|
||||
void TL_messageEntityCashtag::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityCashtag::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityBold::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityBold::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityHashtag::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityHashtag::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityCode::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityCode::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityStrike::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityStrike::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityBlockquote::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityBlockquote::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityUnderline::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityUnderline::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
void TL_messageEntityPhone::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
offset = stream->readInt32(&error);
|
||||
length = stream->readInt32(&error);
|
||||
}
|
||||
|
||||
void TL_messageEntityPhone::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(offset);
|
||||
stream->writeInt32(length);
|
||||
}
|
||||
|
||||
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);
|
||||
return nullptr;
|
||||
}
|
||||
TL_dataJSON *result = new TL_dataJSON();
|
||||
result->readParams(stream, instanceNum, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TL_dataJSON::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
data = stream->readString(&error);
|
||||
}
|
||||
|
||||
void TL_dataJSON::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeString(data);
|
||||
}
|
||||
|
||||
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);
|
||||
return nullptr;
|
||||
}
|
||||
TL_help_termsOfService *result = new TL_help_termsOfService();
|
||||
result->readParams(stream, instanceNum, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TL_help_termsOfService::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
flags = stream->readInt32(&error);
|
||||
popup = (flags & 1) != 0;
|
||||
id = std::unique_ptr<TL_dataJSON>(TL_dataJSON::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
|
||||
text = stream->readString(&error);
|
||||
int magic = stream->readInt32(&error);
|
||||
if (magic != 0x1cb5c415) {
|
||||
error = true;
|
||||
if (LOGS_ENABLED) DEBUG_E("wrong Vector magic, got %x", magic);
|
||||
return;
|
||||
}
|
||||
int count = stream->readInt32(&error);
|
||||
for (int a = 0; a < count; a++) {
|
||||
MessageEntity *object = MessageEntity::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error);
|
||||
if (object == nullptr) {
|
||||
return;
|
||||
}
|
||||
entities.push_back(std::unique_ptr<MessageEntity>(object));
|
||||
}
|
||||
if ((flags & 2) != 0) {
|
||||
min_age_confirm = stream->readInt32(&error);
|
||||
}
|
||||
}
|
||||
|
||||
void TL_help_termsOfService::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
flags = popup ? (flags | 1) : (flags & ~1);
|
||||
stream->writeInt32(flags);
|
||||
id->serializeToStream(stream);
|
||||
stream->writeString(text);
|
||||
stream->writeInt32(0x1cb5c415);
|
||||
int32_t count = (int32_t) entities.size();
|
||||
stream->writeInt32(count);
|
||||
for (int a = 0; a < count; a++) {
|
||||
entities[a]->serializeToStream(stream);
|
||||
}
|
||||
if ((flags & 2) != 0) {
|
||||
stream->writeInt32(min_age_confirm);
|
||||
}
|
||||
}
|
||||
|
||||
auth_Authorization *auth_Authorization::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||
auth_Authorization *result = nullptr;
|
||||
switch (constructor) {
|
||||
case 0x44747e9a:
|
||||
result = new TL_auth_authorizationSignUpRequired();
|
||||
break;
|
||||
case 0xcd050916:
|
||||
result = new TL_auth_authorization();
|
||||
break;
|
||||
default:
|
||||
error = true;
|
||||
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in auth_Authorization", constructor);
|
||||
return nullptr;
|
||||
}
|
||||
result->readParams(stream, instanceNum, error);
|
||||
return result;
|
||||
}
|
||||
|
||||
void TL_auth_authorizationSignUpRequired::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
flags = stream->readInt32(&error);
|
||||
if ((flags & 1) != 0) {
|
||||
terms_of_service = std::unique_ptr<TL_help_termsOfService>(TL_help_termsOfService::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
|
||||
}
|
||||
}
|
||||
|
||||
void TL_auth_authorizationSignUpRequired::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(flags);
|
||||
if ((flags & 1) != 0) {
|
||||
terms_of_service->serializeToStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
void TL_auth_authorization::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||
flags = stream->readInt32(&error);
|
||||
if ((flags & 1) != 0) {
|
||||
|
@ -462,6 +982,15 @@ void TL_auth_authorization::readParams(NativeByteBuffer *stream, int32_t instanc
|
|||
user = std::unique_ptr<User>(User::TLdeserialize(stream, stream->readUint32(&error), instanceNum, error));
|
||||
}
|
||||
|
||||
void TL_auth_authorization::serializeToStream(NativeByteBuffer *stream) {
|
||||
stream->writeInt32(constructor);
|
||||
stream->writeInt32(flags);
|
||||
if ((flags & 1) != 0) {
|
||||
stream->writeInt32(tmp_sessions);
|
||||
}
|
||||
user->serializeToStream(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;
|
||||
|
@ -496,7 +1025,7 @@ bool TL_auth_importAuthorization::isNeedLayer() {
|
|||
}
|
||||
|
||||
TLObject *TL_auth_importAuthorization::deserializeResponse(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||
return TL_auth_authorization::TLdeserialize(stream, constructor, instanceNum, error);
|
||||
return auth_Authorization::TLdeserialize(stream, constructor, instanceNum, error);
|
||||
}
|
||||
|
||||
void TL_auth_importAuthorization::serializeToStream(NativeByteBuffer *stream) {
|
||||
|
|
|
@ -315,8 +315,355 @@ public:
|
|||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_auth_authorization : public TLObject {
|
||||
class InputPeer : public TLObject {
|
||||
|
||||
public:
|
||||
int32_t user_id;
|
||||
int32_t chat_id;
|
||||
int32_t channel_id;
|
||||
int64_t access_hash;
|
||||
|
||||
static InputPeer *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
};
|
||||
|
||||
class TL_inputPeerSelf : public InputPeer {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x7da07ec9;
|
||||
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputPeerUser : public InputPeer {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x7b8e7de6;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputPeerChat : public InputPeer {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x179be863;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputPeerUserFromMessage : public InputPeer {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x17bae2e6;
|
||||
|
||||
std::unique_ptr<InputPeer> peer;
|
||||
int32_t msg_id;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputPeerChannelFromMessage : public InputPeer {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x9c95f7bb;
|
||||
|
||||
std::unique_ptr<InputPeer> peer;
|
||||
int32_t msg_id;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputPeerChannel : public InputPeer {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x20adaef8;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputPeerEmpty : public InputPeer {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x7f3b18ea;
|
||||
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class InputUser : public TLObject {
|
||||
|
||||
public:
|
||||
int32_t user_id;
|
||||
int64_t access_hash;
|
||||
|
||||
static InputUser *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
};
|
||||
|
||||
class TL_inputUserSelf : public InputUser {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0xf7c1b13f;
|
||||
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputUser : public InputUser {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0xd8292816;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputUserEmpty : public InputUser {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0xb98886cf;
|
||||
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputUserFromMessage : public InputUser {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x2d117597;
|
||||
|
||||
std::unique_ptr<InputPeer> peer;
|
||||
int32_t msg_id;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class MessageEntity : public TLObject {
|
||||
|
||||
public:
|
||||
int32_t offset;
|
||||
int32_t length;
|
||||
std::string url;
|
||||
std::string language;
|
||||
|
||||
static MessageEntity *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
};
|
||||
|
||||
class TL_messageEntityTextUrl : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x76a6d327;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityBotCommand : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x6cef8ac7;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityEmail : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x64e475c2;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityPre : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x73924be0;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityUnknown : public MessageEntity {
|
||||
public:
|
||||
static const uint32_t constructor = 0xbb92ba95;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityUrl : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x6ed02538;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityItalic : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x826f8b60;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityMention : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0xfa04579d;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityMentionName : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x352dca58;
|
||||
|
||||
int32_t user_id;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_inputMessageEntityMentionName : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x208e68c9;
|
||||
|
||||
std::unique_ptr<InputUser> user_id;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityCashtag : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x4c4e743f;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityBold : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0xbd610bc9;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityHashtag : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x6f635b0d;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityCode : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x28a20571;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityStrike : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0xbf0693d4;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityBlockquote : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x20df5d0;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityUnderline : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x9c4e7e8b;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_messageEntityPhone : public MessageEntity {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x9b69e34b;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_dataJSON : public TLObject {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x7d748d04;
|
||||
|
||||
std::string data;
|
||||
|
||||
static TL_dataJSON *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_help_termsOfService : public TLObject {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x780a0310;
|
||||
|
||||
int32_t flags;
|
||||
bool popup;
|
||||
std::unique_ptr<TL_dataJSON> id;
|
||||
std::string text;
|
||||
std::vector<std::unique_ptr<MessageEntity>> entities;
|
||||
int32_t min_age_confirm;
|
||||
|
||||
static TL_help_termsOfService *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class auth_Authorization : public TLObject {
|
||||
|
||||
public:
|
||||
static auth_Authorization *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
};
|
||||
|
||||
class TL_auth_authorizationSignUpRequired : public auth_Authorization {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0x44747e9a;
|
||||
|
||||
int32_t flags;
|
||||
std::unique_ptr<TL_help_termsOfService> terms_of_service;
|
||||
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_auth_authorization : public auth_Authorization {
|
||||
|
||||
public:
|
||||
static const uint32_t constructor = 0xcd050916;
|
||||
|
||||
|
@ -324,8 +671,8 @@ public:
|
|||
int32_t tmp_sessions;
|
||||
std::unique_ptr<User> user;
|
||||
|
||||
static TL_auth_authorization *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
class TL_auth_exportedAuthorization : public TLObject {
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
#include <openssl/sha.h>
|
||||
#include <algorithm>
|
||||
#include "Connection.h"
|
||||
#include "ConnectionsManager.h"
|
||||
#include "BuffersStorage.h"
|
||||
|
@ -219,7 +220,7 @@ void Connection::onReceivedData(NativeByteBuffer *buffer) {
|
|||
len = currentPacketLength + 4;
|
||||
}
|
||||
|
||||
if (currentProtocolType != ProtocolTypeDD && currentPacketLength % 4 != 0 || currentPacketLength > 2 * 1024 * 1024) {
|
||||
if (currentProtocolType != ProtocolTypeDD && currentProtocolType != ProtocolTypeTLS && currentPacketLength % 4 != 0 || currentPacketLength > 2 * 1024 * 1024) {
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received invalid packet length", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType);
|
||||
reconnect();
|
||||
return;
|
||||
|
@ -348,7 +349,7 @@ void Connection::connect() {
|
|||
lastPacketLength = 0;
|
||||
wasConnected = false;
|
||||
hasSomeDataSinceLastConnect = false;
|
||||
openConnection(hostAddress, hostPort, ipv6 != 0, ConnectionsManager::getInstance(currentDatacenter->instanceNum).currentNetworkType);
|
||||
openConnection(hostAddress, hostPort, secret, ipv6 != 0, ConnectionsManager::getInstance(currentDatacenter->instanceNum).currentNetworkType);
|
||||
if (connectionType == ConnectionTypeProxy) {
|
||||
setTimeout(5);
|
||||
} else if (connectionType == ConnectionTypePush) {
|
||||
|
@ -408,7 +409,7 @@ void Connection::setHasUsefullData() {
|
|||
}
|
||||
|
||||
bool Connection::allowsCustomPadding() {
|
||||
return currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeEF;
|
||||
return currentProtocolType == ProtocolTypeTLS || currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeEF;
|
||||
}
|
||||
|
||||
void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted) {
|
||||
|
@ -444,8 +445,10 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted
|
|||
}
|
||||
if (useSecret != 0) {
|
||||
std::string *currentSecret = getCurrentSecret(useSecret);
|
||||
if (currentSecret->length() == 34 && (*currentSecret)[0] == 'd' && (*currentSecret)[1] == 'd') {
|
||||
if (currentSecret->length() >= 17 && (*currentSecret)[0] == '\xdd') {
|
||||
currentProtocolType = ProtocolTypeDD;
|
||||
} else if (currentSecret->length() > 17 && (*currentSecret)[0] == '\xee') {
|
||||
currentProtocolType = ProtocolTypeTLS;
|
||||
} else {
|
||||
currentProtocolType = ProtocolTypeEF;
|
||||
}
|
||||
|
@ -464,7 +467,7 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted
|
|||
}
|
||||
} else {
|
||||
packetLength = buff->limit();
|
||||
if (currentProtocolType == ProtocolTypeDD) {
|
||||
if (currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeTLS) {
|
||||
RAND_bytes((uint8_t *) &additinalPacketSize, 4);
|
||||
if (!encrypted) {
|
||||
additinalPacketSize = additinalPacketSize % 257;
|
||||
|
@ -506,10 +509,10 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted
|
|||
RAND_bytes(bytes, 64);
|
||||
uint32_t val = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0]);
|
||||
uint32_t val2 = (bytes[7] << 24) | (bytes[6] << 16) | (bytes[5] << 8) | (bytes[4]);
|
||||
if (bytes[0] != 0xef && val != 0x44414548 && val != 0x54534f50 && val != 0x20544547 && val != 0x4954504f && val != 0xeeeeeeee && val != 0xdddddddd && val2 != 0x00000000) {
|
||||
if (currentProtocolType == ProtocolTypeTLS || bytes[0] != 0xef && val != 0x44414548 && val != 0x54534f50 && val != 0x20544547 && val != 0x4954504f && val != 0xeeeeeeee && val != 0xdddddddd && val != 0x02010316 && val2 != 0x00000000) {
|
||||
if (currentProtocolType == ProtocolTypeEF) {
|
||||
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xef;
|
||||
} else if (currentProtocolType == ProtocolTypeDD) {
|
||||
} else if (currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeTLS) {
|
||||
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xdd;
|
||||
} else if (currentProtocolType == ProtocolTypeEE) {
|
||||
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xee;
|
||||
|
@ -603,17 +606,6 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted
|
|||
}
|
||||
}
|
||||
|
||||
inline char char2int(char input) {
|
||||
if (input >= '0' && input <= '9') {
|
||||
return input - '0';
|
||||
} else if (input >= 'A' && input <= 'F') {
|
||||
return (char) (input - 'A' + 10);
|
||||
} else if (input >= 'a' && input <= 'f') {
|
||||
return (char) (input - 'a' + 10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline std::string *Connection::getCurrentSecret(uint8_t secretType) {
|
||||
if (secretType == 2) {
|
||||
return &secret;
|
||||
|
@ -630,16 +622,18 @@ inline void Connection::encryptKeyWithSecret(uint8_t *bytes, uint8_t secretType)
|
|||
}
|
||||
std::string *currentSecret = getCurrentSecret(secretType);
|
||||
size_t a = 0;
|
||||
if (currentSecret->length() == 34 && (*currentSecret)[0] == 'd' && (*currentSecret)[1] == 'd') {
|
||||
size_t size = std::min((size_t) 16, currentSecret->length());
|
||||
if (currentSecret->length() >= 17 && ((*currentSecret)[0] == '\xdd' || (*currentSecret)[0] == '\xee')) {
|
||||
a = 1;
|
||||
size = 17;
|
||||
}
|
||||
|
||||
SHA256_CTX sha256Ctx;
|
||||
SHA256_Init(&sha256Ctx);
|
||||
SHA256_Update(&sha256Ctx, bytes, 32);
|
||||
char b[1];
|
||||
for (; a < currentSecret->size() / 2; a++) {
|
||||
b[0] = (char) (char2int((*currentSecret)[a * 2]) * 16 + char2int((*currentSecret)[a * 2 + 1]));
|
||||
for (; a < size; a++) {
|
||||
b[0] = (char) (*currentSecret)[a];
|
||||
SHA256_Update(&sha256Ctx, b, 1);
|
||||
}
|
||||
SHA256_Final(bytes, &sha256Ctx);
|
||||
|
|
|
@ -64,7 +64,8 @@ private:
|
|||
enum ProtocolType {
|
||||
ProtocolTypeEF,
|
||||
ProtocolTypeEE,
|
||||
ProtocolTypeDD
|
||||
ProtocolTypeDD,
|
||||
ProtocolTypeTLS
|
||||
};
|
||||
|
||||
inline void encryptKeyWithSecret(uint8_t *array, uint8_t secretType);
|
||||
|
|
|
@ -8,12 +8,15 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <cerrno>
|
||||
#include <sys/socket.h>
|
||||
#include <memory.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <algorithm>
|
||||
#include "ByteStream.h"
|
||||
#include "ConnectionSocket.h"
|
||||
#include "FileLog.h"
|
||||
|
@ -23,11 +26,197 @@
|
|||
#include "Timer.h"
|
||||
#include "NativeByteBuffer.h"
|
||||
#include "BuffersStorage.h"
|
||||
#include "Connection.h"
|
||||
|
||||
#ifndef EPOLLRDHUP
|
||||
#define EPOLLRDHUP 0x2000
|
||||
#endif
|
||||
|
||||
#define MAX_GREASE 8
|
||||
|
||||
class TlsHello {
|
||||
public:
|
||||
|
||||
TlsHello() {
|
||||
RAND_bytes(grease, MAX_GREASE);
|
||||
for (int a = 0; a < MAX_GREASE; a++) {
|
||||
grease[a] = (uint8_t) ((grease[a] & 0xf0) + 0x0A);
|
||||
}
|
||||
for (size_t i = 1; i < MAX_GREASE; i += 2) {
|
||||
if (grease[i] == grease[i - 1]) {
|
||||
grease[i] ^= 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Op {
|
||||
enum class Type {
|
||||
String, Random, Zero, Domain, Grease, BeginScope, EndScope
|
||||
};
|
||||
Type type;
|
||||
size_t length;
|
||||
int seed;
|
||||
std::string data;
|
||||
|
||||
static Op string(const char str[], size_t len) {
|
||||
Op res;
|
||||
res.type = Type::String;
|
||||
res.data = std::string(str, len);
|
||||
return res;
|
||||
}
|
||||
|
||||
static Op random(size_t length) {
|
||||
Op res;
|
||||
res.type = Type::Random;
|
||||
res.length = length;
|
||||
return res;
|
||||
}
|
||||
|
||||
static Op zero(size_t length) {
|
||||
Op res;
|
||||
res.type = Type::Zero;
|
||||
res.length = length;
|
||||
return res;
|
||||
}
|
||||
|
||||
static Op domain() {
|
||||
Op res;
|
||||
res.type = Type::Domain;
|
||||
return res;
|
||||
}
|
||||
|
||||
static Op grease(int seed) {
|
||||
Op res;
|
||||
res.type = Type::Grease;
|
||||
res.seed = seed;
|
||||
return res;
|
||||
}
|
||||
|
||||
static Op begin_scope() {
|
||||
Op res;
|
||||
res.type = Type::BeginScope;
|
||||
return res;
|
||||
}
|
||||
|
||||
static Op end_scope() {
|
||||
Op res;
|
||||
res.type = Type::EndScope;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
static const TlsHello &getDefault() {
|
||||
static TlsHello result = [] {
|
||||
TlsHello res;
|
||||
res.ops = {
|
||||
Op::string("\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03", 11),
|
||||
Op::zero(32),
|
||||
Op::string("\x20", 1),
|
||||
Op::random(32),
|
||||
Op::string("\x00\x22", 2),
|
||||
Op::grease(0),
|
||||
Op::string("\x13\x01\x13\x02\x13\x03\xc0\x2b\xc0\x2f\xc0\x2c\xc0\x30\xcc\xa9\xcc\xa8\xc0\x13\xc0\x14\x00\x9c"
|
||||
"\x00\x9d\x00\x2f\x00\x35\x00\x0a\x01\x00\x01\x91", 36),
|
||||
Op::grease(2),
|
||||
Op::string("\x00\x00\x00\x00", 4),
|
||||
Op::begin_scope(),
|
||||
Op::begin_scope(),
|
||||
Op::string("\x00", 1),
|
||||
Op::begin_scope(),
|
||||
Op::domain(),
|
||||
Op::end_scope(),
|
||||
Op::end_scope(),
|
||||
Op::end_scope(),
|
||||
Op::string("\x00\x17\x00\x00\xff\x01\x00\x01\x00\x00\x0a\x00\x0a\x00\x08", 15),
|
||||
Op::grease(4),
|
||||
Op::string(
|
||||
"\x00\x1d\x00\x17\x00\x18\x00\x0b\x00\x02\x01\x00\x00\x23\x00\x00\x00\x10\x00\x0e\x00\x0c\x02\x68\x32\x08"
|
||||
"\x68\x74\x74\x70\x2f\x31\x2e\x31\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x0d\x00\x14\x00\x12\x04\x03\x08"
|
||||
"\x04\x04\x01\x05\x03\x08\x05\x05\x01\x08\x06\x06\x01\x02\x01\x00\x12\x00\x00\x00\x33\x00\x2b\x00\x29", 77),
|
||||
Op::grease(4),
|
||||
Op::string("\x00\x01\x00\x00\x1d\x00\x20", 7),
|
||||
Op::random(32),
|
||||
Op::string("\x00\x2d\x00\x02\x01\x01\x00\x2b\x00\x0b\x0a", 11),
|
||||
Op::grease(6),
|
||||
Op::string("\x03\x04\x03\x03\x03\x02\x03\x01\x00\x1b\x00\x03\x02\x00\x02", 15),
|
||||
Op::grease(3),
|
||||
Op::string("\x00\x01\x00\x00\x15", 5)};
|
||||
return res;
|
||||
}();
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t writeToBuffer(uint8_t *data) {
|
||||
uint32_t offset = 0;
|
||||
for (auto op : ops) {
|
||||
writeOp(op, data, offset);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
uint32_t writePadding(uint8_t *data, uint32_t length) {
|
||||
if (length > 515) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t size = 515 - length;
|
||||
memset(data + length + 2, 0, size);
|
||||
data[length] = static_cast<uint8_t>((size >> 8) & 0xff);
|
||||
data[length + 1] = static_cast<uint8_t>(size & 0xff);
|
||||
return length + size + 2;
|
||||
}
|
||||
|
||||
void setDomain(std::string value) {
|
||||
domain = std::move(value);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<Op> ops;
|
||||
uint8_t grease[MAX_GREASE];
|
||||
std::vector<size_t> scopeOffset;
|
||||
std::string domain;
|
||||
|
||||
void writeOp(const TlsHello::Op &op, uint8_t *data, uint32_t &offset) {
|
||||
using Type = TlsHello::Op::Type;
|
||||
switch (op.type) {
|
||||
case Type::String:
|
||||
memcpy(data + offset, op.data.data(), op.data.size());
|
||||
offset += op.data.size();
|
||||
break;
|
||||
case Type::Random:
|
||||
RAND_bytes(data + offset, (size_t) op.length);
|
||||
offset += op.length;
|
||||
break;
|
||||
case Type::Zero:
|
||||
std::memset(data + offset, 0, op.length);
|
||||
offset += op.length;
|
||||
break;
|
||||
case Type::Domain: {
|
||||
memcpy(data + offset, domain.data(), domain.size());
|
||||
offset += domain.size();
|
||||
break;
|
||||
}
|
||||
case Type::Grease: {
|
||||
data[offset] = grease[op.seed];
|
||||
data[offset + 1] = grease[op.seed];
|
||||
offset += 2;
|
||||
break;
|
||||
}
|
||||
case Type::BeginScope:
|
||||
scopeOffset.push_back(offset);
|
||||
offset += 2;
|
||||
break;
|
||||
case Type::EndScope: {
|
||||
auto begin_offset = scopeOffset.back();
|
||||
scopeOffset.pop_back();
|
||||
size_t size = offset - begin_offset - 2;
|
||||
data[begin_offset] = static_cast<uint8_t>((size >> 8) & 0xff);
|
||||
data[begin_offset + 1] = static_cast<uint8_t>(size & 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ConnectionSocket::ConnectionSocket(int32_t instance) {
|
||||
instanceNum = instance;
|
||||
outgoingByteStream = new ByteStream();
|
||||
|
@ -44,15 +233,24 @@ ConnectionSocket::~ConnectionSocket() {
|
|||
delete eventObject;
|
||||
eventObject = nullptr;
|
||||
}
|
||||
if (tempBuffer != nullptr) {
|
||||
delete tempBuffer;
|
||||
tempBuffer = nullptr;
|
||||
}
|
||||
if (tlsBuffer != nullptr) {
|
||||
tlsBuffer->reuse();
|
||||
tlsBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionSocket::openConnection(std::string address, uint16_t port, bool ipv6, int32_t networkType) {
|
||||
void ConnectionSocket::openConnection(std::string address, uint16_t port, std::string secret, bool ipv6, int32_t networkType) {
|
||||
currentNetworkType = networkType;
|
||||
isIpv6 = ipv6;
|
||||
currentAddress = address;
|
||||
currentPort = port;
|
||||
waitingForHostResolve = "";
|
||||
adjustWriteOpAfterResolve = false;
|
||||
tlsState = 0;
|
||||
ConnectionsManager::getInstance(instanceNum).attachConnection(this);
|
||||
|
||||
memset(&socketAddress, 0, sizeof(sockaddr_in));
|
||||
|
@ -67,16 +265,33 @@ void ConnectionSocket::openConnection(std::string address, uint16_t port, bool i
|
|||
proxySecret = &ConnectionsManager::getInstance(instanceNum).proxySecret;
|
||||
}
|
||||
|
||||
if (proxyAddress != nullptr && !proxyAddress->empty()) {
|
||||
if (!proxyAddress->empty()) {
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) connecting via proxy %s:%d secret[%d]", this, proxyAddress->c_str(), proxyPort, (int) proxySecret->size());
|
||||
if ((socketFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) can't create proxy socket", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
}
|
||||
uint32_t tempBuffLength;
|
||||
if (proxySecret->empty()) {
|
||||
proxyAuthState = 1;
|
||||
tempBuffLength = 1024;
|
||||
} else if (proxySecret->size() > 17 && (*proxySecret)[0] == '\xee') {
|
||||
proxyAuthState = 10;
|
||||
currentSecret = proxySecret->substr(1, 16);
|
||||
currentSecretDomain = proxySecret->substr(17);
|
||||
tempBuffLength = 65 * 1024;
|
||||
} else {
|
||||
proxyAuthState = 0;
|
||||
tempBuffLength = 0;
|
||||
}
|
||||
if (tempBuffLength > 0) {
|
||||
if (tempBuffer == nullptr || tempBuffer->length < tempBuffLength) {
|
||||
if (tempBuffer != nullptr) {
|
||||
delete tempBuffer;
|
||||
}
|
||||
tempBuffer = new ByteArray(tempBuffLength);
|
||||
}
|
||||
}
|
||||
socketAddress.sin_family = AF_INET;
|
||||
socketAddress.sin_port = htons(proxyPort);
|
||||
|
@ -145,6 +360,24 @@ void ConnectionSocket::openConnection(std::string address, uint16_t port, bool i
|
|||
return;
|
||||
}
|
||||
}
|
||||
uint32_t tempBuffLength;
|
||||
if (secret.size() > 17 && secret[0] == '\xee') {
|
||||
proxyAuthState = 10;
|
||||
currentSecret = secret.substr(1, 16);
|
||||
currentSecretDomain = secret.substr(17);
|
||||
tempBuffLength = 65 * 1024;
|
||||
} else {
|
||||
proxyAuthState = 0;
|
||||
tempBuffLength = 0;
|
||||
}
|
||||
if (tempBuffLength > 0) {
|
||||
if (tempBuffer == nullptr || tempBuffer->length < tempBuffLength) {
|
||||
if (tempBuffer != nullptr) {
|
||||
delete tempBuffer;
|
||||
}
|
||||
tempBuffer = new ByteArray(tempBuffLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
openConnectionInternal(ipv6);
|
||||
|
@ -197,7 +430,7 @@ void ConnectionSocket::closeSocket(int32_t reason, int32_t error) {
|
|||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||
ConnectionsManager::getInstance(instanceNum).detachConnection(this);
|
||||
if (socketFd >= 0) {
|
||||
epoll_ctl(ConnectionsManager::getInstance(instanceNum).epolFd, EPOLL_CTL_DEL, socketFd, NULL);
|
||||
epoll_ctl(ConnectionsManager::getInstance(instanceNum).epolFd, EPOLL_CTL_DEL, socketFd, nullptr);
|
||||
if (close(socketFd) != 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) unable to close socket", this);
|
||||
}
|
||||
|
@ -206,8 +439,13 @@ void ConnectionSocket::closeSocket(int32_t reason, int32_t error) {
|
|||
waitingForHostResolve = "";
|
||||
adjustWriteOpAfterResolve = false;
|
||||
proxyAuthState = 0;
|
||||
tlsState = 0;
|
||||
onConnectedSent = false;
|
||||
outgoingByteStream->clean();
|
||||
if (tlsBuffer != nullptr) {
|
||||
tlsBuffer->reuse();
|
||||
tlsBuffer = nullptr;
|
||||
}
|
||||
onDisconnected(reason, error);
|
||||
}
|
||||
|
||||
|
@ -222,6 +460,7 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
|||
NativeByteBuffer *buffer = ConnectionsManager::getInstance(instanceNum).networkBuffer;
|
||||
while (true) {
|
||||
buffer->rewind();
|
||||
Connection *connection = (Connection *) this;
|
||||
readCount = recv(socketFd, buffer->bytes(), READ_BUFFER_SIZE, 0);
|
||||
if (readCount < 0) {
|
||||
closeSocket(1, -1);
|
||||
|
@ -231,7 +470,75 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
|||
if (readCount > 0) {
|
||||
buffer->limit((uint32_t) readCount);
|
||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||
if (proxyAuthState == 2) {
|
||||
if (proxyAuthState == 11) {
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) TLS received %d", this, (int) readCount);
|
||||
size_t newBytesRead = bytesRead + readCount;
|
||||
if (newBytesRead > 64 * 1024) {
|
||||
closeSocket(1, -1);
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) TLS client hello too much data", this);
|
||||
return;
|
||||
}
|
||||
if (newBytesRead >= 16) {
|
||||
std::memcpy(tempBuffer->bytes + bytesRead, buffer->bytes(), (size_t) readCount);
|
||||
|
||||
static std::string hello1 = std::string("\x16\x03\x03", 3);
|
||||
if (std::memcmp(hello1.data(), tempBuffer->bytes, hello1.size()) != 0) {
|
||||
closeSocket(1, -1);
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) TLS hello1 mismatch", this);
|
||||
return;
|
||||
}
|
||||
size_t len1 = (tempBuffer->bytes[3] << 8) + tempBuffer->bytes[4];
|
||||
if (len1 > 64 * 1024 - 5) {
|
||||
closeSocket(1, -1);
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) TLS len1 invalid", this);
|
||||
return;
|
||||
} else if (newBytesRead < len1 + 5) {
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) TLS client hello wait for more data", this);
|
||||
bytesRead = newBytesRead;
|
||||
return;
|
||||
}
|
||||
|
||||
static std::string hello2 = std::string("\x14\x03\x03\x00\x01\x01\x17\x03\x03", 9);
|
||||
if (std::memcmp(hello2.data(), tempBuffer->bytes + 5 + len1, hello2.size()) != 0) {
|
||||
closeSocket(1, -1);
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) TLS hello2 mismatch", this);
|
||||
return;
|
||||
}
|
||||
size_t len2 = (tempBuffer->bytes[5 + 9 + len1] << 8) + tempBuffer->bytes[5 + 9 + len1 + 1];
|
||||
if (len2 > 64 * 1024 - len1 - 5 - 11) {
|
||||
closeSocket(1, -1);
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) TLS len2 invalid", this);
|
||||
return;
|
||||
} else if (newBytesRead < len2 + len1 + 5 + 11) {
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) TLS client hello wait for more data", this);
|
||||
bytesRead = newBytesRead;
|
||||
return;
|
||||
}
|
||||
std::memcpy(tempBuffer->bytes + 64 * 1024 + 32, tempBuffer->bytes + 11, 32);
|
||||
std::memset(tempBuffer->bytes + 11, 0, 32);
|
||||
|
||||
uint8_t *temp = new uint8_t[32 + newBytesRead];
|
||||
memcpy(temp, tempBuffer->bytes + 64 * 1024, 32);
|
||||
memcpy(temp + 32, tempBuffer->bytes, newBytesRead);
|
||||
uint32_t outLength;
|
||||
HMAC(EVP_sha256(), currentSecret.data(), currentSecret.size(), temp, 32 + newBytesRead, tempBuffer->bytes + 64 * 1024, &outLength);
|
||||
delete[] temp;
|
||||
if (std::memcmp(tempBuffer->bytes + 64 * 1024, tempBuffer->bytes + 64 * 1024 + 32, 32) != 0) {
|
||||
tlsHashMismatch = true;
|
||||
closeSocket(1, -1);
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) TLS hash mismatch", this);
|
||||
return;
|
||||
}
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) TLS hello complete", this);
|
||||
tlsState = 1;
|
||||
proxyAuthState = 0;
|
||||
bytesRead = 0;
|
||||
adjustWriteOp();
|
||||
} else {
|
||||
std::memcpy(tempBuffer->bytes + bytesRead, buffer->bytes(), (size_t) readCount);
|
||||
bytesRead = newBytesRead;
|
||||
}
|
||||
} else if (proxyAuthState == 2) {
|
||||
if (readCount == 2) {
|
||||
uint8_t auth_method = buffer->bytes()[1];
|
||||
if (auth_method == 0xff) {
|
||||
|
@ -281,7 +588,65 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
|||
if (ConnectionsManager::getInstance(instanceNum).delegate != nullptr) {
|
||||
ConnectionsManager::getInstance(instanceNum).delegate->onBytesReceived((int32_t) readCount, currentNetworkType, instanceNum);
|
||||
}
|
||||
onReceivedData(buffer);
|
||||
if (tlsState != 0) {
|
||||
while (buffer->hasRemaining()) {
|
||||
size_t newBytesRead = (tlsBuffer != nullptr ? tlsBuffer->position() : 0) + buffer->remaining();
|
||||
if (newBytesRead >= 5) {
|
||||
if (tlsBuffer == nullptr || tlsBuffer->limit() < 5) {
|
||||
uint32_t pos = buffer->position();
|
||||
|
||||
uint8_t offset = 0;
|
||||
uint8_t header[5];
|
||||
if (tlsBuffer != nullptr) {
|
||||
offset = (uint8_t) tlsBuffer->position();
|
||||
memcpy(header, tlsBuffer->bytes(), offset);
|
||||
tlsBuffer->reuse();
|
||||
}
|
||||
memcpy(header + offset, buffer->bytes() + pos, (uint8_t) (5 - offset));
|
||||
|
||||
static std::string header1 = std::string("\x17\x03\x03", 3);
|
||||
if (std::memcmp(header1.data(), header, header1.size()) != 0) {
|
||||
closeSocket(1, -1);
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) TLS response header1 mismatch", this);
|
||||
return;
|
||||
}
|
||||
uint32_t len1 = (header[3] << 8) + header[4];
|
||||
if (len1 > 64 * 1024) {
|
||||
closeSocket(1, -1);
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) TLS response len1 invalid", this);
|
||||
return;
|
||||
} else {
|
||||
tlsBuffer = BuffersStorage::getInstance().getFreeBuffer(len1);
|
||||
buffer->position(pos + (5 - offset));
|
||||
}
|
||||
} else {
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) TLS response new data %d", this, buffer->remaining());
|
||||
}
|
||||
buffer->limit(std::min(buffer->position() + tlsBuffer->remaining(), buffer->limit()));
|
||||
tlsBuffer->writeBytes(buffer);
|
||||
buffer->limit((uint32_t) readCount);
|
||||
if (tlsBuffer->remaining() == 0) {
|
||||
tlsBuffer->rewind();
|
||||
onReceivedData(tlsBuffer);
|
||||
if (tlsBuffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
tlsBuffer->reuse();
|
||||
tlsBuffer = nullptr;
|
||||
} else {
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) TLS response wait for more data, total size %d, left %d", this, tlsBuffer->limit(), tlsBuffer->remaining());
|
||||
}
|
||||
} else {
|
||||
if (tlsBuffer == nullptr) {
|
||||
tlsBuffer = BuffersStorage::getInstance().getFreeBuffer(4);
|
||||
}
|
||||
tlsBuffer->writeBytes(buffer);
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) TLS response wait for more data, not enough bytes for header, total = %d", this, (int) tlsBuffer->position());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
onReceivedData(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (readCount != READ_BUFFER_SIZE) {
|
||||
|
@ -297,58 +662,90 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
|||
return;
|
||||
} else {
|
||||
if (proxyAuthState != 0) {
|
||||
if (proxyAuthState == 1) {
|
||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||
proxyAuthState = 2;
|
||||
buffer[0] = 0x05;
|
||||
buffer[1] = 0x02;
|
||||
buffer[2] = 0x00;
|
||||
buffer[3] = 0x02;
|
||||
if (send(socketFd, buffer, 4, 0) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
if (proxyAuthState >= 10) {
|
||||
if (proxyAuthState == 10) {
|
||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||
tlsHashMismatch = false;
|
||||
proxyAuthState = 11;
|
||||
TlsHello hello = TlsHello::getDefault();
|
||||
hello.setDomain(currentSecretDomain);
|
||||
uint32_t size = hello.writeToBuffer(tempBuffer->bytes);
|
||||
if (!(size = hello.writePadding(tempBuffer->bytes, size))) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) too much data for padding", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
}
|
||||
uint32_t outLength;
|
||||
HMAC(EVP_sha256(), currentSecret.data(), currentSecret.size(), tempBuffer->bytes, size, tempBuffer->bytes + 64 * 1024, &outLength);
|
||||
|
||||
int32_t currentTime = ConnectionsManager::getInstance(instanceNum).getCurrentTime();
|
||||
int32_t old = ((int32_t *) (tempBuffer->bytes + 64 * 1024 + 28))[0];
|
||||
((int32_t *) (tempBuffer->bytes + 64 * 1024 + 28))[0] = old ^ currentTime;
|
||||
|
||||
memcpy(tempBuffer->bytes + 11, tempBuffer->bytes + 64 * 1024, 32);
|
||||
bytesRead = 0;
|
||||
|
||||
if (send(socketFd, tempBuffer->bytes, size, 0) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
}
|
||||
adjustWriteOp();
|
||||
}
|
||||
adjustWriteOp();
|
||||
} else if (proxyAuthState == 3) {
|
||||
buffer[0] = 0x01;
|
||||
std::string *proxyUser;
|
||||
std::string *proxyPassword;
|
||||
if (!overrideProxyAddress.empty()) {
|
||||
proxyUser = &overrideProxyUser;
|
||||
proxyPassword = &overrideProxyPassword;
|
||||
} else {
|
||||
proxyUser = &ConnectionsManager::getInstance(instanceNum).proxyUser;
|
||||
proxyPassword = &ConnectionsManager::getInstance(instanceNum).proxyPassword;
|
||||
} else {
|
||||
if (proxyAuthState == 1) {
|
||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||
proxyAuthState = 2;
|
||||
tempBuffer->bytes[0] = 0x05;
|
||||
tempBuffer->bytes[1] = 0x02;
|
||||
tempBuffer->bytes[2] = 0x00;
|
||||
tempBuffer->bytes[3] = 0x02;
|
||||
if (send(socketFd, tempBuffer->bytes, 4, 0) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
}
|
||||
adjustWriteOp();
|
||||
} else if (proxyAuthState == 3) {
|
||||
tempBuffer->bytes[0] = 0x01;
|
||||
std::string *proxyUser;
|
||||
std::string *proxyPassword;
|
||||
if (!overrideProxyAddress.empty()) {
|
||||
proxyUser = &overrideProxyUser;
|
||||
proxyPassword = &overrideProxyPassword;
|
||||
} else {
|
||||
proxyUser = &ConnectionsManager::getInstance(instanceNum).proxyUser;
|
||||
proxyPassword = &ConnectionsManager::getInstance(instanceNum).proxyPassword;
|
||||
}
|
||||
uint8_t len1 = (uint8_t) proxyUser->length();
|
||||
uint8_t len2 = (uint8_t) proxyPassword->length();
|
||||
tempBuffer->bytes[1] = len1;
|
||||
memcpy(tempBuffer->bytes + 2, proxyUser->c_str(), len1);
|
||||
tempBuffer->bytes[2 + len1] = len2;
|
||||
memcpy(tempBuffer->bytes + 3 + len1, proxyPassword->c_str(), len2);
|
||||
proxyAuthState = 4;
|
||||
if (send(socketFd, tempBuffer->bytes, 3 + len1 + len2, 0) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
}
|
||||
adjustWriteOp();
|
||||
} else if (proxyAuthState == 5) {
|
||||
tempBuffer->bytes[0] = 0x05;
|
||||
tempBuffer->bytes[1] = 0x01;
|
||||
tempBuffer->bytes[2] = 0x00;
|
||||
tempBuffer->bytes[3] = (uint8_t) (isIpv6 ? 0x04 : 0x01);
|
||||
uint16_t networkPort = ntohs(currentPort);
|
||||
inet_pton(isIpv6 ? AF_INET6 : AF_INET, currentAddress.c_str(), tempBuffer->bytes + 4);
|
||||
memcpy(tempBuffer->bytes + 4 + (isIpv6 ? 16 : 4), &networkPort, sizeof(uint16_t));
|
||||
proxyAuthState = 6;
|
||||
if (send(socketFd, tempBuffer->bytes, 4 + (isIpv6 ? 16 : 4) + 2, 0) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
}
|
||||
adjustWriteOp();
|
||||
}
|
||||
uint8_t len1 = (uint8_t) proxyUser->length();
|
||||
uint8_t len2 = (uint8_t) proxyPassword->length();
|
||||
buffer[1] = len1;
|
||||
memcpy(&buffer[2], proxyUser->c_str(), len1);
|
||||
buffer[2 + len1] = len2;
|
||||
memcpy(&buffer[3 + len1], proxyPassword->c_str(), len2);
|
||||
proxyAuthState = 4;
|
||||
if (send(socketFd, buffer, 3 + len1 + len2, 0) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
}
|
||||
adjustWriteOp();
|
||||
} else if (proxyAuthState == 5) {
|
||||
buffer[0] = 0x05;
|
||||
buffer[1] = 0x01;
|
||||
buffer[2] = 0x00;
|
||||
buffer[3] = (uint8_t) (isIpv6 ? 0x04 : 0x01);
|
||||
uint16_t networkPort = ntohs(currentPort);
|
||||
inet_pton(isIpv6 ? AF_INET6 : AF_INET, currentAddress.c_str(), &buffer[4]);
|
||||
memcpy(&buffer[4 + (isIpv6 ? 16 : 4)], &networkPort, sizeof(uint16_t));
|
||||
proxyAuthState = 6;
|
||||
if (send(socketFd, buffer, 4 + (isIpv6 ? 16 : 4) + 2, 0) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
}
|
||||
adjustWriteOp();
|
||||
}
|
||||
} else {
|
||||
if (!onConnectedSent) {
|
||||
|
@ -365,16 +762,50 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
|||
uint32_t remaining = buffer->remaining();
|
||||
if (remaining) {
|
||||
ssize_t sentLength;
|
||||
if ((sentLength = send(socketFd, buffer->bytes(), remaining, 0)) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
} else {
|
||||
if (ConnectionsManager::getInstance(instanceNum).delegate != nullptr) {
|
||||
ConnectionsManager::getInstance(instanceNum).delegate->onBytesSent((int32_t) sentLength, currentNetworkType, instanceNum);
|
||||
if (tlsState != 0) {
|
||||
if (remaining > 2878) {
|
||||
remaining = 2878;
|
||||
}
|
||||
size_t headersSize = 0;
|
||||
if (tlsState == 1) {
|
||||
static std::string header1 = std::string("\x14\x03\x03\x00\x01\x01", 6);
|
||||
std::memcpy(tempBuffer->bytes, header1.data(), header1.size());
|
||||
headersSize += header1.size();
|
||||
tlsState = 2;
|
||||
}
|
||||
static std::string header2 = std::string("\x17\x03\x03", 3);
|
||||
std::memcpy(tempBuffer->bytes + headersSize, header2.data(), header2.size());
|
||||
headersSize += header2.size();
|
||||
|
||||
tempBuffer->bytes[headersSize] = static_cast<uint8_t>((remaining >> 8) & 0xff);
|
||||
tempBuffer->bytes[headersSize + 1] = static_cast<uint8_t>(remaining & 0xff);
|
||||
headersSize += 2;
|
||||
|
||||
std::memcpy(tempBuffer->bytes + headersSize, buffer->bytes(), remaining);
|
||||
|
||||
if ((sentLength = send(socketFd, tempBuffer->bytes, headersSize + remaining, 0)) < headersSize) {
|
||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
} else {
|
||||
if (ConnectionsManager::getInstance(instanceNum).delegate != nullptr) {
|
||||
ConnectionsManager::getInstance(instanceNum).delegate->onBytesSent((int32_t) sentLength, currentNetworkType, instanceNum);
|
||||
}
|
||||
outgoingByteStream->discard((uint32_t) (sentLength - headersSize));
|
||||
adjustWriteOp();
|
||||
}
|
||||
} else {
|
||||
if ((sentLength = send(socketFd, buffer->bytes(), remaining, 0)) < 0) {
|
||||
if (LOGS_ENABLED) DEBUG_D("connection(%p) send failed", this);
|
||||
closeSocket(1, -1);
|
||||
return;
|
||||
} else {
|
||||
if (ConnectionsManager::getInstance(instanceNum).delegate != nullptr) {
|
||||
ConnectionsManager::getInstance(instanceNum).delegate->onBytesSent((int32_t) sentLength, currentNetworkType, instanceNum);
|
||||
}
|
||||
outgoingByteStream->discard((uint32_t) sentLength);
|
||||
adjustWriteOp();
|
||||
}
|
||||
outgoingByteStream->discard((uint32_t) sentLength);
|
||||
adjustWriteOp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -413,7 +844,7 @@ void ConnectionSocket::adjustWriteOp() {
|
|||
return;
|
||||
}
|
||||
eventMask.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLET;
|
||||
if (proxyAuthState == 0 && (outgoingByteStream->hasData() || !onConnectedSent) || proxyAuthState == 1 || proxyAuthState == 3 || proxyAuthState == 5) {
|
||||
if (proxyAuthState == 0 && (outgoingByteStream->hasData() || !onConnectedSent) || proxyAuthState == 1 || proxyAuthState == 3 || proxyAuthState == 5 || proxyAuthState == 10) {
|
||||
eventMask.events |= EPOLLOUT;
|
||||
}
|
||||
eventMask.data.ptr = eventObject;
|
||||
|
@ -444,6 +875,10 @@ void ConnectionSocket::checkTimeout(int64_t now) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ConnectionSocket::hasTlsHashMismatch() {
|
||||
return tlsHashMismatch;
|
||||
}
|
||||
|
||||
void ConnectionSocket::resetLastEventTime() {
|
||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ class NativeByteBuffer;
|
|||
class ConnectionsManager;
|
||||
class ByteStream;
|
||||
class EventObject;
|
||||
class ByteArray;
|
||||
|
||||
class ConnectionSocket {
|
||||
|
||||
|
@ -26,7 +27,7 @@ public:
|
|||
|
||||
void writeBuffer(uint8_t *data, uint32_t size);
|
||||
void writeBuffer(NativeByteBuffer *buffer);
|
||||
void openConnection(std::string address, uint16_t port, bool ipv6, int32_t networkType);
|
||||
void openConnection(std::string address, uint16_t port, std::string secret, bool ipv6, int32_t networkType);
|
||||
void setTimeout(time_t timeout);
|
||||
time_t getTimeout();
|
||||
bool isDisconnected();
|
||||
|
@ -39,6 +40,7 @@ protected:
|
|||
void onEvent(uint32_t events);
|
||||
void checkTimeout(int64_t now);
|
||||
void resetLastEventTime();
|
||||
bool hasTlsHashMismatch();
|
||||
virtual void onReceivedData(NativeByteBuffer *buffer) = 0;
|
||||
virtual void onDisconnected(int32_t reason, int32_t error) = 0;
|
||||
virtual void onConnected() = 0;
|
||||
|
@ -68,7 +70,14 @@ private:
|
|||
std::string waitingForHostResolve;
|
||||
bool adjustWriteOpAfterResolve;
|
||||
|
||||
uint8_t buffer[1024];
|
||||
std::string currentSecret;
|
||||
std::string currentSecretDomain;
|
||||
|
||||
bool tlsHashMismatch = false;
|
||||
NativeByteBuffer *tlsBuffer = nullptr;
|
||||
ByteArray *tempBuffer = nullptr;
|
||||
size_t bytesRead = 0;
|
||||
int8_t tlsState = 0;
|
||||
|
||||
uint8_t proxyAuthState;
|
||||
|
||||
|
|
|
@ -625,7 +625,7 @@ void ConnectionsManager::onConnectionClosed(Connection *connection, int reason)
|
|||
if (connection->getConnectionType() == ConnectionTypeGeneric) {
|
||||
if (datacenter->getDatacenterId() == currentDatacenterId) {
|
||||
sendingPing = false;
|
||||
if (!connection->isSuspended() && proxyAddress.empty()) {
|
||||
if (!connection->isSuspended() && (proxyAddress.empty() || connection->hasTlsHashMismatch())) {
|
||||
if (reason == 2) {
|
||||
disconnectTimeoutAmount += connection->getTimeout();
|
||||
} else {
|
||||
|
@ -641,6 +641,7 @@ void ConnectionsManager::onConnectionClosed(Connection *connection, int reason)
|
|||
if (disconnectTimeoutAmount >= maxTimeout) {
|
||||
if (!connection->hasUsefullData()) {
|
||||
if (LOGS_ENABLED) DEBUG_D("start requesting new address and port due to timeout reach");
|
||||
requestingSecondAddressByTlsHashMismatch = connection->hasTlsHashMismatch();
|
||||
requestingSecondAddress = 0;
|
||||
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
||||
} else {
|
||||
|
@ -976,7 +977,7 @@ TLObject *ConnectionsManager::TLdeserialize(TLObject *request, uint32_t bytes, N
|
|||
if (request != nullptr) {
|
||||
TL_api_request *apiRequest = dynamic_cast<TL_api_request *>(request);
|
||||
if (apiRequest != nullptr) {
|
||||
object = apiRequest->deserializeResponse(data, bytes, error);
|
||||
object = apiRequest->deserializeResponse(data, bytes, instanceNum, error);
|
||||
if (LOGS_ENABLED) DEBUG_D("api request constructor 0x%x, don't parse", constructor);
|
||||
} else {
|
||||
object = request->deserializeResponse(data, constructor, instanceNum, error);
|
||||
|
@ -1230,15 +1231,22 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
|||
} else if (error->error_code == 420) {
|
||||
int32_t waitTime = 2;
|
||||
static std::string floodWait = "FLOOD_WAIT_";
|
||||
static std::string slowmodeWait = "SLOWMODE_WAIT_";
|
||||
discardResponse = true;
|
||||
if (error->error_message.find(floodWait) != std::string::npos) {
|
||||
std::string num = error->error_message.substr(floodWait.size(), error->error_message.size() - floodWait.size());
|
||||
waitTime = atoi(num.c_str());
|
||||
if (waitTime <= 0) {
|
||||
waitTime = 2;
|
||||
}
|
||||
} else if (error->error_message.find(slowmodeWait) != std::string::npos) {
|
||||
std::string num = error->error_message.substr(slowmodeWait.size(), error->error_message.size() - slowmodeWait.size());
|
||||
waitTime = atoi(num.c_str());
|
||||
if (waitTime <= 0) {
|
||||
waitTime = 2;
|
||||
}
|
||||
discardResponse = false;
|
||||
}
|
||||
|
||||
discardResponse = true;
|
||||
request->failedByFloodWait = waitTime;
|
||||
request->startTime = 0;
|
||||
request->startTimeMillis = 0;
|
||||
|
@ -1431,7 +1439,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
|||
datacenter->addServerSalt(salt);
|
||||
saveConfig();
|
||||
|
||||
requestSaltsForDatacenter(datacenter);
|
||||
requestSaltsForDatacenter(datacenter, connection->getConnectionType() == ConnectionTypeTemp);
|
||||
if (datacenter->hasAuthKey(ConnectionTypeGeneric, 1)) {
|
||||
processRequestQueue(AllConnectionTypes, datacenter->getDatacenterId());
|
||||
}
|
||||
|
@ -1873,7 +1881,7 @@ void ConnectionsManager::cancelRequest(int32_t token, bool notifyServer) {
|
|||
void ConnectionsManager::onDatacenterHandshakeComplete(Datacenter *datacenter, HandshakeType type, int32_t timeDiff) {
|
||||
saveConfig();
|
||||
uint32_t datacenterId = datacenter->getDatacenterId();
|
||||
if (datacenterId == currentDatacenterId || datacenterId == movingToDatacenterId) {
|
||||
if (datacenterId == currentDatacenterId || datacenterId == movingToDatacenterId || updatingDcSettingsWorkaround || updatingDcSettings) {
|
||||
timeDifference = timeDiff;
|
||||
datacenter->recreateSessions(type);
|
||||
clearRequestsForDatacenter(datacenter, type);
|
||||
|
@ -1953,15 +1961,19 @@ void ConnectionsManager::sendMessagesToConnectionWithConfirmation(std::vector<st
|
|||
sendMessagesToConnection(messages, connection, reportAck);
|
||||
}
|
||||
|
||||
void ConnectionsManager::requestSaltsForDatacenter(Datacenter *datacenter) {
|
||||
if (std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), datacenter->getDatacenterId()) != requestingSaltsForDc.end()) {
|
||||
void ConnectionsManager::requestSaltsForDatacenter(Datacenter *datacenter, bool useTempConnection) {
|
||||
uint32_t id = datacenter->getDatacenterId();
|
||||
if (useTempConnection) {
|
||||
id |= 0x80000000;
|
||||
}
|
||||
if (std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), id) != requestingSaltsForDc.end()) {
|
||||
return;
|
||||
}
|
||||
requestingSaltsForDc.push_back(datacenter->getDatacenterId());
|
||||
TL_get_future_salts *request = new TL_get_future_salts();
|
||||
request->num = 32;
|
||||
sendRequest(request, [&, datacenter](TLObject *response, TL_error *error, int32_t networkType) {
|
||||
std::vector<uint32_t>::iterator iter = std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), datacenter->getDatacenterId());
|
||||
sendRequest(request, [&, datacenter, id](TLObject *response, TL_error *error, int32_t networkType) {
|
||||
std::vector<uint32_t>::iterator iter = std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), id);
|
||||
if (iter != requestingSaltsForDc.end()) {
|
||||
requestingSaltsForDc.erase(iter);
|
||||
}
|
||||
|
@ -1970,7 +1982,7 @@ void ConnectionsManager::requestSaltsForDatacenter(Datacenter *datacenter) {
|
|||
datacenter->mergeServerSalts(res->salts);
|
||||
saveConfig();
|
||||
}
|
||||
}, nullptr, RequestFlagWithoutLogin | RequestFlagEnableUnauthorized | RequestFlagUseUnboundKey, datacenter->getDatacenterId(), ConnectionTypeGeneric, true);
|
||||
}, nullptr, RequestFlagWithoutLogin | RequestFlagEnableUnauthorized | RequestFlagUseUnboundKey, datacenter->getDatacenterId(), useTempConnection ? ConnectionTypeTemp : ConnectionTypeGeneric, true);
|
||||
}
|
||||
|
||||
void ConnectionsManager::clearRequestsForDatacenter(Datacenter *datacenter, HandshakeType type) {
|
||||
|
@ -2374,7 +2386,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
|
|||
} else {
|
||||
currentCount = 0;
|
||||
}
|
||||
if (!networkAvailable || currentCount >= 10) {
|
||||
if (!networkAvailable || currentCount >= 12) {
|
||||
iter++;
|
||||
continue;
|
||||
}
|
||||
|
@ -2691,14 +2703,85 @@ std::unique_ptr<TLObject> ConnectionsManager::wrapInLayer(TLObject *object, Data
|
|||
return std::unique_ptr<TLObject>(object);
|
||||
}
|
||||
|
||||
inline std::string hexStr(unsigned char *data, uint32_t len) {
|
||||
constexpr char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
std::string s(len * 2, ' ');
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
s[2 * i] = hexmap[(data[i] & 0xF0) >> 4];
|
||||
s[2 * i + 1] = hexmap[data[i] & 0x0F];
|
||||
static const char *const url_symbols64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||
static unsigned char url_char_to_value[256];
|
||||
static void init_base64url_table() {
|
||||
static bool is_inited = []() {
|
||||
std::fill(std::begin(url_char_to_value), std::end(url_char_to_value), static_cast<unsigned char>(64));
|
||||
for (unsigned char i = 0; i < 64; i++) {
|
||||
url_char_to_value[static_cast<size_t>(url_symbols64[i])] = i;
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
assert(is_inited);
|
||||
}
|
||||
|
||||
std::string base64UrlDecode(std::string base64) {
|
||||
init_base64url_table();
|
||||
|
||||
size_t padding_length = 0;
|
||||
while (!base64.empty() && base64.back() == '=') {
|
||||
padding_length++;
|
||||
}
|
||||
return s;
|
||||
if (padding_length >= 3 || (padding_length > 0 && ((base64.size() + padding_length) & 3) != 0)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if ((base64.size() & 3) == 1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string output;
|
||||
size_t size = base64.size() - padding_length;
|
||||
output.reserve(((base64.size() + 3) >> 2) * 3);
|
||||
for (size_t i = 0; i < size;) {
|
||||
size_t left = std::min(size - i, static_cast<size_t>(4));
|
||||
int c = 0;
|
||||
for (size_t t = 0; t < left; t++) {
|
||||
auto value = url_char_to_value[base64.c_str()[i++]];
|
||||
if (value == 64) {
|
||||
return "";
|
||||
}
|
||||
c |= value << ((3 - t) * 6);
|
||||
}
|
||||
output += static_cast<char>(static_cast<unsigned char>(c >> 16));
|
||||
if (left == 2) {
|
||||
if ((c & ((1 << 16) - 1)) != 0) {
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
output += static_cast<char>(static_cast<unsigned char>(c >> 8));
|
||||
if (left == 3) {
|
||||
if ((c & ((1 << 8) - 1)) != 0) {
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
output += static_cast<char>(static_cast<unsigned char>(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
inline std::string decodeSecret(std::string secret) {
|
||||
bool allHex = true;
|
||||
for (size_t i = 0; i < secret.size(); i++) {
|
||||
if (!(secret[i] >= '0' && secret[i] <= '9' || secret[i] >= 'a' && secret[i] <= 'f' || secret[i] >= 'A' && secret[i] <= 'F')) {
|
||||
allHex = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allHex) {
|
||||
size_t size = secret.size() / 2;
|
||||
char *result = new char[size];
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
result[i] = (char) (char2int(secret[i * 2]) * 16 + char2int(secret[i * 2 + 1]));
|
||||
}
|
||||
secret = std::string(result, size);
|
||||
delete[] result;
|
||||
return secret;
|
||||
}
|
||||
return base64UrlDecode(secret);
|
||||
}
|
||||
|
||||
void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) {
|
||||
|
@ -2764,7 +2847,7 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) {
|
|||
}
|
||||
std::string secret;
|
||||
if (dcOption->secret != nullptr) {
|
||||
secret = hexStr(dcOption->secret->bytes, dcOption->secret->length);
|
||||
secret = std::string((const char *) dcOption->secret->bytes, dcOption->secret->length);
|
||||
}
|
||||
if (LOGS_ENABLED) DEBUG_D("getConfig add %s:%d to dc%d, flags %d, has secret = %d[%d]", dcOption->ip_address.c_str(), dcOption->port, dcOption->id, dcOption->flags, dcOption->secret != nullptr ? 1 : 0, dcOption->secret != nullptr ? dcOption->secret->length : 0);
|
||||
addresses->push_back(TcpAddress(dcOption->ip_address, dcOption->port, dcOption->flags, secret));
|
||||
|
@ -2946,12 +3029,20 @@ inline bool checkPhoneByPrefixesRules(std::string phone, std::string rules) {
|
|||
return found;
|
||||
}
|
||||
|
||||
void ConnectionsManager::applyDnsConfig(NativeByteBuffer *buffer, std::string phone) {
|
||||
scheduleTask([&, buffer, phone] {
|
||||
void ConnectionsManager::applyDnsConfig(NativeByteBuffer *buffer, std::string phone, int32_t date) {
|
||||
scheduleTask([&, buffer, phone, date] {
|
||||
int32_t realDate = date;
|
||||
if (LOGS_ENABLED) DEBUG_D("trying to decrypt config %d", requestingSecondAddress);
|
||||
TL_help_configSimple *config = Datacenter::decodeSimpleConfig(buffer);
|
||||
if (config != nullptr && realDate == 0) {
|
||||
realDate = config->date;
|
||||
}
|
||||
int currentDate = getCurrentTime();
|
||||
if (config != nullptr && config->date <= currentDate && currentDate <= config->expires) {
|
||||
if (realDate > 0 && requestingSecondAddressByTlsHashMismatch) {
|
||||
timeDifference = realDate - currentDate;
|
||||
requestingSecondAddressByTlsHashMismatch = false;
|
||||
}
|
||||
for (std::vector<std::unique_ptr<TL_accessPointRule>>::iterator iter = config->rules.begin(); iter != config->rules.end(); iter++) {
|
||||
TL_accessPointRule *rule = iter->get();
|
||||
if (!checkPhoneByPrefixesRules(phone, rule->phone_prefix_rules)) {
|
||||
|
@ -2969,7 +3060,7 @@ void ConnectionsManager::applyDnsConfig(NativeByteBuffer *buffer, std::string ph
|
|||
if (LOGS_ENABLED) DEBUG_D("got address %s and port %d for dc%d", ipPort->ipv4.c_str(), ipPort->port, rule->dc_id);
|
||||
} else if (typeInfo == typeid(TL_ipPortSecret)) {
|
||||
TL_ipPortSecret *ipPort = (TL_ipPortSecret *) port;
|
||||
addresses.push_back(TcpAddress(ipPort->ipv4, ipPort->port, 0, hexStr(ipPort->secret->bytes, ipPort->secret->length)));
|
||||
addresses.push_back(TcpAddress(ipPort->ipv4, ipPort->port, 0, std::string((const char *) ipPort->secret->bytes, ipPort->secret->length)));
|
||||
if (LOGS_ENABLED) DEBUG_D("got address %s and port %d for dc%d with secret", ipPort->ipv4.c_str(), ipPort->port, rule->dc_id);
|
||||
}
|
||||
}
|
||||
|
@ -2999,9 +3090,6 @@ void ConnectionsManager::applyDnsConfig(NativeByteBuffer *buffer, std::string ph
|
|||
if (requestingSecondAddress == 0) {
|
||||
requestingSecondAddress = 1;
|
||||
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
||||
} else if (requestingSecondAddress == 1) {
|
||||
requestingSecondAddress = 2;
|
||||
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
||||
} else {
|
||||
requestingSecondAddress = 0;
|
||||
}
|
||||
|
@ -3060,13 +3148,14 @@ void ConnectionsManager::init(uint32_t version, int32_t layer, int32_t apiId, st
|
|||
|
||||
void ConnectionsManager::setProxySettings(std::string address, uint16_t port, std::string username, std::string password, std::string secret) {
|
||||
scheduleTask([&, address, port, username, password, secret] {
|
||||
bool secretChanged = proxySecret != secret;
|
||||
std::string newSecret = decodeSecret(secret);
|
||||
bool secretChanged = proxySecret != newSecret;
|
||||
bool reconnect = proxyAddress != address || proxyPort != port || username != proxyUser || proxyPassword != password || secretChanged;
|
||||
proxyAddress = address;
|
||||
proxyPort = port;
|
||||
proxyUser = username;
|
||||
proxyPassword = password;
|
||||
proxySecret = secret;
|
||||
proxySecret = std::move(newSecret);
|
||||
if (!proxyAddress.empty() && connectionState == ConnectionStateConnecting) {
|
||||
connectionState = ConnectionStateConnectingViaProxy;
|
||||
if (delegate != nullptr) {
|
||||
|
@ -3119,6 +3208,7 @@ void ConnectionsManager::setRegId(std::string regId) {
|
|||
for (std::map<uint32_t, Datacenter *>::iterator iter = datacenters.begin(); iter != datacenters.end(); iter++) {
|
||||
iter->second->resetInitVersion();
|
||||
}
|
||||
updateDcSettings(0, false);
|
||||
saveConfig();
|
||||
});
|
||||
}
|
||||
|
@ -3206,7 +3296,7 @@ int64_t ConnectionsManager::checkProxy(std::string address, uint16_t port, std::
|
|||
proxyCheckInfo->port = port;
|
||||
proxyCheckInfo->username = username;
|
||||
proxyCheckInfo->password = password;
|
||||
proxyCheckInfo->secret = secret;
|
||||
proxyCheckInfo->secret = decodeSecret(secret);
|
||||
proxyCheckInfo->onRequestTime = requestTimeFunc;
|
||||
proxyCheckInfo->pingId = ++lastPingProxyId;
|
||||
proxyCheckInfo->instanceNum = instanceNum;
|
||||
|
|
|
@ -69,7 +69,7 @@ public:
|
|||
void setSystemLangCode(std::string langCode);
|
||||
void updateDcSettings(uint32_t datacenterId, bool workaround);
|
||||
void setPushConnectionEnabled(bool value);
|
||||
void applyDnsConfig(NativeByteBuffer *buffer, std::string phone);
|
||||
void applyDnsConfig(NativeByteBuffer *buffer, std::string phone, int32_t date);
|
||||
void setMtProtoVersion(int version);
|
||||
int32_t getMtProtoVersion();
|
||||
int64_t checkProxy(std::string address, uint16_t port, std::string username, std::string password, std::string secret, onRequestTimeFunc requestTimeFunc, jobject ptr1);
|
||||
|
@ -92,7 +92,7 @@ private:
|
|||
void sendPing(Datacenter *datacenter, bool usePushConnection);
|
||||
void sendMessagesToConnection(std::vector<std::unique_ptr<NetworkMessage>> &messages, Connection *connection, bool reportAck);
|
||||
void sendMessagesToConnectionWithConfirmation(std::vector<std::unique_ptr<NetworkMessage>> &messages, Connection *connection, bool reportAck);
|
||||
void requestSaltsForDatacenter(Datacenter *datacenter);
|
||||
void requestSaltsForDatacenter(Datacenter *datacenter, bool useTempConnection);
|
||||
void clearRequestsForDatacenter(Datacenter *datacenter, HandshakeType type);
|
||||
void registerForInternalPushUpdates();
|
||||
void processRequestQueue(uint32_t connectionType, uint32_t datacenterId);
|
||||
|
@ -153,6 +153,7 @@ private:
|
|||
bool updatingDcSettings = false;
|
||||
bool updatingDcSettingsWorkaround = false;
|
||||
int32_t disconnectTimeoutAmount = 0;
|
||||
bool requestingSecondAddressByTlsHashMismatch = false;
|
||||
int32_t requestingSecondAddress = 0;
|
||||
int32_t updatingDcStartTime = 0;
|
||||
int32_t lastDcUpdateTime = 0;
|
||||
|
|
|
@ -43,17 +43,6 @@ Datacenter::Datacenter(int32_t instance, uint32_t id) {
|
|||
}
|
||||
}
|
||||
|
||||
inline char char2int(char input) {
|
||||
if (input >= '0' && input <= '9') {
|
||||
return input - '0';
|
||||
} else if (input >= 'A' && input <= 'F') {
|
||||
return (char) (input - 'A' + 10);
|
||||
} else if (input >= 'a' && input <= 'f') {
|
||||
return (char) (input - 'a' + 10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Datacenter::Datacenter(int32_t instance, NativeByteBuffer *data) {
|
||||
instanceNum = instance;
|
||||
for (uint32_t a = 0; a < UPLOAD_CONNECTIONS_COUNT; a++) {
|
||||
|
@ -108,8 +97,19 @@ Datacenter::Datacenter(int32_t instance, NativeByteBuffer *data) {
|
|||
} else {
|
||||
flags = 0;
|
||||
}
|
||||
if (currentVersion >= 9) {
|
||||
if (currentVersion >= 11) {
|
||||
secret = data->readString(nullptr);
|
||||
} else if (currentVersion >= 9) {
|
||||
secret = data->readString(nullptr);
|
||||
if (!secret.empty()) {
|
||||
size_t size = secret.size() / 2;
|
||||
char *result = new char[size];
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
result[i] = (char) (char2int(secret[i * 2]) * 16 + char2int(secret[i * 2 + 1]));
|
||||
}
|
||||
secret = std::string(result, size);
|
||||
delete[] result;
|
||||
}
|
||||
}
|
||||
(*array).push_back(TcpAddress(address, port, flags, secret));
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ private:
|
|||
|
||||
std::vector<std::unique_ptr<Handshake>> handshakes;
|
||||
|
||||
const uint32_t configVersion = 10;
|
||||
const uint32_t configVersion = 11;
|
||||
const uint32_t paramsConfigVersion = 1;
|
||||
|
||||
Connection *createProxyConnection(uint8_t num);
|
||||
|
|
|
@ -179,4 +179,15 @@ inline std::string to_string_uint64(uint64_t value) {
|
|||
return std::string(buf, (uint32_t) len);
|
||||
}
|
||||
|
||||
inline int32_t char2int(char input) {
|
||||
if (input >= '0' && input <= '9') {
|
||||
return input - '0';
|
||||
} else if (input >= 'A' && input <= 'F') {
|
||||
return (char) (input - 'A' + 10);
|
||||
} else if (input >= 'a' && input <= 'f') {
|
||||
return (char) (input - 'a' + 10);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -92,7 +92,7 @@ bool TL_api_request::isNeedLayer() {
|
|||
return true;
|
||||
}
|
||||
|
||||
TLObject *TL_api_request::deserializeResponse(NativeByteBuffer *stream, uint32_t bytes, bool &error) {
|
||||
TLObject *TL_api_request::deserializeResponse(NativeByteBuffer *stream, uint32_t bytes, int32_t instanceNum, bool &error) {
|
||||
TL_api_response *result = new TL_api_response();
|
||||
result->readParamsEx(stream, bytes, error);
|
||||
return result;
|
||||
|
|
|
@ -21,7 +21,6 @@ class TLClassStore {
|
|||
|
||||
public:
|
||||
static TLObject *TLdeserialize(NativeByteBuffer *stream, uint32_t bytes, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||
|
||||
};
|
||||
|
||||
class TL_api_request : public TLObject {
|
||||
|
@ -31,7 +30,7 @@ public:
|
|||
|
||||
~TL_api_request();
|
||||
bool isNeedLayer();
|
||||
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t bytes, bool &error);
|
||||
TLObject *deserializeResponse(NativeByteBuffer *stream, uint32_t bytes, int32_t instanceNum, bool &error);
|
||||
void serializeToStream(NativeByteBuffer *stream);
|
||||
};
|
||||
|
||||
|
|
|
@ -229,14 +229,6 @@
|
|||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver
|
||||
android:name=".SmsReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".CallReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PHONE_STATE"/>
|
||||
|
@ -276,7 +268,6 @@
|
|||
<service android:name=".BringAppForegroundService" android:enabled="true"/>
|
||||
<service android:name=".NotificationsService" android:enabled="true"/>
|
||||
<service android:name=".NotificationRepeat" android:exported="false"/>
|
||||
<service android:name=".ClearCacheService" android:exported="false"/>
|
||||
<service android:name=".VideoEncodingService" android:enabled="true"/>
|
||||
<service android:name=".LocationSharingService" android:enabled="true"/>
|
||||
<service android:name=".voip.VoIPService" android:enabled="true"/>
|
||||
|
|
|
@ -22,7 +22,7 @@ key_chat_messagePanelVoiceLock=-1
|
|||
chat_secretChatStatusText=-9997953
|
||||
switchTrack=-11314335
|
||||
chat_inPreviewInstantSelectedText=-11099429
|
||||
chat_attachAudioBackground=-1267376
|
||||
chat_attachAudioBackground=-1282464
|
||||
actionBarDefaultSubmenuBackground=-13749706
|
||||
switchTrackBlueThumb=-14473945
|
||||
avatar_nameInMessageViolet=-5925398
|
||||
|
@ -49,7 +49,7 @@ switch2Track=-2135965
|
|||
chats_menuPhoneCats=-8287602
|
||||
chat_outPreviewLine=-5515009
|
||||
dialogScrollGlow=-1708041
|
||||
chat_messagePanelHint=-10459539
|
||||
chat_messagePanelHint=-10064780
|
||||
windowBackgroundGray=-15197927
|
||||
chat_inViaBotNameText=-9456666
|
||||
chat_outVoiceSeekbar=-1300913456
|
||||
|
@ -95,7 +95,7 @@ chat_topPanelLine=-9456666
|
|||
chat_inReplyMessageText=-251658241
|
||||
windowBackgroundWhiteInputFieldActivated=-10636041
|
||||
dialogInputField=-11248027
|
||||
chat_attachGalleryBackground=-6192928
|
||||
chat_attachGalleryBackground=-11037210
|
||||
chat_outInstantSelected=-1
|
||||
chat_outSentCheck=-7156228
|
||||
key_graySectionText=-9075309
|
||||
|
@ -158,6 +158,7 @@ dialogTextRed2=-892058
|
|||
chats_nameMessageArchived=-9011322
|
||||
avatar_nameInMessageOrange=-1265812
|
||||
chats_pinnedIcon=-10524305
|
||||
chat_attachActiveTab=-12341003
|
||||
chat_replyPanelLine=1907997
|
||||
avatar_subtitleInProfileOrange=-7697782
|
||||
chat_outSentCheckSelected=-7156228
|
||||
|
@ -220,6 +221,7 @@ dialogRoundCheckBox=-9912583
|
|||
chat_emojiPanelTrendingTitle=-2167820
|
||||
actionBarTabLine=-10510610
|
||||
switchThumbChecked=-13600600
|
||||
chat_stickersHintPanel=-13748673
|
||||
chats_nameMessageArchived_threeLines=-1644826
|
||||
chat_outSiteNameText=-5515009
|
||||
windowBackgroundWhite=-14737118
|
||||
|
@ -283,12 +285,13 @@ avatar_nameInMessagePink=-1215324
|
|||
windowBackgroundWhiteGrayText=-9603715
|
||||
musicPicker_buttonBackground=-11035162
|
||||
avatar_actionBarSelectorViolet=-11972268
|
||||
chat_attachPollBackground=-1263011
|
||||
avatar_nameInMessageBlue=-9456666
|
||||
dialogTextBlack=-328966
|
||||
actionBarDefault=-14276309
|
||||
profile_actionIcon=-1
|
||||
windowBackgroundUnchecked=-14473945
|
||||
actionBarDefaultSelector=-196521644
|
||||
actionBarDefaultSelector=-1102491308
|
||||
chats_menuTopShadow=-1558504677
|
||||
chat_outAudioPerfomerText=-6965025
|
||||
sharedMedia_startStopLoadIcon=-11164432
|
||||
|
@ -307,6 +310,7 @@ dialogBadgeBackground=-10371847
|
|||
chat_outBubbleSelected=-12487769
|
||||
avatar_backgroundInProfileBlue=-11232035
|
||||
chat_inFileNameText=-1
|
||||
chat_attachEmptyImage=-11840420
|
||||
inappPlayerPerformer=-1
|
||||
chat_inInstantSelected=-9456666
|
||||
chat_outFileInfoText=-6965025
|
||||
|
@ -341,7 +345,7 @@ key_player_progressCachedBackground=-12433330
|
|||
chat_outTimeText=-6965025
|
||||
chat_outBubble=-12687992
|
||||
avatar_backgroundActionBarCyan=-14605274
|
||||
chat_attachFileBackground=-10706196
|
||||
chat_attachFileBackground=-11291668
|
||||
chat_attachHideBackground=-14078156
|
||||
chats_menuItemText=-986896
|
||||
chats_message=-9011322
|
||||
|
@ -371,7 +375,7 @@ player_background=-14407896
|
|||
inappPlayerClose=-10525075
|
||||
chat_outMediaIcon=-1
|
||||
player_actionBarSubtitle=-9339518
|
||||
chat_attachContactBackground=-10438416
|
||||
chat_attachContactBackground=-1265579
|
||||
chat_outAudioCacheSeekbar=-1218212423
|
||||
chats_sentClock=-8740661
|
||||
chat_inAudioSeekbar=-581869200
|
||||
|
@ -382,7 +386,7 @@ chat_inPreviewInstantText=-9456666
|
|||
chats_archiveBackground=-10642482
|
||||
chat_inViews=-8812137
|
||||
chat_outLoaderSelected=-9194520
|
||||
dialogButtonSelector=352321535
|
||||
dialogButtonSelector=1229541716
|
||||
chats_archivePinBackground=-13749706
|
||||
player_actionBarItems=-1
|
||||
chat_sentError=-1551526
|
||||
|
|
|
@ -20,7 +20,7 @@ key_chat_messagePanelVoiceLock=-1
|
|||
chat_secretChatStatusText=-8812137
|
||||
switchTrack=-10984850
|
||||
chat_inPreviewInstantSelectedText=-5648402
|
||||
chat_attachAudioBackground=-619421
|
||||
chat_attachAudioBackground=-626837
|
||||
location_sendLocationBackground=-9919529
|
||||
actionBarDefaultSubmenuBackground=-14075831
|
||||
switchTrackBlueThumb=-14866637
|
||||
|
@ -47,7 +47,7 @@ key_sheet_other=1140850687
|
|||
chat_inContactNameText=-8796932
|
||||
chats_menuPhoneCats=-11049613
|
||||
chat_outPreviewLine=-6631937
|
||||
chat_messagePanelHint=-11180684
|
||||
chat_messagePanelHint=-9798256
|
||||
windowBackgroundGray=-15393241
|
||||
chat_inViaBotNameText=-8796932
|
||||
chat_outVoiceSeekbar=-429551165
|
||||
|
@ -62,6 +62,7 @@ chat_emojiPanelBackspace=-9996665
|
|||
chat_replyPanelClose=-10062202
|
||||
chat_inContactPhoneSelectedText=-7490861
|
||||
dialogSearchText=-1
|
||||
actionBarTabUnactiveText=-7628894
|
||||
chat_outAudioTitleText=-1
|
||||
chat_emojiPanelBackground=-14866637
|
||||
chats_unreadCounter=-10177041
|
||||
|
@ -84,6 +85,7 @@ files_folderIconBackground=-13286315
|
|||
passport_authorizeBackgroundSelected=-11627561
|
||||
switchTrackBlueChecked=-8333825
|
||||
player_seekBarBackground=1196577362
|
||||
dialogShadowLine=335544320
|
||||
groupcreate_onlineText=-10177041
|
||||
profile_status=-9192457
|
||||
divider=-1795162112
|
||||
|
@ -91,6 +93,7 @@ chat_topPanelLine=-11108183
|
|||
chat_inReplyMessageText=-1
|
||||
dialogInputField=-8549479
|
||||
windowBackgroundWhiteInputFieldActivated=-9522449
|
||||
chat_attachGalleryBackground=-11692299
|
||||
chat_outInstantSelected=-4268038
|
||||
chat_outSentCheck=-7878657
|
||||
key_graySectionText=-8549479
|
||||
|
@ -153,6 +156,7 @@ dialogTextRed2=-1152913
|
|||
chats_nameMessageArchived=-8549479
|
||||
avatar_nameInMessageOrange=-13984
|
||||
chats_pinnedIcon=-10982016
|
||||
chat_attachActiveTab=-9781249
|
||||
chat_replyPanelLine=1779898909
|
||||
avatar_subtitleInProfileOrange=-7628894
|
||||
chat_outSentCheckSelected=-4268038
|
||||
|
@ -163,6 +167,7 @@ avatar_backgroundGroupCreateSpanBlue=-13803892
|
|||
dialogTextBlue3=-10177041
|
||||
switchTrackBlueThumbChecked=-11632213
|
||||
dialogTextBlue4=-10177041
|
||||
chat_attachUnactiveTab=-9596506
|
||||
windowBackgroundWhiteGreenText=-10371737
|
||||
actionBarTabActiveText=-9781249
|
||||
chat_emojiPanelIcon=-9996665
|
||||
|
@ -221,6 +226,7 @@ chat_inVoiceSeekbarSelected=-9203285
|
|||
dialogTextGray=-8549479
|
||||
chat_messageLinkOut=-6631937
|
||||
avatar_backgroundArchived=-13087910
|
||||
picker_badge=-11097097
|
||||
chat_outFileInfoSelectedText=-4268038
|
||||
chats_tabletSelectedOverlay=268435455
|
||||
chat_outAudioDurationSelectedText=-4268038
|
||||
|
@ -269,10 +275,12 @@ profile_verifiedCheck=-1
|
|||
listSelectorSDK21=301989887
|
||||
key_chat_messagePanelVoiceLockBackground=-13548712
|
||||
chat_outFileNameText=-1
|
||||
picker_enabledButton=-9781249
|
||||
inappPlayerBackground=-14602949
|
||||
avatar_nameInMessagePink=-624741
|
||||
windowBackgroundWhiteGrayText=-8549479
|
||||
avatar_actionBarSelectorViolet=-12758164
|
||||
chat_attachPollBackground=-2183099
|
||||
avatar_nameInMessageBlue=-8796932
|
||||
dialogTextBlack=-592138
|
||||
actionBarDefault=-14602949
|
||||
|
@ -334,7 +342,7 @@ key_player_progressCachedBackground=-11245182
|
|||
chat_outTimeText=-7357217
|
||||
chat_outBubble=-12689014
|
||||
avatar_backgroundActionBarCyan=-14602949
|
||||
chat_attachFileBackground=-11359756
|
||||
chat_attachFileBackground=-10830604
|
||||
chat_attachHideBackground=-14074026
|
||||
chats_menuItemText=-369098753
|
||||
chats_message=-8549479
|
||||
|
@ -365,6 +373,7 @@ chat_outMediaIcon=-1
|
|||
chats_message_threeLines=-8549479
|
||||
player_actionBarSubtitle=-8549479
|
||||
chat_outAudioCacheSeekbar=-10120765
|
||||
chat_attachContactBackground=-2183099
|
||||
chats_sentClock=-11772054
|
||||
chat_inAudioSeekbar=-11443856
|
||||
avatar_subtitleInProfileRed=-7628894
|
||||
|
@ -375,7 +384,7 @@ chats_archiveBackground=-11036980
|
|||
dialog_liveLocationProgress=-9919529
|
||||
chat_inViews=-8812137
|
||||
chat_outLoaderSelected=-9919529
|
||||
dialogButtonSelector=352321535
|
||||
dialogButtonSelector=-13483690
|
||||
chats_archivePinBackground=-13746613
|
||||
player_actionBarItems=-1
|
||||
chat_sentError=-633010
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.content.pm.ActivityInfo;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
|
@ -40,6 +41,7 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.CallLog;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.Settings;
|
||||
|
@ -1317,6 +1319,8 @@ public class AndroidUtilities {
|
|||
}
|
||||
}*/
|
||||
|
||||
private static ContentObserver callLogContentObserver;
|
||||
private static Runnable unregisterRunnable;
|
||||
private static boolean hasCallPermissions = Build.VERSION.SDK_INT >= 23;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -1333,9 +1337,38 @@ public class AndroidUtilities {
|
|||
telephonyService = (ITelephony) m.invoke(tm);
|
||||
telephonyService.silenceRinger();
|
||||
telephonyService.endCall();
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String obtainLoginPhoneCall(String pattern) {
|
||||
if (!hasCallPermissions) {
|
||||
return null;
|
||||
}
|
||||
try (Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(
|
||||
CallLog.Calls.CONTENT_URI,
|
||||
new String[]{CallLog.Calls.NUMBER, CallLog.Calls.DATE},
|
||||
CallLog.Calls.TYPE + " IN (" + CallLog.Calls.MISSED_TYPE + "," + CallLog.Calls.INCOMING_TYPE + "," + CallLog.Calls.REJECTED_TYPE + ")",
|
||||
null,
|
||||
"date DESC LIMIT 5")) {
|
||||
while (cursor.moveToNext()) {
|
||||
String number = cursor.getString(0);
|
||||
long date = cursor.getLong(1);
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.e("number = " + number);
|
||||
}
|
||||
if (Math.abs(System.currentTimeMillis() - date) >= 60 * 60 * 1000) {
|
||||
continue;
|
||||
}
|
||||
if (checkPhonePattern(pattern, number)) {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean checkPhonePattern(String pattern, String phone) {
|
||||
|
|
|
@ -15,12 +15,14 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
|||
private final Object sync = new Object();
|
||||
private int lastOffset;
|
||||
private boolean waitingForLoad;
|
||||
private boolean preview;
|
||||
|
||||
public AnimatedFileDrawableStream(TLRPC.Document d, Object p, int a) {
|
||||
public AnimatedFileDrawableStream(TLRPC.Document d, Object p, int a, boolean prev) {
|
||||
document = d;
|
||||
parentObject = p;
|
||||
currentAccount = a;
|
||||
loadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, 0);
|
||||
preview = prev;
|
||||
loadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, 0, preview);
|
||||
}
|
||||
|
||||
public int read(int offset, int readLength) {
|
||||
|
@ -37,8 +39,8 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
|||
while (availableLength == 0) {
|
||||
availableLength = loadOperation.getDownloadedLengthFromOffset(offset, readLength);
|
||||
if (availableLength == 0) {
|
||||
if (loadOperation.isPaused() || lastOffset != offset) {
|
||||
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, offset);
|
||||
if (loadOperation.isPaused() || lastOffset != offset || preview) {
|
||||
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, offset, preview);
|
||||
}
|
||||
synchronized (sync) {
|
||||
if (canceled) {
|
||||
|
@ -46,7 +48,9 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
|||
}
|
||||
countDownLatch = new CountDownLatch(1);
|
||||
}
|
||||
FileLoader.getInstance(currentAccount).setLoadingVideo(document, false, true);
|
||||
if (!preview) {
|
||||
FileLoader.getInstance(currentAccount).setLoadingVideo(document, false, true);
|
||||
}
|
||||
waitingForLoad = true;
|
||||
countDownLatch.await();
|
||||
waitingForLoad = false;
|
||||
|
@ -68,7 +72,7 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
|||
synchronized (sync) {
|
||||
if (countDownLatch != null) {
|
||||
countDownLatch.countDown();
|
||||
if (removeLoading && !canceled) {
|
||||
if (removeLoading && !canceled && !preview) {
|
||||
FileLoader.getInstance(currentAccount).removeLoadingVideo(document, false, true);
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +94,10 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
|||
return document;
|
||||
}
|
||||
|
||||
public boolean isPreview() {
|
||||
return preview;
|
||||
}
|
||||
|
||||
public int getCurrentAccount() {
|
||||
return currentAccount;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ public class ApplicationLoader extends Application {
|
|||
public static volatile boolean mainInterfacePausedStageQueue = true;
|
||||
public static volatile long mainInterfacePausedStageQueueTime;
|
||||
|
||||
public static boolean hasPlayServices;
|
||||
|
||||
public static File getFilesDirFixed() {
|
||||
for (int a = 0; a < 10; a++) {
|
||||
File path = ApplicationLoader.applicationContext.getFilesDir();
|
||||
|
@ -140,7 +142,6 @@ public class ApplicationLoader extends Application {
|
|||
TLRPC.User user = UserConfig.getInstance(a).getCurrentUser();
|
||||
if (user != null) {
|
||||
MessagesController.getInstance(a).putUser(user, true);
|
||||
MessagesController.getInstance(a).getBlockedUsers(true);
|
||||
SendMessagesHelper.getInstance(a).checkUnsentMessages();
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +222,7 @@ public class ApplicationLoader extends Application {
|
|||
|
||||
private void initPlayServices() {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (checkPlayServices()) {
|
||||
if (hasPlayServices = checkPlayServices()) {
|
||||
final String currentPushString = SharedConfig.pushString;
|
||||
if (!TextUtils.isEmpty(currentPushString)) {
|
||||
if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) {
|
||||
|
|
|
@ -23,6 +23,7 @@ public class BringAppForegroundService extends IntentService {
|
|||
protected void onHandleIntent(Intent intent) {
|
||||
Intent intent2 = new Intent(this, LaunchActivity.class);
|
||||
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent2.setAction(Intent.ACTION_MAIN);
|
||||
startActivity(intent2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ public class BuildVars {
|
|||
public static boolean LOGS_ENABLED = false;
|
||||
public static boolean USE_CLOUD_STRINGS = true;
|
||||
public static boolean CHECK_UPDATES = false;
|
||||
public static int BUILD_VERSION = 1648;
|
||||
public static String BUILD_VERSION_STRING = "5.9.0";
|
||||
public static int BUILD_VERSION = 1684;
|
||||
public static String BUILD_VERSION_STRING = "5.10.0";
|
||||
public static int APP_ID = 0; //obtain your own APP_ID at https://core.telegram.org/api/obtaining_api_id
|
||||
public static String APP_HASH = ""; //obtain your own APP_HASH at https://core.telegram.org/api/obtaining_api_id
|
||||
public static String HOCKEY_APP_HASH = "your-hockeyapp-api-key-here";
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package org.telegram.messenger;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ClearCacheService extends IntentService {
|
||||
|
||||
public ClearCacheService() {
|
||||
super("ClearCacheService");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
ApplicationLoader.postInitApplication();
|
||||
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
final int keepMedia = preferences.getInt("keep_media", 2);
|
||||
if (keepMedia == 2) {
|
||||
return;
|
||||
}
|
||||
Utilities.globalQueue.postRunnable(() -> {
|
||||
int days;
|
||||
if (keepMedia == 0) {
|
||||
days = 7;
|
||||
} else if (keepMedia == 1) {
|
||||
days = 30;
|
||||
} else {
|
||||
days = 3;
|
||||
}
|
||||
long currentTime = System.currentTimeMillis() / 1000 - 60 * 60 * 24 * days;
|
||||
final SparseArray<File> paths = ImageLoader.getInstance().createMediaPaths();
|
||||
for (int a = 0; a < paths.size(); a++) {
|
||||
if (paths.keyAt(a) == FileLoader.MEDIA_DIR_CACHE) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Utilities.clearDir(paths.valueAt(a).getAbsolutePath(), 0, currentTime);
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -211,7 +211,7 @@ public class DownloadController extends BaseController implements NotificationCe
|
|||
mediumPreset = new Preset(preferences.getString("preset1", "13_13_13_13_1048576_10485760_1048576_524288_1_1_1_0"));
|
||||
highPreset = new Preset(preferences.getString("preset2", "13_13_13_13_1048576_15728640_3145728_524288_1_1_1_0"));
|
||||
boolean newConfig;
|
||||
if (newConfig = preferences.contains("newConfig") || !getUserConfig().isClientActivated()) {
|
||||
if ((newConfig = preferences.contains("newConfig")) || !getUserConfig().isClientActivated()) {
|
||||
mobilePreset = new Preset(preferences.getString("mobilePreset", mediumPreset.toString()));
|
||||
wifiPreset = new Preset(preferences.getString("wifiPreset", highPreset.toString()));
|
||||
roamingPreset = new Preset(preferences.getString("roamingPreset", lowPreset.toString()));
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.io.File;
|
|||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
@ -114,6 +115,8 @@ public class FileLoadOperation {
|
|||
private int totalBytesCount;
|
||||
private int bytesCountPadding;
|
||||
private int streamStartOffset;
|
||||
private int streamPriorityStartOffset;
|
||||
private RequestInfo priorityRequestInfo;
|
||||
private FileLoadOperationDelegate delegate;
|
||||
private byte[] key;
|
||||
private byte[] iv;
|
||||
|
@ -386,6 +389,23 @@ public class FileLoadOperation {
|
|||
break;
|
||||
}
|
||||
}
|
||||
Collections.sort(ranges, (o1, o2) -> {
|
||||
if (o1.start > o2.start) {
|
||||
return 1;
|
||||
} else if (o1.start < o2.start) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
for (int a = 0; a < ranges.size() - 1; a++) {
|
||||
Range r1 = ranges.get(a);
|
||||
Range r2 = ranges.get(a + 1);
|
||||
if (r1.end == r2.start) {
|
||||
r1.end = r2.end;
|
||||
ranges.remove(a + 1);
|
||||
a--;
|
||||
}
|
||||
}
|
||||
if (!modified) {
|
||||
ranges.add(new Range(start, end));
|
||||
}
|
||||
|
@ -533,7 +553,7 @@ public class FileLoadOperation {
|
|||
}
|
||||
}
|
||||
|
||||
protected void removeStreamListener(final FileStreamLoadOperation operation) {
|
||||
protected void removeStreamListener(final FileLoadOperationStream operation) {
|
||||
Utilities.stageQueue.postRunnable(() -> {
|
||||
if (streamListeners == null) {
|
||||
return;
|
||||
|
@ -557,10 +577,10 @@ public class FileLoadOperation {
|
|||
}
|
||||
|
||||
public boolean start() {
|
||||
return start(null, 0);
|
||||
return start(null, 0, false);
|
||||
}
|
||||
|
||||
public boolean start(final FileLoadOperationStream stream, final int streamOffset) {
|
||||
public boolean start(final FileLoadOperationStream stream, final int streamOffset, final boolean steamPriority) {
|
||||
if (currentDownloadChunkSize == 0) {
|
||||
currentDownloadChunkSize = totalBytesCount >= bigFileSizeFrom ? downloadChunkSizeBig : downloadChunkSize;
|
||||
currentMaxDownloadRequests = totalBytesCount >= bigFileSizeFrom ? maxDownloadRequestsBig : maxDownloadRequests;
|
||||
|
@ -573,7 +593,27 @@ public class FileLoadOperation {
|
|||
if (streamListeners == null) {
|
||||
streamListeners = new ArrayList<>();
|
||||
}
|
||||
streamStartOffset = streamOffset / currentDownloadChunkSize * currentDownloadChunkSize;
|
||||
if (steamPriority) {
|
||||
int offset = streamOffset / currentDownloadChunkSize * currentDownloadChunkSize;
|
||||
if (priorityRequestInfo != null && priorityRequestInfo.offset != offset) {
|
||||
requestInfos.remove(priorityRequestInfo);
|
||||
requestedBytesCount -= currentDownloadChunkSize;
|
||||
removePart(notRequestedBytesRanges, priorityRequestInfo.offset, priorityRequestInfo.offset + currentDownloadChunkSize);
|
||||
if (priorityRequestInfo.requestToken != 0) {
|
||||
ConnectionsManager.getInstance(currentAccount).cancelRequest(priorityRequestInfo.requestToken, true);
|
||||
requestsCount--;
|
||||
}
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.d("frame get cancel request at offset " + priorityRequestInfo.offset);
|
||||
}
|
||||
priorityRequestInfo = null;
|
||||
}
|
||||
if (priorityRequestInfo == null) {
|
||||
streamPriorityStartOffset = offset;
|
||||
}
|
||||
} else {
|
||||
streamStartOffset = streamOffset / currentDownloadChunkSize * currentDownloadChunkSize;
|
||||
}
|
||||
streamListeners.add(stream);
|
||||
if (alreadyStarted) {
|
||||
if (preloadedBytesRanges != null && getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, streamStartOffset, 1) == 0) {
|
||||
|
@ -1549,12 +1589,13 @@ public class FileLoadOperation {
|
|||
protected void startDownloadRequest() {
|
||||
if (paused ||
|
||||
state != stateDownloading ||
|
||||
!nextPartWasPreloaded && (requestInfos.size() + delayedRequestInfos.size() >= currentMaxDownloadRequests) ||
|
||||
isPreloadVideoOperation && (requestedBytesCount > preloadMaxBytes || moovFound != 0 && requestInfos.size() > 0)) {
|
||||
streamPriorityStartOffset == 0 && (
|
||||
!nextPartWasPreloaded && (requestInfos.size() + delayedRequestInfos.size() >= currentMaxDownloadRequests) ||
|
||||
isPreloadVideoOperation && (requestedBytesCount > preloadMaxBytes || moovFound != 0 && requestInfos.size() > 0))) {
|
||||
return;
|
||||
}
|
||||
int count = 1;
|
||||
if (!nextPartWasPreloaded && (!isPreloadVideoOperation || moovFound != 0) && totalBytesCount > 0) {
|
||||
if (streamPriorityStartOffset == 0 && !nextPartWasPreloaded && (!isPreloadVideoOperation || moovFound != 0) && totalBytesCount > 0) {
|
||||
count = Math.max(0, currentMaxDownloadRequests - requestInfos.size());
|
||||
}
|
||||
|
||||
|
@ -1598,18 +1639,19 @@ public class FileLoadOperation {
|
|||
preloadNotRequestedBytesCount -= currentDownloadChunkSize;
|
||||
} else {
|
||||
if (notRequestedBytesRanges != null) {
|
||||
int sreamOffset = streamPriorityStartOffset != 0 ? streamPriorityStartOffset : streamStartOffset;
|
||||
int size = notRequestedBytesRanges.size();
|
||||
int minStart = Integer.MAX_VALUE;
|
||||
int minStreamStart = Integer.MAX_VALUE;
|
||||
for (int b = 0; b < size; b++) {
|
||||
Range range = notRequestedBytesRanges.get(b);
|
||||
if (streamStartOffset != 0) {
|
||||
if (range.start <= streamStartOffset && range.end > streamStartOffset) {
|
||||
minStreamStart = streamStartOffset;
|
||||
if (sreamOffset != 0) {
|
||||
if (range.start <= sreamOffset && range.end > sreamOffset) {
|
||||
minStreamStart = sreamOffset;
|
||||
minStart = Integer.MAX_VALUE;
|
||||
break;
|
||||
}
|
||||
if (streamStartOffset < range.start && range.start < minStreamStart) {
|
||||
if (sreamOffset < range.start && range.start < minStreamStart) {
|
||||
minStreamStart = range.start;
|
||||
}
|
||||
}
|
||||
|
@ -1687,11 +1729,24 @@ public class FileLoadOperation {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (streamPriorityStartOffset != 0) {
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.d("frame get offset = " + streamPriorityStartOffset);
|
||||
}
|
||||
streamPriorityStartOffset = 0;
|
||||
priorityRequestInfo = requestInfo;
|
||||
}
|
||||
|
||||
requestInfo.requestToken = ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> {
|
||||
if (!requestInfos.contains(requestInfo)) {
|
||||
return;
|
||||
}
|
||||
if (requestInfo == priorityRequestInfo) {
|
||||
if (BuildVars.DEBUG_VERSION) {
|
||||
FileLog.d("frame get request completed " + priorityRequestInfo.offset);
|
||||
}
|
||||
priorityRequestInfo = null;
|
||||
}
|
||||
if (error != null) {
|
||||
if (FileRefController.isFileRefError(error.text)) {
|
||||
requestReference(requestInfo);
|
||||
|
|
|
@ -507,7 +507,7 @@ public class FileLoader extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
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 int locationSize, final int priority, final FileLoadOperationStream stream, final int streamOffset, 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 int locationSize, final int priority, final FileLoadOperationStream stream, final int streamOffset, boolean streamPriority, final int cacheType) {
|
||||
String fileName = null;
|
||||
if (location != null) {
|
||||
fileName = getAttachFileName(location, locationExt);
|
||||
|
@ -553,15 +553,15 @@ public class FileLoader extends BaseController {
|
|||
downloadQueue.remove(index);
|
||||
if (stream != null) {
|
||||
if (downloadQueue == audioLoadOperationQueue) {
|
||||
if (operation.start(stream, streamOffset)) {
|
||||
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||
currentAudioLoadOperationsCount.put(datacenterId, currentAudioLoadOperationsCount.get(datacenterId) + 1);
|
||||
}
|
||||
} else if (downloadQueue == photoLoadOperationQueue) {
|
||||
if (operation.start(stream, streamOffset)) {
|
||||
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||
currentPhotoLoadOperationsCount.put(datacenterId, currentPhotoLoadOperationsCount.get(datacenterId) + 1);
|
||||
}
|
||||
} else {
|
||||
if (operation.start(stream, streamOffset)) {
|
||||
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||
currentLoadOperationsCount.put(datacenterId, currentLoadOperationsCount.get(datacenterId) + 1);
|
||||
}
|
||||
if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) {
|
||||
|
@ -578,7 +578,7 @@ public class FileLoader extends BaseController {
|
|||
if (stream != null) {
|
||||
pauseCurrentFileLoadOperations(operation);
|
||||
}
|
||||
operation.start(stream, streamOffset);
|
||||
operation.start(stream, streamOffset, streamPriority);
|
||||
if (downloadQueue == loadOperationQueue && !activeFileLoadOperation.contains(operation)) {
|
||||
activeFileLoadOperation.add(operation);
|
||||
}
|
||||
|
@ -676,7 +676,7 @@ public class FileLoader extends BaseController {
|
|||
int maxCount = priority > 0 ? 3 : 1;
|
||||
int count = currentAudioLoadOperationsCount.get(datacenterId);
|
||||
if (stream != null || count < maxCount) {
|
||||
if (operation.start(stream, streamOffset)) {
|
||||
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||
currentAudioLoadOperationsCount.put(datacenterId, count + 1);
|
||||
}
|
||||
} else {
|
||||
|
@ -686,7 +686,7 @@ public class FileLoader extends BaseController {
|
|||
int maxCount = priority > 0 ? 6 : 2;
|
||||
int count = currentPhotoLoadOperationsCount.get(datacenterId);
|
||||
if (stream != null || count < maxCount) {
|
||||
if (operation.start(stream, streamOffset)) {
|
||||
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||
currentPhotoLoadOperationsCount.put(datacenterId, count + 1);
|
||||
}
|
||||
} else {
|
||||
|
@ -696,7 +696,7 @@ public class FileLoader extends BaseController {
|
|||
int maxCount = priority > 0 ? 4 : 1;
|
||||
int count = currentLoadOperationsCount.get(datacenterId);
|
||||
if (stream != null || count < maxCount) {
|
||||
if (operation.start(stream, streamOffset)) {
|
||||
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||
currentLoadOperationsCount.put(datacenterId, count + 1);
|
||||
activeFileLoadOperation.add(operation);
|
||||
}
|
||||
|
@ -741,14 +741,14 @@ public class FileLoader extends BaseController {
|
|||
if (cacheType != 10 && !TextUtils.isEmpty(fileName) && !fileName.contains("" + Integer.MIN_VALUE)) {
|
||||
loadOperationPathsUI.put(fileName, true);
|
||||
}
|
||||
fileLoaderQueue.postRunnable(() -> loadFileInternal(document, secureDocument, webDocument, location, imageLocation, parentObject, locationExt, locationSize, priority, null, 0, cacheType));
|
||||
fileLoaderQueue.postRunnable(() -> loadFileInternal(document, secureDocument, webDocument, location, imageLocation, parentObject, locationExt, locationSize, priority, null, 0, false, cacheType));
|
||||
}
|
||||
|
||||
protected FileLoadOperation loadStreamFile(final FileLoadOperationStream stream, final TLRPC.Document document, final Object parentObject, final int offset) {
|
||||
protected FileLoadOperation loadStreamFile(final FileLoadOperationStream stream, final TLRPC.Document document, final Object parentObject, final int offset, final boolean priority) {
|
||||
final CountDownLatch semaphore = new CountDownLatch(1);
|
||||
final FileLoadOperation[] result = new FileLoadOperation[1];
|
||||
fileLoaderQueue.postRunnable(() -> {
|
||||
result[0] = loadFileInternal(document, null, null, null, null, parentObject, null, 0, 1, stream, offset, 0);
|
||||
result[0] = loadFileInternal(document, null, null, null, null, parentObject, null, 0, 1, stream, offset, priority, 0);
|
||||
semaphore.countDown();
|
||||
});
|
||||
try {
|
||||
|
@ -1049,7 +1049,7 @@ public class FileLoader extends BaseController {
|
|||
|
||||
public static String fixFileName(String fileName) {
|
||||
if (fileName != null) {
|
||||
fileName = fileName.replaceAll("[\u0001-\u001f<>:\"/\\\\|?*\u007f]+", "").trim();
|
||||
fileName = fileName.replaceAll("[\u0001-\u001f<>\u202E:\"/\\\\|?*\u007f]+", "").trim();
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
|
|
|
@ -420,7 +420,7 @@ public class FileRefController extends BaseController {
|
|||
}
|
||||
if (done) {
|
||||
multiMediaCache.remove(multiMedia);
|
||||
getSendMessagesHelper().performSendMessageRequestMulti(multiMedia, (ArrayList<MessageObject>) objects[1], (ArrayList<String>) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4]);
|
||||
AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequestMulti(multiMedia, (ArrayList<MessageObject>) objects[1], (ArrayList<String>) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4]));
|
||||
}
|
||||
} else if (requester.args[0] instanceof TLRPC.TL_messages_sendMedia) {
|
||||
TLRPC.TL_messages_sendMedia req = (TLRPC.TL_messages_sendMedia) requester.args[0];
|
||||
|
@ -431,7 +431,7 @@ public class FileRefController extends BaseController {
|
|||
TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media;
|
||||
mediaPhoto.id.file_reference = file_reference;
|
||||
}
|
||||
getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null);
|
||||
AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null));
|
||||
} else if (requester.args[0] instanceof TLRPC.TL_messages_editMessage) {
|
||||
TLRPC.TL_messages_editMessage req = (TLRPC.TL_messages_editMessage) requester.args[0];
|
||||
if (req.media instanceof TLRPC.TL_inputMediaDocument) {
|
||||
|
@ -441,7 +441,7 @@ public class FileRefController extends BaseController {
|
|||
TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media;
|
||||
mediaPhoto.id.file_reference = file_reference;
|
||||
}
|
||||
getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null);
|
||||
AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) requester.args[0], (MessageObject) requester.args[1], (String) requester.args[2], (SendMessagesHelper.DelayedMessage) requester.args[3], (Boolean) requester.args[4], (SendMessagesHelper.DelayedMessage) requester.args[5], null));
|
||||
} else if (requester.args[0] instanceof TLRPC.TL_messages_saveGif) {
|
||||
TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) requester.args[0];
|
||||
req.id.file_reference = file_reference;
|
||||
|
@ -489,10 +489,10 @@ public class FileRefController extends BaseController {
|
|||
Object[] objects = multiMediaCache.get(req);
|
||||
if (objects != null) {
|
||||
multiMediaCache.remove(req);
|
||||
getSendMessagesHelper().performSendMessageRequestMulti(req, (ArrayList<MessageObject>) objects[1], (ArrayList<String>) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4]);
|
||||
AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequestMulti(req, (ArrayList<MessageObject>) objects[1], (ArrayList<String>) objects[2], null, (SendMessagesHelper.DelayedMessage) objects[4]));
|
||||
}
|
||||
} else if (args[0] instanceof TLRPC.TL_messages_sendMedia || args[0] instanceof TLRPC.TL_messages_editMessage) {
|
||||
getSendMessagesHelper().performSendMessageRequest((TLObject) args[0], (MessageObject) args[1], (String) args[2], (SendMessagesHelper.DelayedMessage) args[3], (Boolean) args[4], (SendMessagesHelper.DelayedMessage) args[5], null);
|
||||
AndroidUtilities.runOnUIThread(() -> getSendMessagesHelper().performSendMessageRequest((TLObject) args[0], (MessageObject) args[1], (String) args[2], (SendMessagesHelper.DelayedMessage) args[3], (Boolean) args[4], (SendMessagesHelper.DelayedMessage) args[5], null));
|
||||
} else if (args[0] instanceof TLRPC.TL_messages_saveGif) {
|
||||
TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) args[0];
|
||||
//do nothing
|
||||
|
|
|
@ -69,7 +69,7 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
} else if (document.mime_type.startsWith("audio")) {
|
||||
document.attributes.add(new TLRPC.TL_documentAttributeAudio());
|
||||
}
|
||||
loadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, currentOffset = (int) dataSpec.position);
|
||||
loadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, currentOffset = (int) dataSpec.position, false);
|
||||
bytesRemaining = dataSpec.length == C.LENGTH_UNSET ? document.size - dataSpec.position : dataSpec.length;
|
||||
if (bytesRemaining < 0) {
|
||||
throw new EOFException();
|
||||
|
@ -95,15 +95,17 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
if (bytesRemaining < readLength) {
|
||||
readLength = (int) bytesRemaining;
|
||||
}
|
||||
while (availableLength == 0) {
|
||||
while (availableLength == 0 && opened) {
|
||||
availableLength = loadOperation.getDownloadedLengthFromOffset(currentOffset, readLength);
|
||||
if (availableLength == 0) {
|
||||
FileLog.d("not found bytes " + offset);
|
||||
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, currentOffset);
|
||||
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, currentOffset, false);
|
||||
countDownLatch = new CountDownLatch(1);
|
||||
countDownLatch.await();
|
||||
}
|
||||
}
|
||||
if (!opened) {
|
||||
return 0;
|
||||
}
|
||||
file.readFully(buffer, offset, availableLength);
|
||||
currentOffset += availableLength;
|
||||
bytesRemaining -= availableLength;
|
||||
|
@ -125,9 +127,6 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
if (loadOperation != null) {
|
||||
loadOperation.removeStreamListener(this);
|
||||
}
|
||||
if (countDownLatch != null) {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
if (file != null) {
|
||||
try {
|
||||
file.close();
|
||||
|
@ -141,6 +140,9 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
|||
opened = false;
|
||||
transferEnded();
|
||||
}
|
||||
if (countDownLatch != null) {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -777,6 +777,8 @@ public class ImageLoader {
|
|||
int h = Math.min(512, AndroidUtilities.dp(170.6f));
|
||||
boolean precache = false;
|
||||
boolean limitFps = false;
|
||||
int autoRepeat = 1;
|
||||
int[] colors = null;
|
||||
if (cacheImage.filter != null) {
|
||||
String[] args = cacheImage.filter.split("_");
|
||||
if (args.length >= 2) {
|
||||
|
@ -791,8 +793,29 @@ public class ImageLoader {
|
|||
precache = SharedConfig.getDevicePerfomanceClass() != SharedConfig.PERFORMANCE_CLASS_HIGH;
|
||||
}
|
||||
}
|
||||
if (args.length >= 3) {
|
||||
if ("nr".equals(args[2])) {
|
||||
autoRepeat = 2;
|
||||
} else if ("nrs".equals(args[2])) {
|
||||
autoRepeat = 3;
|
||||
}
|
||||
}
|
||||
if (args.length >= 5) {
|
||||
if ("c1".equals(args[4])) {
|
||||
colors = new int[]{0xf77e41, 0xca907a, 0xffb139, 0xedc5a5, 0xffd140, 0xf7e3c3, 0xffdf79, 0xfbefd6};
|
||||
} else if ("c2".equals(args[4])) {
|
||||
colors = new int[]{0xf77e41, 0xaa7c60, 0xffb139, 0xc8a987, 0xffd140, 0xddc89f, 0xffdf79, 0xe6d6b2};
|
||||
} else if ("c3".equals(args[4])) {
|
||||
colors = new int[]{0xf77e41, 0x8c6148, 0xffb139, 0xad8562, 0xffd140, 0xc49e76, 0xffdf79, 0xd4b188};
|
||||
} else if ("c4".equals(args[4])) {
|
||||
colors = new int[]{0xf77e41, 0x6e3c2c, 0xffb139, 0x925a34, 0xffd140, 0xa16e46, 0xffdf79, 0xac7a52};
|
||||
} else if ("c5".equals(args[4])) {
|
||||
colors = new int[]{0xf77e41, 0x291c12, 0xffb139, 0x472a22, 0xffd140, 0x573b30, 0xffdf79, 0x68493c};
|
||||
}
|
||||
}
|
||||
}
|
||||
RLottieDrawable lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, w, h, precache, limitFps);
|
||||
RLottieDrawable lottieDrawable = new RLottieDrawable(cacheImage.finalFilePath, w, h, precache, limitFps, colors);
|
||||
lottieDrawable.setAutoRepeat(autoRepeat);
|
||||
onPostExecute(lottieDrawable);
|
||||
} else if (cacheImage.animatedFile) {
|
||||
synchronized (sync) {
|
||||
|
@ -802,9 +825,9 @@ public class ImageLoader {
|
|||
}
|
||||
AnimatedFileDrawable fileDrawable;
|
||||
if (AUTOPLAY_FILTER.equals(cacheImage.filter) && !(cacheImage.imageLocation.document instanceof TLRPC.TL_documentEncrypted)) {
|
||||
fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, false, cacheImage.size, cacheImage.imageLocation.document instanceof TLRPC.Document ? cacheImage.imageLocation.document : null, cacheImage.parentObject, cacheImage.currentAccount);
|
||||
fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, false, cacheImage.size, cacheImage.imageLocation.document instanceof TLRPC.Document ? cacheImage.imageLocation.document : null, cacheImage.parentObject, cacheImage.currentAccount, false);
|
||||
} else {
|
||||
fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, "d".equals(cacheImage.filter), 0, null, null, cacheImage.currentAccount);
|
||||
fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, "d".equals(cacheImage.filter), 0, null, null, cacheImage.currentAccount, false);
|
||||
}
|
||||
Thread.interrupted();
|
||||
onPostExecute(fileDrawable);
|
||||
|
|
|
@ -31,6 +31,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
|
||||
public interface ImageReceiverDelegate {
|
||||
void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb);
|
||||
default void onAnimationReady(ImageReceiver imageReceiver) {
|
||||
}
|
||||
}
|
||||
|
||||
public static class BitmapHolder {
|
||||
|
@ -152,6 +154,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
private boolean allowStartAnimation = true;
|
||||
private boolean useSharedAnimationQueue;
|
||||
private boolean allowDecodeSingleFrame;
|
||||
private int autoRepeat = 1;
|
||||
private boolean animationReadySent;
|
||||
|
||||
private boolean crossfadeWithOldImage;
|
||||
private boolean crossfadingWithThumb;
|
||||
|
@ -936,6 +940,12 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
if (lottieDrawable != null) {
|
||||
lottieDrawable.setCurrentParentView(parentView);
|
||||
}
|
||||
if ((animation != null || lottieDrawable != null) && !animationNotReady && !animationReadySent) {
|
||||
animationReadySent = true;
|
||||
if (delegate != null) {
|
||||
delegate.onAnimationReady(this);
|
||||
}
|
||||
}
|
||||
int orientation = 0;
|
||||
BitmapShader shaderToUse = null;
|
||||
if (!forcePreview && currentMediaDrawable != null && !animationNotReady) {
|
||||
|
@ -1399,6 +1409,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
allowDecodeSingleFrame = value;
|
||||
}
|
||||
|
||||
public void setAutoRepeat(int value) {
|
||||
autoRepeat = value;
|
||||
RLottieDrawable drawable = getLottieAnimation();
|
||||
if (drawable != null) {
|
||||
drawable.setAutoRepeat(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void setUseSharedAnimationQueue(boolean value) {
|
||||
useSharedAnimationQueue = value;
|
||||
}
|
||||
|
@ -1618,6 +1636,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
fileDrawable.start();
|
||||
}
|
||||
fileDrawable.setAllowDecodeSingleFrame(allowDecodeSingleFrame);
|
||||
animationReadySent = false;
|
||||
} else if (drawable instanceof RLottieDrawable) {
|
||||
RLottieDrawable fileDrawable = (RLottieDrawable) drawable;
|
||||
fileDrawable.addParentView(parentView);
|
||||
|
@ -1625,6 +1644,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
|||
fileDrawable.start();
|
||||
}
|
||||
fileDrawable.setAllowDecodeSingleFrame(true);
|
||||
fileDrawable.setAutoRepeat(autoRepeat);
|
||||
animationReadySent = false;
|
||||
}
|
||||
if (parentView != null) {
|
||||
if (invalidateAll) {
|
||||
|
|
|
@ -139,6 +139,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
|
||||
public static class AlbumEntry {
|
||||
public int bucketId;
|
||||
public boolean videoOnly;
|
||||
public String bucketName;
|
||||
public PhotoEntry coverPhoto;
|
||||
public ArrayList<PhotoEntry> photos = new ArrayList<>();
|
||||
|
@ -358,6 +359,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
public static AlbumEntry allMediaAlbumEntry;
|
||||
public static AlbumEntry allPhotosAlbumEntry;
|
||||
public static AlbumEntry allVideosAlbumEntry;
|
||||
public static ArrayList<AlbumEntry> allMediaAlbums = new ArrayList<>();
|
||||
public static ArrayList<AlbumEntry> allPhotoAlbums = new ArrayList<>();
|
||||
private static Runnable broadcastPhotosRunnable;
|
||||
|
||||
private boolean isPaused = false;
|
||||
|
@ -1763,7 +1766,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
private void playNextMessageWithoutOrder(boolean byStop) {
|
||||
ArrayList<MessageObject> currentPlayList = SharedConfig.shuffleMusic ? shuffledPlaylist : playlist;
|
||||
|
||||
if (byStop && SharedConfig.repeatMode == 2 && !forceLoopCurrentPlaylist) {
|
||||
if (byStop && (SharedConfig.repeatMode == 2 || SharedConfig.repeatMode == 1 && currentPlayList.size() == 1) && !forceLoopCurrentPlaylist) {
|
||||
cleanupPlayer(false, false);
|
||||
MessageObject messageObject = currentPlayList.get(currentPlaylistNum);
|
||||
messageObject.audioProgress = 0;
|
||||
|
@ -2081,7 +2084,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
return currentPlaybackSpeed;
|
||||
}
|
||||
|
||||
private void updateVideoState(MessageObject messageObject, int playCount[], boolean destroyAtEnd, boolean playWhenReady, int playbackState) {
|
||||
private void updateVideoState(MessageObject messageObject, int[] playCount, boolean destroyAtEnd, boolean playWhenReady, int playbackState) {
|
||||
if (videoPlayer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -2495,7 +2498,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
@Override
|
||||
public void onStateChanged(boolean playWhenReady, int playbackState) {
|
||||
if (playbackState == ExoPlayer.STATE_ENDED || (playbackState == ExoPlayer.STATE_IDLE || playbackState == ExoPlayer.STATE_BUFFERING) && playWhenReady && messageObject.audioProgress >= 0.999f) {
|
||||
if (!playlist.isEmpty() && playlist.size() > 1) {
|
||||
if (!playlist.isEmpty() && (playlist.size() > 1 || !messageObject.isVoice())) {
|
||||
playNextMessageWithoutOrder(true);
|
||||
} else {
|
||||
cleanupPlayer(true, true, messageObject != null && messageObject.isVoice(), false);
|
||||
|
@ -3017,13 +3020,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
if (!destFile.exists()) {
|
||||
destFile.createNewFile();
|
||||
}
|
||||
FileChannel source = null;
|
||||
FileChannel destination = null;
|
||||
boolean result = true;
|
||||
long lastProgress = System.currentTimeMillis() - 500;
|
||||
try {
|
||||
source = new FileInputStream(sourceFile).getChannel();
|
||||
destination = new FileOutputStream(destFile).getChannel();
|
||||
try (FileChannel source = new FileInputStream(sourceFile).getChannel(); FileChannel destination = new FileOutputStream(destFile).getChannel()) {
|
||||
long size = source.size();
|
||||
for (long a = 0; a < size; a += 4096) {
|
||||
if (cancelled[0]) {
|
||||
|
@ -3047,21 +3046,6 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
result = false;
|
||||
} finally {
|
||||
try {
|
||||
if (source != null) {
|
||||
source.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//
|
||||
}
|
||||
try {
|
||||
if (destination != null) {
|
||||
destination.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//
|
||||
}
|
||||
}
|
||||
if (cancelled[0]) {
|
||||
destFile.delete();
|
||||
|
@ -3148,18 +3132,12 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
public static String getFileName(Uri uri) {
|
||||
String result = null;
|
||||
if (uri.getScheme().equals("content")) {
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null);
|
||||
try (Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
} finally {
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result == null) {
|
||||
|
@ -3340,6 +3318,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
|
||||
if (allVideosAlbum == null) {
|
||||
allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideos", R.string.AllVideos), photoEntry);
|
||||
allVideosAlbum.videoOnly = true;
|
||||
int index = 0;
|
||||
if (allMediaAlbum != null) {
|
||||
index++;
|
||||
|
@ -3408,6 +3387,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
|||
broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, cameraAlbumIdFinal, allMediaAlbumFinal, allPhotosAlbumFinal, allVideosAlbumFinal, 1000);
|
||||
return;
|
||||
}
|
||||
allMediaAlbums = mediaAlbumsSorted;
|
||||
allPhotoAlbums = photoAlbumsSorted;
|
||||
broadcastPhotosRunnable = null;
|
||||
allPhotosAlbumEntry = allPhotosAlbumFinal;
|
||||
allMediaAlbumEntry = allMediaAlbumFinal;
|
||||
|
|
|
@ -120,16 +120,18 @@ public class MediaDataController extends BaseController {
|
|||
public static final int TYPE_MASK = 1;
|
||||
public static final int TYPE_FAVE = 2;
|
||||
public static final int TYPE_FEATURED = 3;
|
||||
public static final int TYPE_EMOJI = 4;
|
||||
|
||||
private ArrayList<TLRPC.TL_messages_stickerSet>[] stickerSets = new ArrayList[]{new ArrayList<>(), new ArrayList<>(), new ArrayList(0), new ArrayList()};
|
||||
private ArrayList<TLRPC.TL_messages_stickerSet>[] stickerSets = new ArrayList[]{new ArrayList<>(), new ArrayList<>(), new ArrayList(0), new ArrayList(), new ArrayList()};
|
||||
private LongSparseArray<TLRPC.Document>[] stickersByIds = new LongSparseArray[]{new LongSparseArray<>(), new LongSparseArray<>(), new LongSparseArray(), new LongSparseArray(), new LongSparseArray()};
|
||||
private LongSparseArray<TLRPC.TL_messages_stickerSet> stickerSetsById = new LongSparseArray<>();
|
||||
private LongSparseArray<TLRPC.TL_messages_stickerSet> installedStickerSetsById = new LongSparseArray<>();
|
||||
private LongSparseArray<TLRPC.TL_messages_stickerSet> groupStickerSets = new LongSparseArray<>();
|
||||
private HashMap<String, TLRPC.TL_messages_stickerSet> stickerSetsByName = new HashMap<>();
|
||||
private boolean[] loadingStickers = new boolean[4];
|
||||
private boolean[] stickersLoaded = new boolean[4];
|
||||
private int[] loadHash = new int[4];
|
||||
private int[] loadDate = new int[4];
|
||||
private boolean[] loadingStickers = new boolean[5];
|
||||
private boolean[] stickersLoaded = new boolean[5];
|
||||
private int[] loadHash = new int[5];
|
||||
private int[] loadDate = new int[5];
|
||||
|
||||
private int[] archivedStickersCount = new int[2];
|
||||
|
||||
|
@ -235,6 +237,9 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
|
||||
public void addRecentSticker(final int type, Object parentObject, TLRPC.Document document, int date, boolean remove) {
|
||||
if (document == null) {
|
||||
return;
|
||||
}
|
||||
boolean found = false;
|
||||
for (int a = 0; a < recentStickers[type].size(); a++) {
|
||||
TLRPC.Document image = recentStickers[type].get(a);
|
||||
|
@ -392,26 +397,44 @@ public class MediaDataController extends BaseController {
|
|||
if (existingSet == null) {
|
||||
return;
|
||||
}
|
||||
LongSparseArray<TLRPC.Document> documents = new LongSparseArray<>();
|
||||
for (int a = 0, size = set.documents.size(); a < size; a++) {
|
||||
TLRPC.Document document = set.documents.get(a);
|
||||
documents.put(document.id, document);
|
||||
}
|
||||
boolean changed = false;
|
||||
for (int a = 0, size = existingSet.documents.size(); a < size; a++) {
|
||||
TLRPC.Document document = set.documents.get(a);
|
||||
TLRPC.Document newDocument = documents.get(document.id);
|
||||
if (newDocument != null) {
|
||||
existingSet.documents.set(a, newDocument);
|
||||
changed = true;
|
||||
if ("AnimatedEmojies".equals(set.set.short_name)) {
|
||||
changed = true;
|
||||
existingSet.documents = set.documents;
|
||||
existingSet.packs = set.packs;
|
||||
existingSet.set = set.set;
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
LongSparseArray<TLRPC.Document> stickersById = getStickerByIds(TYPE_EMOJI);
|
||||
for (int b = 0; b < set.documents.size(); b++) {
|
||||
TLRPC.Document document = set.documents.get(b);
|
||||
stickersById.put(document.id, document);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
LongSparseArray<TLRPC.Document> documents = new LongSparseArray<>();
|
||||
for (int a = 0, size = set.documents.size(); a < size; a++) {
|
||||
TLRPC.Document document = set.documents.get(a);
|
||||
documents.put(document.id, document);
|
||||
}
|
||||
for (int a = 0, size = existingSet.documents.size(); a < size; a++) {
|
||||
TLRPC.Document document = set.documents.get(a);
|
||||
TLRPC.Document newDocument = documents.get(document.id);
|
||||
if (newDocument != null) {
|
||||
existingSet.documents.set(a, newDocument);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
if (isGroupSet) {
|
||||
putSetToCache(existingSet);
|
||||
} else {
|
||||
final int type = set.set.masks ? TYPE_MASK : TYPE_IMAGE;
|
||||
int type = set.set.masks ? TYPE_MASK : TYPE_IMAGE;
|
||||
putStickersToCache(type, stickerSets[type], loadDate[type], loadHash[type]);
|
||||
if ("AnimatedEmojies".equals(set.set.short_name)) {
|
||||
type = TYPE_EMOJI;
|
||||
putStickersToCache(type, stickerSets[type], loadDate[type], loadHash[type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -524,6 +547,22 @@ public class MediaDataController extends BaseController {
|
|||
return allStickersFeatured;
|
||||
}
|
||||
|
||||
public TLRPC.Document getEmojiAnimatedSticker(CharSequence message) {
|
||||
String emoji = message.toString().replace("\uFE0F", "");
|
||||
ArrayList<TLRPC.TL_messages_stickerSet> arrayList = getStickerSets(MediaDataController.TYPE_EMOJI);
|
||||
for (int a = 0, N = arrayList.size(); a < N; a++) {
|
||||
TLRPC.TL_messages_stickerSet set = arrayList.get(a);
|
||||
for (int b = 0, N2 = set.packs.size(); b < N2; b++) {
|
||||
TLRPC.TL_stickerPack pack = set.packs.get(b);
|
||||
if (!pack.documents.isEmpty() && TextUtils.equals(pack.emoticon, emoji)) {
|
||||
LongSparseArray<TLRPC.Document> stickerByIds = getStickerByIds(MediaDataController.TYPE_EMOJI);
|
||||
return stickerByIds.get(pack.documents.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean canAddStickerToFavorites() {
|
||||
return !stickersLoaded[0] || stickerSets[0].size() >= 5 || !recentStickers[TYPE_FAVE].isEmpty();
|
||||
}
|
||||
|
@ -536,6 +575,10 @@ public class MediaDataController extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
public LongSparseArray<TLRPC.Document> getStickerByIds(int type) {
|
||||
return stickersByIds[type];
|
||||
}
|
||||
|
||||
public ArrayList<TLRPC.StickerSetCovered> getFeaturedStickerSets() {
|
||||
return featuredStickerSets;
|
||||
}
|
||||
|
@ -1185,7 +1228,7 @@ public class MediaDataController extends BaseController {
|
|||
if (featuredStickerSets.isEmpty() || !getMessagesController().preloadFeaturedStickers) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
} else if (type != TYPE_EMOJI) {
|
||||
loadArchivedStickersCount(type, cache);
|
||||
}
|
||||
loadingStickers[type] = true;
|
||||
|
@ -1228,24 +1271,36 @@ public class MediaDataController extends BaseController {
|
|||
response.sets.add(featuredStickerSets.get(a).set);
|
||||
}
|
||||
processLoadStickersResponse(type, response);
|
||||
return;
|
||||
}
|
||||
TLObject req;
|
||||
final int hash;
|
||||
if (type == TYPE_IMAGE) {
|
||||
req = new TLRPC.TL_messages_getAllStickers();
|
||||
hash = ((TLRPC.TL_messages_getAllStickers) req).hash = force ? 0 : loadHash[type];
|
||||
} 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) {
|
||||
final ArrayList<TLRPC.TL_messages_stickerSet> newStickerArray = new ArrayList<>();
|
||||
newStickerArray.add((TLRPC.TL_messages_stickerSet) response);
|
||||
processLoadedStickers(type, newStickerArray, false, (int) (System.currentTimeMillis() / 1000), calcStickersHash(newStickerArray));
|
||||
} else {
|
||||
processLoadedStickers(type, null, false, (int) (System.currentTimeMillis() / 1000), 0);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
req = new TLRPC.TL_messages_getMaskStickers();
|
||||
hash = ((TLRPC.TL_messages_getMaskStickers) req).hash = force ? 0 : loadHash[type];
|
||||
}
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (response instanceof TLRPC.TL_messages_allStickers) {
|
||||
processLoadStickersResponse(type, (TLRPC.TL_messages_allStickers) response);
|
||||
TLObject req;
|
||||
final int hash;
|
||||
if (type == TYPE_IMAGE) {
|
||||
req = new TLRPC.TL_messages_getAllStickers();
|
||||
hash = ((TLRPC.TL_messages_getAllStickers) req).hash = force ? 0 : loadHash[type];
|
||||
} else {
|
||||
processLoadedStickers(type, null, false, (int) (System.currentTimeMillis() / 1000), hash);
|
||||
req = new TLRPC.TL_messages_getMaskStickers();
|
||||
hash = ((TLRPC.TL_messages_getMaskStickers) req).hash = force ? 0 : loadHash[type];
|
||||
}
|
||||
}));
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (response instanceof TLRPC.TL_messages_allStickers) {
|
||||
processLoadStickersResponse(type, (TLRPC.TL_messages_allStickers) response);
|
||||
} else {
|
||||
processLoadedStickers(type, null, false, (int) (System.currentTimeMillis() / 1000), hash);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1411,12 +1466,14 @@ public class MediaDataController extends BaseController {
|
|||
for (int a = 0; a < stickerSets[type].size(); a++) {
|
||||
TLRPC.StickerSet set = stickerSets[type].get(a).set;
|
||||
stickerSetsById.remove(set.id);
|
||||
installedStickerSetsById.remove(set.id);
|
||||
stickerSetsByName.remove(set.short_name);
|
||||
if (type != TYPE_FEATURED && type != TYPE_EMOJI) {
|
||||
installedStickerSetsById.remove(set.id);
|
||||
}
|
||||
}
|
||||
for (int a = 0; a < stickerSetsByIdNew.size(); a++) {
|
||||
stickerSetsById.put(stickerSetsByIdNew.keyAt(a), stickerSetsByIdNew.valueAt(a));
|
||||
if (type != TYPE_FEATURED) {
|
||||
if (type != TYPE_FEATURED && type != TYPE_EMOJI) {
|
||||
installedStickerSetsById.put(stickerSetsByIdNew.keyAt(a), stickerSetsByIdNew.valueAt(a));
|
||||
}
|
||||
}
|
||||
|
@ -1424,6 +1481,7 @@ public class MediaDataController extends BaseController {
|
|||
stickerSets[type] = stickerSetsNew;
|
||||
loadHash[type] = hash;
|
||||
loadDate[type] = date;
|
||||
stickersByIds[type] = stickersByIdNew;
|
||||
if (type == TYPE_IMAGE) {
|
||||
allStickers = allStickersNew;
|
||||
stickersByEmoji = stickersByEmojiNew;
|
||||
|
@ -3524,7 +3582,6 @@ public class MediaDataController extends BaseController {
|
|||
|
||||
public static void addStyleToText(TextStyleSpan span, int start, int end, Spannable editable, boolean allowIntersection) {
|
||||
try {
|
||||
allowIntersection = true;
|
||||
CharacterStyle[] spans = editable.getSpans(start, end, CharacterStyle.class);
|
||||
if (spans != null && spans.length > 0) {
|
||||
for (int a = 0; a < spans.length; a++) {
|
||||
|
|
|
@ -75,6 +75,8 @@ public class MessageObject {
|
|||
public boolean localChannel;
|
||||
public boolean localEdit;
|
||||
public TLRPC.Message messageOwner;
|
||||
public TLRPC.Document emojiAnimatedSticker;
|
||||
public String emojiAnimatedStickerColor;
|
||||
public CharSequence messageText;
|
||||
public CharSequence linkDescription;
|
||||
public CharSequence caption;
|
||||
|
@ -87,6 +89,7 @@ public class MessageObject {
|
|||
public String monthKey;
|
||||
public boolean deleted;
|
||||
public float audioProgress;
|
||||
public float forceSeekTo = -1;
|
||||
public int audioProgressMs;
|
||||
public float bufferedProgress;
|
||||
public float gifState;
|
||||
|
@ -141,6 +144,7 @@ public class MessageObject {
|
|||
|
||||
public static Pattern urlPattern;
|
||||
public static Pattern instagramUrlPattern;
|
||||
public static Pattern videoTimeUrlPattern;
|
||||
|
||||
public CharSequence vCardData;
|
||||
|
||||
|
@ -745,7 +749,11 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public MessageObject(int accountNum, TLRPC.Message message, boolean generateLayout) {
|
||||
this(accountNum, message, null, null, null, null, generateLayout, 0);
|
||||
this(accountNum, message, null, null, null, null, null, generateLayout, 0);
|
||||
}
|
||||
|
||||
public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyToMessage, boolean generateLayout) {
|
||||
this(accountNum, message, replyToMessage, null, null, null, null, generateLayout, 0);
|
||||
}
|
||||
|
||||
public MessageObject(int accountNum, TLRPC.Message message, AbstractMap<Integer, TLRPC.User> users, AbstractMap<Integer, TLRPC.Chat> chats, boolean generateLayout) {
|
||||
|
@ -753,22 +761,23 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public MessageObject(int accountNum, TLRPC.Message message, SparseArray<TLRPC.User> users, SparseArray<TLRPC.Chat> chats, boolean generateLayout) {
|
||||
this(accountNum, message, null, null, users, chats, generateLayout, 0);
|
||||
this(accountNum, message, null, null, null, users, chats, generateLayout, 0);
|
||||
}
|
||||
|
||||
public MessageObject(int accountNum, TLRPC.Message message, AbstractMap<Integer, TLRPC.User> users, AbstractMap<Integer, TLRPC.Chat> chats, boolean generateLayout, long eid) {
|
||||
this(accountNum, message, users, chats, null, null, generateLayout, eid);
|
||||
this(accountNum, message, null, users, chats, null, null, generateLayout, eid);
|
||||
}
|
||||
|
||||
public MessageObject(int accountNum, TLRPC.Message message, AbstractMap<Integer, TLRPC.User> users, AbstractMap<Integer, TLRPC.Chat> chats, SparseArray<TLRPC.User> sUsers, SparseArray<TLRPC.Chat> sChats, boolean generateLayout, long eid) {
|
||||
public MessageObject(int accountNum, TLRPC.Message message, MessageObject replyToMessage, AbstractMap<Integer, TLRPC.User> users, AbstractMap<Integer, TLRPC.Chat> chats, SparseArray<TLRPC.User> sUsers, SparseArray<TLRPC.Chat> sChats, boolean generateLayout, long eid) {
|
||||
Theme.createChatResources(null, true);
|
||||
|
||||
currentAccount = accountNum;
|
||||
messageOwner = message;
|
||||
replyMessageObject = replyToMessage;
|
||||
eventId = eid;
|
||||
|
||||
if (message.replyMessage != null) {
|
||||
replyMessageObject = new MessageObject(currentAccount, message.replyMessage, users, chats, sUsers, sChats, false, eid);
|
||||
replyMessageObject = new MessageObject(currentAccount, message.replyMessage, null, users, chats, sUsers, sChats, false, eid);
|
||||
}
|
||||
|
||||
TLRPC.User fromUser = null;
|
||||
|
@ -807,7 +816,40 @@ public class MessageObject {
|
|||
int[] emojiOnly = SharedConfig.allowBigEmoji ? new int[1] : null;
|
||||
messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly);
|
||||
checkEmojiOnly(emojiOnly);
|
||||
generateLayout(fromUser);
|
||||
emojiAnimatedSticker = null;
|
||||
if (emojiOnlyCount == 1 && !(message.media instanceof TLRPC.TL_messageMediaWebPage) && message.entities.isEmpty()) {
|
||||
CharSequence emoji = messageText;
|
||||
int index;
|
||||
if ((index = TextUtils.indexOf(emoji, "\uD83C\uDFFB")) >= 0) {
|
||||
emojiAnimatedStickerColor = "_c1";
|
||||
emoji = emoji.subSequence(0, index);
|
||||
} else if ((index = TextUtils.indexOf(emoji, "\uD83C\uDFFC")) >= 0) {
|
||||
emojiAnimatedStickerColor = "_c2";
|
||||
emoji = emoji.subSequence(0, index);
|
||||
} else if ((index = TextUtils.indexOf(emoji, "\uD83C\uDFFD")) >= 0) {
|
||||
emojiAnimatedStickerColor = "_c3";
|
||||
emoji = emoji.subSequence(0, index);
|
||||
} else if ((index = TextUtils.indexOf(emoji, "\uD83C\uDFFE")) >= 0) {
|
||||
emojiAnimatedStickerColor = "_c4";
|
||||
emoji = emoji.subSequence(0, index);
|
||||
} else if ((index = TextUtils.indexOf(emoji, "\uD83C\uDFFF")) >= 0) {
|
||||
emojiAnimatedStickerColor = "_c5";
|
||||
emoji = emoji.subSequence(0, index);
|
||||
} else {
|
||||
emojiAnimatedStickerColor = "";
|
||||
}
|
||||
emojiAnimatedSticker = MediaDataController.getInstance(currentAccount).getEmojiAnimatedSticker(emoji);
|
||||
}
|
||||
if (emojiAnimatedSticker == null) {
|
||||
generateLayout(fromUser);
|
||||
} else {
|
||||
type = 1000;
|
||||
if (isSticker()) {
|
||||
type = TYPE_STICKER;
|
||||
} else if (isAnimatedSticker()) {
|
||||
type = TYPE_ANIMATED_STICKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
layoutCreated = generateLayout;
|
||||
generateThumbs(false);
|
||||
|
@ -966,6 +1008,15 @@ public class MessageObject {
|
|||
if (n == null) {
|
||||
n = new TLRPC.TL_chatAdminRights();
|
||||
}
|
||||
if (!TextUtils.equals(event.action.prev_participant.rank, event.action.new_participant.rank)) {
|
||||
if (TextUtils.isEmpty(event.action.new_participant.rank)) {
|
||||
rights.append('\n').append('-').append(' ');
|
||||
rights.append(LocaleController.getString("EventLogPromotedRemovedTitle", R.string.EventLogPromotedRemovedTitle));
|
||||
} else {
|
||||
rights.append('\n').append('+').append(' ');
|
||||
rights.append(LocaleController.formatString("EventLogPromotedTitle", R.string.EventLogPromotedTitle, event.action.new_participant.rank));
|
||||
}
|
||||
}
|
||||
if (o.change_info != n.change_info) {
|
||||
rights.append('\n').append(n.change_info ? '+' : '-').append(' ');
|
||||
rights.append(chat.megagroup ? LocaleController.getString("EventLogPromotedChangeGroupInfo", R.string.EventLogPromotedChangeGroupInfo) : LocaleController.getString("EventLogPromotedChangeChannelInfo", R.string.EventLogPromotedChangeChannelInfo));
|
||||
|
@ -1418,6 +1469,21 @@ public class MessageObject {
|
|||
TLRPC.TL_channelLocation channelLocation = (TLRPC.TL_channelLocation) location.new_value;
|
||||
messageText = replaceWithLink(LocaleController.formatString("EventLogChangedLocation", R.string.EventLogChangedLocation, channelLocation.address), "un1", fromUser);
|
||||
}
|
||||
} else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionToggleSlowMode) {
|
||||
TLRPC.TL_channelAdminLogEventActionToggleSlowMode slowMode = (TLRPC.TL_channelAdminLogEventActionToggleSlowMode) event.action;
|
||||
if (slowMode.new_value == 0) {
|
||||
messageText = replaceWithLink(LocaleController.getString("EventLogToggledSlowmodeOff", R.string.EventLogToggledSlowmodeOff), "un1", fromUser);
|
||||
} else {
|
||||
String string;
|
||||
if (slowMode.new_value < 60) {
|
||||
string = LocaleController.formatPluralString("Seconds", slowMode.new_value);
|
||||
} else if (slowMode.new_value < 60 * 60) {
|
||||
string = LocaleController.formatPluralString("Minutes", slowMode.new_value / 60);
|
||||
} else {
|
||||
string = LocaleController.formatPluralString("Hours", slowMode.new_value / 60 / 60);
|
||||
}
|
||||
messageText = replaceWithLink(LocaleController.formatString("EventLogToggledSlowmodeOn", R.string.EventLogToggledSlowmodeOn, string), "un1", fromUser);
|
||||
}
|
||||
} else {
|
||||
messageText = "unsupported " + event.action;
|
||||
}
|
||||
|
@ -2224,7 +2290,7 @@ public class MessageObject {
|
|||
} else {
|
||||
messageText = LocaleController.getString("AttachPhoto", R.string.AttachPhoto);
|
||||
}
|
||||
} else if (isVideo() || messageOwner.media instanceof TLRPC.TL_messageMediaDocument && messageOwner.media.document instanceof TLRPC.TL_documentEmpty && messageOwner.media.ttl_seconds != 0) {
|
||||
} else if (isVideo() || messageOwner.media instanceof TLRPC.TL_messageMediaDocument && getDocument() instanceof TLRPC.TL_documentEmpty && messageOwner.media.ttl_seconds != 0) {
|
||||
if (messageOwner.media.ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) {
|
||||
messageText = LocaleController.getString("AttachDestructingVideo", R.string.AttachDestructingVideo);
|
||||
} else {
|
||||
|
@ -2262,7 +2328,7 @@ public class MessageObject {
|
|||
} else if (isGif()) {
|
||||
messageText = LocaleController.getString("AttachGif", R.string.AttachGif);
|
||||
} else {
|
||||
String name = FileLoader.getDocumentFileName(messageOwner.media.document);
|
||||
String name = FileLoader.getDocumentFileName(getDocument());
|
||||
if (name != null && name.length() > 0) {
|
||||
messageText = name;
|
||||
} else {
|
||||
|
@ -2283,12 +2349,18 @@ public class MessageObject {
|
|||
int oldType = type;
|
||||
isRoundVideoCached = 0;
|
||||
if (messageOwner instanceof TLRPC.TL_message || messageOwner instanceof TLRPC.TL_messageForwarded_old2) {
|
||||
if (isMediaEmpty()) {
|
||||
if (emojiAnimatedSticker != null) {
|
||||
if (isSticker()) {
|
||||
type = TYPE_STICKER;
|
||||
} else {
|
||||
type = TYPE_ANIMATED_STICKER;
|
||||
}
|
||||
} else if (isMediaEmpty()) {
|
||||
type = 0;
|
||||
if (TextUtils.isEmpty(messageText) && eventId == 0) {
|
||||
messageText = "Empty message";
|
||||
}
|
||||
} else if (messageOwner.media.ttl_seconds != 0 && (messageOwner.media.photo instanceof TLRPC.TL_photoEmpty || messageOwner.media.document instanceof TLRPC.TL_documentEmpty)) {
|
||||
} else if (messageOwner.media.ttl_seconds != 0 && (messageOwner.media.photo instanceof TLRPC.TL_photoEmpty || getDocument() instanceof TLRPC.TL_documentEmpty)) {
|
||||
contentType = 1;
|
||||
type = 10;
|
||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
|
@ -2310,8 +2382,9 @@ public class MessageObject {
|
|||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) {
|
||||
type = 0;
|
||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
if (messageOwner.media.document != null && messageOwner.media.document.mime_type != null) {
|
||||
if (isGifDocument(messageOwner.media.document)) {
|
||||
TLRPC.Document document = getDocument();
|
||||
if (document != null && document.mime_type != null) {
|
||||
if (isGifDocument(document)) {
|
||||
type = 8;
|
||||
} else if (isSticker()) {
|
||||
type = TYPE_STICKER;
|
||||
|
@ -2394,8 +2467,9 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public String getMimeType() {
|
||||
if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
return messageOwner.media.document.mime_type;
|
||||
TLRPC.Document document = getDocument();
|
||||
if (document != null) {
|
||||
return document.mime_type;
|
||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) {
|
||||
TLRPC.WebDocument photo = ((TLRPC.TL_messageMediaInvoice) messageOwner.media).photo;
|
||||
if (photo != null) {
|
||||
|
@ -2404,9 +2478,7 @@ public class MessageObject {
|
|||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
return "image/jpeg";
|
||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
|
||||
if (messageOwner.media.webpage.document != null) {
|
||||
return messageOwner.media.document.mime_type;
|
||||
} else if (messageOwner.media.webpage.photo != null) {
|
||||
if (messageOwner.media.webpage.photo != null) {
|
||||
return "image/jpeg";
|
||||
}
|
||||
}
|
||||
|
@ -2551,6 +2623,16 @@ public class MessageObject {
|
|||
}
|
||||
photoThumbsObject = messageOwner.action.photo;
|
||||
}
|
||||
} else if (emojiAnimatedSticker != null) {
|
||||
if (TextUtils.isEmpty(emojiAnimatedStickerColor) && isDocumentHasThumb(emojiAnimatedSticker)) {
|
||||
if (!update || photoThumbs == null) {
|
||||
photoThumbs = new ArrayList<>();
|
||||
photoThumbs.addAll(emojiAnimatedSticker.thumbs);
|
||||
} else if (photoThumbs != null && !photoThumbs.isEmpty()) {
|
||||
updatePhotoSizeLocations(photoThumbs, emojiAnimatedSticker.thumbs);
|
||||
}
|
||||
photoThumbsObject = emojiAnimatedSticker;
|
||||
}
|
||||
} else if (messageOwner.media != null && !(messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) {
|
||||
if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
TLRPC.Photo photo = messageOwner.media.photo;
|
||||
|
@ -2576,7 +2658,7 @@ public class MessageObject {
|
|||
}
|
||||
photoThumbsObject = messageOwner.media.photo;
|
||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
TLRPC.Document document = messageOwner.media.document;
|
||||
TLRPC.Document document = getDocument();
|
||||
if (isDocumentHasThumb(document)) {
|
||||
if (!update || photoThumbs == null) {
|
||||
photoThumbs = new ArrayList<>();
|
||||
|
@ -2719,7 +2801,7 @@ public class MessageObject {
|
|||
ext = fileName.substring(idx + 1);
|
||||
}
|
||||
if (ext == null || ext.length() == 0) {
|
||||
ext = messageOwner.media.document.mime_type;
|
||||
ext = getDocument().mime_type;
|
||||
}
|
||||
if (ext == null) {
|
||||
ext = "";
|
||||
|
@ -2730,7 +2812,7 @@ public class MessageObject {
|
|||
|
||||
public String getFileName() {
|
||||
if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
return FileLoader.getAttachFileName(messageOwner.media.document);
|
||||
return FileLoader.getAttachFileName(getDocument());
|
||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
ArrayList<TLRPC.PhotoSize> sizes = messageOwner.media.photo.sizes;
|
||||
if (sizes.size() > 0) {
|
||||
|
@ -2852,7 +2934,7 @@ public class MessageObject {
|
|||
if (!(linkDescription instanceof Spannable)) {
|
||||
linkDescription = new SpannableStringBuilder(linkDescription);
|
||||
}
|
||||
addUsernamesAndHashtags(isOutOwner(), linkDescription, false, hashtagsType);
|
||||
addUrlsByPattern(isOutOwner(), linkDescription, false, hashtagsType, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2896,23 +2978,25 @@ public class MessageObject {
|
|||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
addUsernamesAndHashtags(isOutOwner(), caption, true, 0);
|
||||
} else {
|
||||
try {
|
||||
Linkify.addLinks((Spannable) caption, Linkify.PHONE_NUMBERS);
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
addUrlsByPattern(isOutOwner(), caption, true, 0, 0);
|
||||
}
|
||||
|
||||
addEntitiesToText(caption, useManualParse);
|
||||
if (isVideo()) {
|
||||
addUrlsByPattern(isOutOwner(), caption, true, 3, getDuration());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addUsernamesAndHashtags(boolean isOut, CharSequence charSequence, boolean botCommands, int hashtagsType) {
|
||||
private static void addUrlsByPattern(boolean isOut, CharSequence charSequence, boolean botCommands, int patternType, int duration) {
|
||||
try {
|
||||
Matcher matcher;
|
||||
if (hashtagsType == 1) {
|
||||
if (patternType == 3) {
|
||||
if (videoTimeUrlPattern == null) {
|
||||
videoTimeUrlPattern = Pattern.compile("\\b(?:(\\d{1,2}):)?(\\d{1,3}):([0-5][0-9])\\b");
|
||||
}
|
||||
matcher = videoTimeUrlPattern.matcher(charSequence);
|
||||
} else if (patternType == 1) {
|
||||
if (instagramUrlPattern == null) {
|
||||
instagramUrlPattern = Pattern.compile("(^|\\s|\\()@[a-zA-Z\\d_.]{1,32}|(^|\\s|\\()#[\\w.]+");
|
||||
}
|
||||
|
@ -2923,47 +3007,73 @@ public class MessageObject {
|
|||
}
|
||||
matcher = urlPattern.matcher(charSequence);
|
||||
}
|
||||
Spannable spannable = (Spannable) charSequence;
|
||||
while (matcher.find()) {
|
||||
int start = matcher.start();
|
||||
int end = matcher.end();
|
||||
char ch = charSequence.charAt(start);
|
||||
if (hashtagsType != 0) {
|
||||
if (ch != '@' && ch != '#') {
|
||||
start++;
|
||||
}
|
||||
ch = charSequence.charAt(start);
|
||||
if (ch != '@' && ch != '#') {
|
||||
URLSpanNoUnderline url = null;
|
||||
if (patternType == 3) {
|
||||
URLSpan[] spans = spannable.getSpans(start, end, URLSpan.class);
|
||||
if (spans != null && spans.length > 0) {
|
||||
continue;
|
||||
}
|
||||
int count = matcher.groupCount();
|
||||
int s1 = matcher.start(1);
|
||||
int e1 = matcher.end(1);
|
||||
int s2 = matcher.start(2);
|
||||
int e2 = matcher.end(2);
|
||||
int s3 = matcher.start(3);
|
||||
int e3 = matcher.end(3);
|
||||
int minutes = Utilities.parseInt(charSequence.subSequence(s2, e2));
|
||||
int seconds = Utilities.parseInt(charSequence.subSequence(s3, e3));
|
||||
int hours = s1 >= 0 && e1 >= 0 ? Utilities.parseInt(charSequence.subSequence(s1, e1)) : -1;
|
||||
seconds += minutes * 60;
|
||||
if (hours > 0) {
|
||||
seconds += hours * 60 * 60;
|
||||
}
|
||||
if (seconds > duration) {
|
||||
continue;
|
||||
}
|
||||
url = new URLSpanNoUnderline("video?" + seconds);
|
||||
} else {
|
||||
if (ch != '@' && ch != '#' && ch != '/' && ch != '$') {
|
||||
start++;
|
||||
}
|
||||
}
|
||||
URLSpanNoUnderline url = null;
|
||||
if (hashtagsType == 1) {
|
||||
if (ch == '@') {
|
||||
url = new URLSpanNoUnderline("https://instagram.com/" + charSequence.subSequence(start + 1, end).toString());
|
||||
} else if (ch == '#') {
|
||||
url = new URLSpanNoUnderline("https://www.instagram.com/explore/tags/" + charSequence.subSequence(start + 1, end).toString());
|
||||
}
|
||||
} else if (hashtagsType == 2) {
|
||||
if (ch == '@') {
|
||||
url = new URLSpanNoUnderline("https://twitter.com/" + charSequence.subSequence(start + 1, end).toString());
|
||||
} else if (ch == '#') {
|
||||
url = new URLSpanNoUnderline("https://twitter.com/hashtag/" + charSequence.subSequence(start + 1, end).toString());
|
||||
}
|
||||
} else {
|
||||
if (charSequence.charAt(start) == '/') {
|
||||
if (botCommands) {
|
||||
url = new URLSpanBotCommand(charSequence.subSequence(start, end).toString(), isOut ? 1 : 0);
|
||||
char ch = charSequence.charAt(start);
|
||||
if (patternType != 0) {
|
||||
if (ch != '@' && ch != '#') {
|
||||
start++;
|
||||
}
|
||||
ch = charSequence.charAt(start);
|
||||
if (ch != '@' && ch != '#') {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
url = new URLSpanNoUnderline(charSequence.subSequence(start, end).toString());
|
||||
if (ch != '@' && ch != '#' && ch != '/' && ch != '$') {
|
||||
start++;
|
||||
}
|
||||
}
|
||||
if (patternType == 1) {
|
||||
if (ch == '@') {
|
||||
url = new URLSpanNoUnderline("https://instagram.com/" + charSequence.subSequence(start + 1, end).toString());
|
||||
} else if (ch == '#') {
|
||||
url = new URLSpanNoUnderline("https://www.instagram.com/explore/tags/" + charSequence.subSequence(start + 1, end).toString());
|
||||
}
|
||||
} else if (patternType == 2) {
|
||||
if (ch == '@') {
|
||||
url = new URLSpanNoUnderline("https://twitter.com/" + charSequence.subSequence(start + 1, end).toString());
|
||||
} else if (ch == '#') {
|
||||
url = new URLSpanNoUnderline("https://twitter.com/hashtag/" + charSequence.subSequence(start + 1, end).toString());
|
||||
}
|
||||
} else {
|
||||
if (charSequence.charAt(start) == '/') {
|
||||
if (botCommands) {
|
||||
url = new URLSpanBotCommand(charSequence.subSequence(start, end).toString(), isOut ? 1 : 0);
|
||||
}
|
||||
} else {
|
||||
url = new URLSpanNoUnderline(charSequence.subSequence(start, end).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (url != null) {
|
||||
((Spannable) charSequence).setSpan(url, start, end, 0);
|
||||
spannable.setSpan(url, start, end, 0);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -3051,7 +3161,7 @@ public class MessageObject {
|
|||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
addUsernamesAndHashtags(isOut, messageText, botCommands, 0);
|
||||
addUrlsByPattern(isOut, messageText, botCommands, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3116,7 +3226,8 @@ public class MessageObject {
|
|||
entity instanceof TLRPC.TL_messageEntityCode ||
|
||||
entity instanceof TLRPC.TL_messageEntityPre ||
|
||||
entity instanceof TLRPC.TL_messageEntityMentionName ||
|
||||
entity instanceof TLRPC.TL_inputMessageEntityMentionName) {
|
||||
entity instanceof TLRPC.TL_inputMessageEntityMentionName ||
|
||||
entity instanceof TLRPC.TL_messageEntityTextUrl) {
|
||||
if (spans != null && spans.length > 0) {
|
||||
for (int b = 0; b < spans.length; b++) {
|
||||
if (spans[b] == null) {
|
||||
|
@ -3161,7 +3272,7 @@ public class MessageObject {
|
|||
newRun.flags = TextStyleSpan.FLAG_STYLE_MENTION;
|
||||
newRun.urlEntity = entity;
|
||||
} else {
|
||||
if (useManualParse) {
|
||||
if (useManualParse && !(entity instanceof TLRPC.TL_messageEntityTextUrl)) {
|
||||
continue;
|
||||
}
|
||||
if ((entity instanceof TLRPC.TL_messageEntityUrl || entity instanceof TLRPC.TL_messageEntityTextUrl) && Browser.isPassportUrl(entity.url)) {
|
||||
|
@ -3313,6 +3424,10 @@ public class MessageObject {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isYouTubeVideo() {
|
||||
return messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage != null && !TextUtils.isEmpty(messageOwner.media.webpage.embed_url) && "YouTube".equals(messageOwner.media.webpage.site_name);
|
||||
}
|
||||
|
||||
public int getMaxMessageTextWidth() {
|
||||
int maxWidth = 0;
|
||||
if (AndroidUtilities.isTablet() && eventId != 0) {
|
||||
|
@ -3391,6 +3506,11 @@ public class MessageObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (isYouTubeVideo() || replyMessageObject != null && replyMessageObject.isYouTubeVideo()) {
|
||||
addUrlsByPattern(isOutOwner(), messageText, false, 3, Integer.MAX_VALUE);
|
||||
} else if (replyMessageObject != null && replyMessageObject.isVideo()) {
|
||||
addUrlsByPattern(isOutOwner(), messageText, false, 3, replyMessageObject.getDuration());
|
||||
}
|
||||
|
||||
boolean hasUrls = addEntitiesToText(messageText, useManualParse);
|
||||
|
||||
|
@ -3894,13 +4014,7 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public String getDocumentName() {
|
||||
TLRPC.Document document;
|
||||
if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
return FileLoader.getDocumentFileName(messageOwner.media.document);
|
||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
|
||||
return FileLoader.getDocumentFileName(messageOwner.media.webpage.document);
|
||||
}
|
||||
return "";
|
||||
return FileLoader.getDocumentFileName(getDocument());
|
||||
}
|
||||
|
||||
public static boolean isStickerDocument(TLRPC.Document document) {
|
||||
|
@ -4010,6 +4124,9 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public TLRPC.Document getDocument() {
|
||||
if (emojiAnimatedSticker != null) {
|
||||
return emojiAnimatedSticker;
|
||||
}
|
||||
return getDocument(messageOwner);
|
||||
}
|
||||
|
||||
|
@ -4108,13 +4225,22 @@ public class MessageObject {
|
|||
|
||||
public static TLRPC.InputStickerSet getInputStickerSet(TLRPC.Message message) {
|
||||
if (message.media != null && message.media.document != null) {
|
||||
for (TLRPC.DocumentAttribute attribute : message.media.document.attributes) {
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
||||
if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetEmpty) {
|
||||
return null;
|
||||
}
|
||||
return attribute.stickerset;
|
||||
return getInputStickerSet(message.media.document);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TLRPC.InputStickerSet getInputStickerSet(TLRPC.Document document) {
|
||||
if (document == null) {
|
||||
return null;
|
||||
}
|
||||
for (int a = 0, N = document.attributes.size(); a < N; a++) {
|
||||
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
||||
if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetEmpty) {
|
||||
return null;
|
||||
}
|
||||
return attribute.stickerset;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -4137,8 +4263,9 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public String getStrickerChar() {
|
||||
if (messageOwner.media != null && messageOwner.media.document != null) {
|
||||
for (TLRPC.DocumentAttribute attribute : messageOwner.media.document.attributes) {
|
||||
TLRPC.Document document = getDocument();
|
||||
if (document != null) {
|
||||
for (TLRPC.DocumentAttribute attribute : document.attributes) {
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
||||
return attribute.alt;
|
||||
}
|
||||
|
@ -4180,7 +4307,9 @@ public class MessageObject {
|
|||
}
|
||||
int photoHeight = 0;
|
||||
int photoWidth = 0;
|
||||
for (TLRPC.DocumentAttribute attribute : messageOwner.media.document.attributes) {
|
||||
TLRPC.Document document = getDocument();
|
||||
for (int a = 0, N = document.attributes.size(); a < N; a++) {
|
||||
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeImageSize) {
|
||||
photoWidth = attribute.w;
|
||||
photoHeight = attribute.h;
|
||||
|
@ -4242,8 +4371,12 @@ public class MessageObject {
|
|||
}
|
||||
|
||||
public String getStickerEmoji() {
|
||||
for (int a = 0; a < messageOwner.media.document.attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = messageOwner.media.document.attributes.get(a);
|
||||
TLRPC.Document document = getDocument();
|
||||
if (document == null) {
|
||||
return null;
|
||||
}
|
||||
for (int a = 0; a < document.attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
||||
return attribute.alt != null && attribute.alt.length() > 0 ? attribute.alt : null;
|
||||
}
|
||||
|
@ -4251,18 +4384,22 @@ public class MessageObject {
|
|||
return null;
|
||||
}
|
||||
|
||||
public boolean isAnimatedEmoji() {
|
||||
return emojiAnimatedSticker != null;
|
||||
}
|
||||
|
||||
public boolean isSticker() {
|
||||
if (type != 1000) {
|
||||
return type == TYPE_STICKER;
|
||||
}
|
||||
return isStickerMessage(messageOwner);
|
||||
return isStickerDocument(getDocument());
|
||||
}
|
||||
|
||||
public boolean isAnimatedSticker() {
|
||||
if (type != 1000) {
|
||||
return type == TYPE_ANIMATED_STICKER;
|
||||
}
|
||||
return isAnimatedStickerMessage(messageOwner);
|
||||
return isAnimatedStickerDocument(getDocument());
|
||||
}
|
||||
|
||||
public boolean isAnyKindOfSticker() {
|
||||
|
|
|
@ -104,6 +104,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
|
||||
public boolean loadingBlockedUsers = false;
|
||||
public SparseIntArray blockedUsers = new SparseIntArray();
|
||||
public int totalBlockedCount = -1;
|
||||
public boolean blockedEndReached;
|
||||
|
||||
private SparseArray<ArrayList<Integer>> channelViewsToSend = new SparseArray<>();
|
||||
private LongSparseArray<SparseArray<MessageObject>> pollsToCheck = new LongSparseArray<>();
|
||||
|
@ -133,7 +135,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
private ArrayList<Integer> loadingFullParticipants = new ArrayList<>();
|
||||
private ArrayList<Integer> loadedFullParticipants = new ArrayList<>();
|
||||
private ArrayList<Integer> loadedFullChats = new ArrayList<>();
|
||||
private SparseArray<ArrayList<Integer>> channelAdmins = new SparseArray<>();
|
||||
private SparseArray<SparseArray<String>> channelAdmins = new SparseArray<>();
|
||||
private SparseIntArray loadingChannelAdmins = new SparseIntArray();
|
||||
|
||||
private SparseIntArray migratedChats = new SparseIntArray();
|
||||
|
@ -205,6 +207,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
private boolean uploadingWallpaperBlurred;
|
||||
private boolean uploadingWallpaperMotion;
|
||||
|
||||
private boolean loadingAppConfig;
|
||||
|
||||
public boolean enableJoined;
|
||||
public String linkPrefix;
|
||||
public int maxGroupCount;
|
||||
|
@ -233,6 +237,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
public boolean blockedCountry;
|
||||
public boolean defaultP2pContacts;
|
||||
public boolean preloadFeaturedStickers;
|
||||
public float animatedEmojisZoom;
|
||||
public String venueSearchBot;
|
||||
public String gifSearchBot;
|
||||
public String imageSearchBot;
|
||||
|
@ -435,14 +440,46 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
gifSearchBot = mainPreferences.getString("gifSearchBot", "gif");
|
||||
imageSearchBot = mainPreferences.getString("imageSearchBot", "pic");
|
||||
blockedCountry = mainPreferences.getBoolean("blockedCountry", false);
|
||||
dcDomainName = mainPreferences.getString("dcDomainName", ConnectionsManager.native_isTestBackend(currentAccount) != 0 ? "tapv2.stel.com" : "apv2.stel.com");
|
||||
dcDomainName = mainPreferences.getString("dcDomainName2", ConnectionsManager.native_isTestBackend(currentAccount) != 0 ? "tapv3.stel.com" : "apv3.stel.com");
|
||||
webFileDatacenterId = mainPreferences.getInt("webFileDatacenterId", ConnectionsManager.native_isTestBackend(currentAccount) != 0 ? 2 : 4);
|
||||
suggestedLangCode = mainPreferences.getString("suggestedLangCode", "en");
|
||||
animatedEmojisZoom = mainPreferences.getFloat("animatedEmojisZoom", 0.625f);
|
||||
}
|
||||
|
||||
private void loadAppConfig() {
|
||||
if (loadingAppConfig) {
|
||||
return;
|
||||
}
|
||||
loadingAppConfig = true;
|
||||
TLRPC.TL_help_getAppConfig req = new TLRPC.TL_help_getAppConfig();
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (response instanceof TLRPC.TL_jsonObject) {
|
||||
SharedPreferences.Editor editor = mainPreferences.edit();
|
||||
boolean changed = false;
|
||||
TLRPC.TL_jsonObject object = (TLRPC.TL_jsonObject) response;
|
||||
for (int a = 0, N = object.value.size(); a < N; a++) {
|
||||
TLRPC.TL_jsonObjectValue value = object.value.get(a);
|
||||
if ("emojies_animated_zoom".equals(value.key) && value.value instanceof TLRPC.TL_jsonNumber) {
|
||||
TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value;
|
||||
if (animatedEmojisZoom != number.value) {
|
||||
animatedEmojisZoom = (float) number.value;
|
||||
editor.putFloat("animatedEmojisZoom", animatedEmojisZoom);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
editor.commit();
|
||||
}
|
||||
}
|
||||
loadingAppConfig = false;
|
||||
}));
|
||||
}
|
||||
|
||||
public void updateConfig(final TLRPC.TL_config config) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
getDownloadController().loadAutoDownloadConfig(false);
|
||||
loadAppConfig();
|
||||
maxMegagroupCount = config.megagroup_size_max;
|
||||
maxGroupCount = config.chat_size_max;
|
||||
maxEditTime = config.edit_time_limit;
|
||||
|
@ -563,7 +600,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
editor.putString("venueSearchBot", venueSearchBot);
|
||||
editor.putString("gifSearchBot", gifSearchBot);
|
||||
editor.putString("imageSearchBot", imageSearchBot);
|
||||
editor.putString("dcDomainName", dcDomainName);
|
||||
editor.putString("dcDomainName2", dcDomainName);
|
||||
editor.putInt("webFileDatacenterId", webFileDatacenterId);
|
||||
editor.putString("suggestedLangCode", suggestedLangCode);
|
||||
editor.commit();
|
||||
|
@ -783,6 +820,16 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
if (obj != null) {
|
||||
dialogMessagesByIds.put(newMsgId, obj);
|
||||
}
|
||||
int lowerId = (int) (long) did;
|
||||
if (lowerId < 0) {
|
||||
TLRPC.ChatFull chatFull = fullChats.get(-lowerId);
|
||||
TLRPC.Chat chat = getChat(-lowerId);
|
||||
if (chat != null && !ChatObject.hasAdminRights(chat) && chatFull != null && chatFull.slowmode_seconds != 0) {
|
||||
chatFull.slowmode_next_send_date = ConnectionsManager.getInstance(currentAccount).getCurrentTime() + chatFull.slowmode_seconds;
|
||||
chatFull.flags |= 262144;
|
||||
getMessagesStorage().updateChatInfo(chatFull, false);
|
||||
}
|
||||
}
|
||||
} else if (id == NotificationCenter.updateMessageMedia) {
|
||||
TLRPC.Message message = (TLRPC.Message) args[0];
|
||||
MessageObject existMessageObject = dialogMessagesByIds.get(message.id);
|
||||
|
@ -812,7 +859,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
editor = emojiPreferences.edit();
|
||||
editor.putLong("lastGifLoadTime", 0).putLong("lastStickersLoadTime", 0).putLong("lastStickersLoadTimeMask", 0).putLong("lastStickersLoadTimeFavs", 0).commit();
|
||||
editor = mainPreferences.edit();
|
||||
editor.remove("archivehint").remove("archivehint_l").remove("gifhint").remove("soundHint").remove("dcDomainName").remove("webFileDatacenterId").commit();
|
||||
editor.remove("archivehint").remove("archivehint_l").remove("gifhint").remove("soundHint").remove("dcDomainName2").remove("webFileDatacenterId").commit();
|
||||
|
||||
reloadingWebpages.clear();
|
||||
reloadingWebpagesPending.clear();
|
||||
|
@ -889,6 +936,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
dialogsEndReached.clear();
|
||||
serverDialogsEndReached.clear();
|
||||
|
||||
loadingAppConfig = false;
|
||||
|
||||
checkingTosUpdate = false;
|
||||
nextTosCheckTime = 0;
|
||||
nextProxyInfoCheckTime = 0;
|
||||
|
@ -900,6 +949,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
currentDeletingTaskChannelId = 0;
|
||||
gettingNewDeleteTask = false;
|
||||
loadingBlockedUsers = false;
|
||||
totalBlockedCount = -1;
|
||||
blockedEndReached = false;
|
||||
firstGettingTask = false;
|
||||
updatingState = false;
|
||||
resetingDialogs = false;
|
||||
|
@ -1395,53 +1446,69 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
});
|
||||
}
|
||||
|
||||
public boolean isChannelAdmin(int chatId, int uid) {
|
||||
ArrayList<Integer> array = channelAdmins.get(chatId);
|
||||
return array != null && array.indexOf(uid) >= 0;
|
||||
public String getAdminRank(int chatId, int uid) {
|
||||
SparseArray<String> array = channelAdmins.get(chatId);
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
return array.get(uid);
|
||||
}
|
||||
|
||||
public boolean isChannelAdminsLoaded(int chatId) {
|
||||
return channelAdmins.get(chatId) != null;
|
||||
}
|
||||
|
||||
public void loadChannelAdmins(final int chatId, final boolean cache) {
|
||||
if (loadingChannelAdmins.indexOfKey(chatId) >= 0) {
|
||||
int loadTime = loadingChannelAdmins.get(chatId);
|
||||
if (SystemClock.uptimeMillis() - loadTime < 60) {
|
||||
return;
|
||||
}
|
||||
loadingChannelAdmins.put(chatId, 0);
|
||||
loadingChannelAdmins.put(chatId, (int) (SystemClock.uptimeMillis() / 1000));
|
||||
if (cache) {
|
||||
getMessagesStorage().loadChannelAdmins(chatId);
|
||||
} else {
|
||||
TLRPC.TL_channels_getParticipants req = new TLRPC.TL_channels_getParticipants();
|
||||
ArrayList<Integer> array = channelAdmins.get(chatId);
|
||||
/*SparseArray<String> array = channelAdmins.get(chatId);
|
||||
if (array != null) {
|
||||
long acc = 0;
|
||||
ArrayList<Integer> values = new ArrayList<>();
|
||||
for (int a = 0; a < array.size(); a++) {
|
||||
acc = ((acc * 20261) + 0x80000000L + array.get(a)) % 0x80000000L;
|
||||
values.add(array.keyAt(a));
|
||||
}
|
||||
Collections.sort(values);
|
||||
long acc = 0;
|
||||
for (int a = 0; a < values.size(); a++) {
|
||||
acc = ((acc * 20261) + 0x80000000L + values.get(a)) % 0x80000000L;
|
||||
}
|
||||
req.hash = (int) acc;
|
||||
}
|
||||
}*/
|
||||
req.channel = getInputChannel(chatId);
|
||||
req.limit = 100;
|
||||
req.filter = new TLRPC.TL_channelParticipantsAdmins();
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
if (response instanceof TLRPC.TL_channels_channelParticipants) {
|
||||
TLRPC.TL_channels_channelParticipants participants = (TLRPC.TL_channels_channelParticipants) response;
|
||||
final ArrayList<Integer> array1 = new ArrayList<>(participants.participants.size());
|
||||
for (int a = 0; a < participants.participants.size(); a++) {
|
||||
array1.add(participants.participants.get(a).user_id);
|
||||
}
|
||||
processLoadedChannelAdmins(array1, chatId, false);
|
||||
processLoadedAdminsResponse(chatId, (TLRPC.TL_channels_channelParticipants) response);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void processLoadedChannelAdmins(final ArrayList<Integer> array, final int chatId, final boolean cache) {
|
||||
Collections.sort(array);
|
||||
public void processLoadedAdminsResponse(int chatId, TLRPC.TL_channels_channelParticipants participants) {
|
||||
final SparseArray<String> array1 = new SparseArray<>(participants.participants.size());
|
||||
for (int a = 0; a < participants.participants.size(); a++) {
|
||||
TLRPC.ChannelParticipant participant = participants.participants.get(a);
|
||||
array1.put(participant.user_id, participant.rank != null ? participant.rank : "");
|
||||
}
|
||||
processLoadedChannelAdmins(array1, chatId, false);
|
||||
}
|
||||
|
||||
public void processLoadedChannelAdmins(final SparseArray<String> array, final int chatId, final boolean cache) {
|
||||
if (!cache) {
|
||||
getMessagesStorage().putChannelAdmins(chatId, array);
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
loadingChannelAdmins.delete(chatId);
|
||||
channelAdmins.put(chatId, array);
|
||||
if (cache) {
|
||||
loadingChannelAdmins.delete(chatId);
|
||||
loadChannelAdmins(chatId, false);
|
||||
}
|
||||
});
|
||||
|
@ -1564,17 +1631,11 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
int index = blockedUsers.indexOfKey(user.id);
|
||||
if (userFull.blocked) {
|
||||
if (index < 0) {
|
||||
SparseIntArray ids = new SparseIntArray();
|
||||
ids.put(user.id, 1);
|
||||
getMessagesStorage().putBlockedUsers(ids, false);
|
||||
|
||||
blockedUsers.put(user.id, 1);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
||||
}
|
||||
} else {
|
||||
if (index >= 0) {
|
||||
getMessagesStorage().deleteBlockedUser(user.id);
|
||||
|
||||
blockedUsers.removeAt(index);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
||||
}
|
||||
|
@ -2053,11 +2114,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
TLRPC.TL_contacts_block req = new TLRPC.TL_contacts_block();
|
||||
req.id = getInputUser(user);
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
if (error == null) {
|
||||
SparseIntArray ids = new SparseIntArray();
|
||||
ids.put(user.id, 1);
|
||||
getMessagesStorage().putBlockedUsers(ids, false);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2079,6 +2136,18 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
});
|
||||
}
|
||||
|
||||
public void setChannelSlowMode(int chatId, int seconds) {
|
||||
TLRPC.TL_channels_toggleSlowMode req = new TLRPC.TL_channels_toggleSlowMode();
|
||||
req.seconds = seconds;
|
||||
req.channel = getInputChannel(chatId);
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
if (error == null) {
|
||||
getMessagesController().processUpdates((TLRPC.Updates) response, false);
|
||||
AndroidUtilities.runOnUIThread(() -> loadFullChat(chatId, 0, true), 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setDefaultBannedRole(final int chatId, TLRPC.TL_chatBannedRights rights, final boolean isChannel, final BaseFragment parentFragment) {
|
||||
if (rights == null) {
|
||||
return;
|
||||
|
@ -2096,7 +2165,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
});
|
||||
}
|
||||
|
||||
public void setUserAdminRole(final int chatId, TLRPC.User user, TLRPC.TL_chatAdminRights rights, final boolean isChannel, final BaseFragment parentFragment, boolean addingNew) {
|
||||
public void setUserAdminRole(final int chatId, TLRPC.User user, TLRPC.TL_chatAdminRights rights, String rank, final boolean isChannel, final BaseFragment parentFragment, boolean addingNew) {
|
||||
if (user == null || rights == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -2106,6 +2175,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
req.channel = getInputChannel(chat);
|
||||
req.user_id = getInputUser(user);
|
||||
req.admin_rights = rights;
|
||||
req.rank = rank;
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
if (error == null) {
|
||||
processUpdates((TLRPC.Updates) response, false);
|
||||
|
@ -2143,53 +2213,37 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
blockedUsers.delete(user.id);
|
||||
req.id = getInputUser(user);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> getMessagesStorage().deleteBlockedUser(user.id));
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void getBlockedUsers(boolean cache) {
|
||||
public void getBlockedUsers(boolean reset) {
|
||||
if (!getUserConfig().isClientActivated() || loadingBlockedUsers) {
|
||||
return;
|
||||
}
|
||||
loadingBlockedUsers = true;
|
||||
if (cache) {
|
||||
getMessagesStorage().getBlockedUsers();
|
||||
} else {
|
||||
TLRPC.TL_contacts_getBlocked req = new TLRPC.TL_contacts_getBlocked();
|
||||
req.offset = 0;
|
||||
req.limit = 200;
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||
SparseIntArray blocked = new SparseIntArray();
|
||||
ArrayList<TLRPC.User> users = null;
|
||||
if (error == null) {
|
||||
final TLRPC.contacts_Blocked res = (TLRPC.contacts_Blocked) response;
|
||||
for (TLRPC.TL_contactBlocked contactBlocked : res.blocked) {
|
||||
blocked.put(contactBlocked.user_id, 1);
|
||||
}
|
||||
users = res.users;
|
||||
getMessagesStorage().putUsersAndChats(res.users, null, true, true);
|
||||
getMessagesStorage().putBlockedUsers(blocked, true);
|
||||
TLRPC.TL_contacts_getBlocked req = new TLRPC.TL_contacts_getBlocked();
|
||||
req.offset = reset ? 0 : blockedUsers.size();
|
||||
req.limit = reset ? 20 : 100;
|
||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (response != null) {
|
||||
TLRPC.contacts_Blocked res = (TLRPC.contacts_Blocked) response;
|
||||
putUsers(res.users, false);
|
||||
getMessagesStorage().putUsersAndChats(res.users, null, true, true);
|
||||
if (reset) {
|
||||
blockedUsers.clear();
|
||||
}
|
||||
processLoadedBlockedUsers(blocked, users, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void processLoadedBlockedUsers(final SparseIntArray ids, final ArrayList<TLRPC.User> users, final boolean cache) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (users != null) {
|
||||
putUsers(users, cache);
|
||||
totalBlockedCount = Math.max(res.count, res.blocked.size());
|
||||
blockedEndReached = res.blocked.size() < req.limit;
|
||||
for (int a = 0, N = res.blocked.size(); a < N; a++) {
|
||||
TLRPC.TL_contactBlocked blocked = res.blocked.get(a);
|
||||
blockedUsers.put(blocked.user_id, 1);
|
||||
}
|
||||
loadingBlockedUsers = false;
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
||||
}
|
||||
loadingBlockedUsers = false;
|
||||
if (ids.size() == 0 && cache && !getUserConfig().blockedUsersLoaded) {
|
||||
getBlockedUsers(false);
|
||||
return;
|
||||
} else if (!cache) {
|
||||
getUserConfig().blockedUsersLoaded = true;
|
||||
getUserConfig().saveConfig(false);
|
||||
}
|
||||
blockedUsers = ids;
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
public void deleteUserPhoto(TLRPC.InputPhoto photo) {
|
||||
|
@ -2380,7 +2434,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
toSend.add(mid);
|
||||
}
|
||||
}
|
||||
getMessagesStorage().markMessagesAsDeleted(messages, true, channelId);
|
||||
getMessagesStorage().markMessagesAsDeleted(messages, true, channelId, forAll);
|
||||
getMessagesStorage().updateDialogsWithDeletedMessages(messages, null, true, channelId);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, messages, channelId);
|
||||
}
|
||||
|
@ -2819,23 +2873,22 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
}));
|
||||
}
|
||||
|
||||
public void loadChatInfo(final int chat_id, CountDownLatch countDownLatch, boolean force) {
|
||||
getMessagesStorage().loadChatInfo(chat_id, countDownLatch, force, false);
|
||||
}
|
||||
|
||||
public void processChatInfo(int chat_id, final TLRPC.ChatFull info, final ArrayList<TLRPC.User> usersArr, final boolean fromCache, boolean force, final boolean byChannelUsers, final MessageObject pinnedMessageObject) {
|
||||
if (fromCache && chat_id > 0 && !byChannelUsers) {
|
||||
loadFullChat(chat_id, 0, force);
|
||||
}
|
||||
if (info != null) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (fromCache && chat_id > 0 && !byChannelUsers) {
|
||||
loadFullChat(chat_id, 0, force);
|
||||
}
|
||||
if (info != null) {
|
||||
if (fullChats.get(chat_id) == null) {
|
||||
fullChats.put(chat_id, info);
|
||||
}
|
||||
putUsers(usersArr, fromCache);
|
||||
if (info.stickerset != null) {
|
||||
getMediaDataController().getGroupStickerSetById(info.stickerset);
|
||||
}
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, byChannelUsers, pinnedMessageObject);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void loadUserInfo(TLRPC.User user, boolean force, int classGuid) {
|
||||
|
@ -2843,15 +2896,22 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
}
|
||||
|
||||
public void processUserInfo(TLRPC.User user, final TLRPC.UserFull info, final boolean fromCache, boolean force, final MessageObject pinnedMessageObject, int classGuid) {
|
||||
if (fromCache) {
|
||||
loadFullUser(user, classGuid, force);
|
||||
}
|
||||
if (info != null) {
|
||||
if (fullUsers.get(user.id) == null) {
|
||||
fullUsers.put(user.id, info);
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (fromCache) {
|
||||
loadFullUser(user, classGuid, force);
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.userInfoDidLoad, user.id, info, pinnedMessageObject));
|
||||
}
|
||||
if (info != null) {
|
||||
if (fullUsers.get(user.id) == null) {
|
||||
fullUsers.put(user.id, info);
|
||||
if (info.blocked) {
|
||||
blockedUsers.put(user.id, 1);
|
||||
} else {
|
||||
blockedUsers.delete(user.id);
|
||||
}
|
||||
}
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.userInfoDidLoad, user.id, info, pinnedMessageObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void updateTimerProc() {
|
||||
|
@ -3196,6 +3256,9 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
nextProxyInfoCheckTime = res.expires;
|
||||
if (!noDialog) {
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (proxyDialog != null && did != proxyDialog.id) {
|
||||
removeProxyDialog();
|
||||
}
|
||||
proxyDialog = dialogs_dict.get(did);
|
||||
|
||||
if (proxyDialog != null) {
|
||||
|
@ -3341,22 +3404,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
getGlobalMainSettings().edit().putLong("proxy_dialog", proxyDialogId).remove("proxyDialogAddress").commit();
|
||||
checkingProxyInfoRequestId = 0;
|
||||
checkingProxyInfo = false;
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (proxyDialog != null) {
|
||||
int lowerId = (int) proxyDialog.id;
|
||||
if (lowerId < 0) {
|
||||
TLRPC.Chat chat = getChat(-lowerId);
|
||||
if (ChatObject.isNotInChat(chat) || chat.restricted) {
|
||||
removeDialog(proxyDialog);
|
||||
}
|
||||
} else {
|
||||
removeDialog(proxyDialog);
|
||||
}
|
||||
proxyDialog = null;
|
||||
sortDialogs(null);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
}
|
||||
});
|
||||
AndroidUtilities.runOnUIThread(this::removeProxyDialog);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -3374,25 +3422,28 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
checkingProxyInfoRequestId = 0;
|
||||
}
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
if (proxyDialog != null) {
|
||||
int lowerId = (int) proxyDialog.id;
|
||||
if (lowerId < 0) {
|
||||
TLRPC.Chat chat = getChat(-lowerId);
|
||||
if (ChatObject.isNotInChat(chat) || chat.restricted) {
|
||||
removeDialog(proxyDialog);
|
||||
}
|
||||
} else {
|
||||
removeDialog(proxyDialog);
|
||||
}
|
||||
proxyDialog = null;
|
||||
sortDialogs(null);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
}
|
||||
});
|
||||
AndroidUtilities.runOnUIThread(this::removeProxyDialog);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeProxyDialog() {
|
||||
if (proxyDialog == null) {
|
||||
return;
|
||||
}
|
||||
int lowerId = (int) proxyDialog.id;
|
||||
if (lowerId < 0) {
|
||||
TLRPC.Chat chat = getChat(-lowerId);
|
||||
if (ChatObject.isNotInChat(chat) || chat.restricted) {
|
||||
removeDialog(proxyDialog);
|
||||
}
|
||||
} else {
|
||||
removeDialog(proxyDialog);
|
||||
}
|
||||
proxyDialog = null;
|
||||
sortDialogs(null);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload);
|
||||
}
|
||||
|
||||
public boolean isProxyDialog(long did, boolean checkLeft) {
|
||||
return proxyDialog != null && proxyDialog.id == did && (!checkLeft || isLeftProxyChannel);
|
||||
}
|
||||
|
@ -6192,7 +6243,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
return 0;
|
||||
}
|
||||
|
||||
public void convertToMegaGroup(final Context context, int chat_id, MessagesStorage.IntCallback convertRunnable) {
|
||||
public void convertToMegaGroup(final Context context, int chat_id, BaseFragment fragment, MessagesStorage.IntCallback convertRunnable) {
|
||||
TLRPC.TL_messages_migrateChat req = new TLRPC.TL_messages_migrateChat();
|
||||
req.chat_id = chat_id;
|
||||
final AlertDialog progressDialog = new AlertDialog(context, 3);
|
||||
|
@ -6228,11 +6279,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
|
||||
builder.setMessage(LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred));
|
||||
builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null);
|
||||
builder.show().setCanceledOnTouchOutside(true);
|
||||
AlertsCreator.processError(currentAccount, error, fragment, req, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -7993,7 +8040,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
}
|
||||
});
|
||||
getMessagesStorage().deletePushMessages(dialogId, ids);
|
||||
ArrayList<Long> dialogIds = getMessagesStorage().markMessagesAsDeleted(ids, false, channelId);
|
||||
ArrayList<Long> dialogIds = getMessagesStorage().markMessagesAsDeleted(ids, false, channelId, true);
|
||||
getMessagesStorage().updateDialogsWithDeletedMessages(ids, dialogIds, false, channelId);
|
||||
});
|
||||
}
|
||||
|
@ -9172,13 +9219,6 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
getSecretChatHelper().processUpdateEncryption((TLRPC.TL_updateEncryption) baseUpdate, usersDict);
|
||||
} else if (baseUpdate instanceof TLRPC.TL_updateUserBlocked) {
|
||||
final TLRPC.TL_updateUserBlocked finalUpdate = (TLRPC.TL_updateUserBlocked) baseUpdate;
|
||||
if (finalUpdate.blocked) {
|
||||
SparseIntArray ids = new SparseIntArray();
|
||||
ids.put(finalUpdate.user_id, 1);
|
||||
getMessagesStorage().putBlockedUsers(ids, false);
|
||||
} else {
|
||||
getMessagesStorage().deleteBlockedUser(finalUpdate.user_id);
|
||||
}
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> {
|
||||
if (finalUpdate.blocked) {
|
||||
if (blockedUsers.indexOfKey(finalUpdate.user_id) < 0) {
|
||||
|
@ -10286,7 +10326,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
final int key = deletedMessages.keyAt(a);
|
||||
final ArrayList<Integer> arrayList = deletedMessages.valueAt(a);
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
ArrayList<Long> dialogIds = getMessagesStorage().markMessagesAsDeleted(arrayList, false, key);
|
||||
ArrayList<Long> dialogIds = getMessagesStorage().markMessagesAsDeleted(arrayList, false, key, true);
|
||||
getMessagesStorage().updateDialogsWithDeletedMessages(arrayList, dialogIds, false, key);
|
||||
});
|
||||
}
|
||||
|
@ -10296,7 +10336,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
final int key = clearHistoryMessages.keyAt(a);
|
||||
final int id = clearHistoryMessages.valueAt(a);
|
||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
||||
ArrayList<Long> dialogIds = getMessagesStorage().markMessagesAsDeleted(key, id, false);
|
||||
ArrayList<Long> dialogIds = getMessagesStorage().markMessagesAsDeleted(key, id, false, true);
|
||||
getMessagesStorage().updateDialogsWithDeletedMessages(new ArrayList<>(), dialogIds, false, key);
|
||||
});
|
||||
}
|
||||
|
@ -10392,7 +10432,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
|||
if (message.isOut() && !message.isSending() && !message.isForwarded()) {
|
||||
if (message.isNewGif()) {
|
||||
getMediaDataController().addRecentGif(message.messageOwner.media.document, message.messageOwner.date);
|
||||
} else if (message.isSticker() || message.isAnimatedSticker()) {
|
||||
} else if (!message.isAnimatedEmoji() && (message.isSticker() || message.isAnimatedSticker())) {
|
||||
getMediaDataController().addRecentSticker(MediaDataController.TYPE_IMAGE, message, message.messageOwner.media.document, message.messageOwner.date, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class MessagesStorage extends BaseController {
|
|||
private CountDownLatch openSync = new CountDownLatch(1);
|
||||
|
||||
private static volatile MessagesStorage[] Instance = new MessagesStorage[UserConfig.MAX_ACCOUNT_COUNT];
|
||||
private final static int LAST_DB_VERSION = 60;
|
||||
private final static int LAST_DB_VERSION = 62;
|
||||
|
||||
public static MessagesStorage getInstance(int num) {
|
||||
MessagesStorage localInstance = Instance[num];
|
||||
|
@ -224,7 +224,7 @@ public class MessagesStorage extends BaseController {
|
|||
database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_mid_idx_messages ON messages(uid, date, mid);").stepThis().dispose();
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS mid_out_idx_messages ON messages(mid, out);").stepThis().dispose();
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS task_idx_messages ON messages(uid, out, read_state, ttl, date, send_state);").stepThis().dispose();
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages ON messages(mid, send_state, date) WHERE mid < 0 AND send_state = 1;").stepThis().dispose();
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages2 ON messages(mid, send_state, date);").stepThis().dispose();
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mention_idx_messages ON messages(uid, mention, read_state);").stepThis().dispose();
|
||||
|
||||
database.executeFast("CREATE TABLE download_queue(uid INTEGER, type INTEGER, date INTEGER, data BLOB, parent TEXT, PRIMARY KEY (uid, type));").stepThis().dispose();
|
||||
|
@ -280,10 +280,9 @@ public class MessagesStorage extends BaseController {
|
|||
database.executeFast("CREATE TABLE chats(uid INTEGER PRIMARY KEY, name TEXT, data BLOB)").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE enc_chats(uid INTEGER PRIMARY KEY, user INTEGER, name TEXT, data BLOB, g BLOB, authkey BLOB, ttl INTEGER, layer INTEGER, seq_in INTEGER, seq_out INTEGER, use_count INTEGER, exchange_id INTEGER, key_date INTEGER, fprint INTEGER, fauthkey BLOB, khash BLOB, in_seq_no INTEGER, admin_id INTEGER, mtproto_seq INTEGER)").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE channel_users_v2(did INTEGER, uid INTEGER, date INTEGER, data BLOB, PRIMARY KEY(did, uid))").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE channel_admins(did INTEGER, uid INTEGER, PRIMARY KEY(did, uid))").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE channel_admins_v2(did INTEGER, uid INTEGER, rank TEXT, PRIMARY KEY(did, uid))").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE contacts(uid INTEGER PRIMARY KEY, mutual INTEGER)").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE blocked_users(uid INTEGER PRIMARY KEY)").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE dialog_settings(did INTEGER PRIMARY KEY, flags INTEGER);").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE web_recent_v3(id TEXT, type INTEGER, image_url TEXT, thumb_url TEXT, local_url TEXT, width INTEGER, height INTEGER, size INTEGER, date INTEGER, document BLOB, PRIMARY KEY (id, type));").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE stickers_v2(id INTEGER PRIMARY KEY, data BLOB, date INTEGER, hash TEXT);").stepThis().dispose();
|
||||
|
@ -407,15 +406,11 @@ public class MessagesStorage extends BaseController {
|
|||
|
||||
database.executeFast("CREATE TABLE IF NOT EXISTS sent_files_v2(uid TEXT, type INTEGER, data BLOB, PRIMARY KEY (uid, type))").stepThis().dispose();
|
||||
|
||||
database.executeFast("CREATE TABLE IF NOT EXISTS blocked_users(uid INTEGER PRIMARY KEY)").stepThis().dispose();
|
||||
|
||||
database.executeFast("CREATE TABLE IF NOT EXISTS download_queue(uid INTEGER, type INTEGER, date INTEGER, data BLOB, PRIMARY KEY (uid, type));").stepThis().dispose();
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS type_date_idx_download_queue ON download_queue(type, date);").stepThis().dispose();
|
||||
|
||||
database.executeFast("CREATE TABLE IF NOT EXISTS dialog_settings(did INTEGER PRIMARY KEY, flags INTEGER);").stepThis().dispose();
|
||||
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages ON messages(mid, send_state, date) WHERE mid < 0 AND send_state = 1;").stepThis().dispose();
|
||||
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS unread_count_idx_dialogs ON dialogs(unread_count);").stepThis().dispose();
|
||||
|
||||
database.executeFast("UPDATE messages SET send_state = 2 WHERE mid < 0 AND send_state = 1").stepThis().dispose();
|
||||
|
@ -690,7 +685,6 @@ public class MessagesStorage extends BaseController {
|
|||
version = 43;
|
||||
}
|
||||
if (version == 43) {
|
||||
database.executeFast("CREATE TABLE IF NOT EXISTS channel_admins(did INTEGER, uid INTEGER, PRIMARY KEY(did, uid))").stepThis().dispose();
|
||||
database.executeFast("PRAGMA user_version = 44").stepThis().dispose();
|
||||
version = 44;
|
||||
}
|
||||
|
@ -785,6 +779,19 @@ public class MessagesStorage extends BaseController {
|
|||
version = 60;
|
||||
}
|
||||
if (version == 60) {
|
||||
database.executeFast("DROP TABLE IF EXISTS channel_admins;").stepThis().dispose();
|
||||
database.executeFast("DROP TABLE IF EXISTS blocked_users;").stepThis().dispose();
|
||||
database.executeFast("CREATE TABLE IF NOT EXISTS channel_admins_v2(did INTEGER, uid INTEGER, rank TEXT, PRIMARY KEY(did, uid))").stepThis().dispose();
|
||||
database.executeFast("PRAGMA user_version = 61").stepThis().dispose();
|
||||
version = 61;
|
||||
}
|
||||
if (version == 61) {
|
||||
database.executeFast("DROP INDEX IF EXISTS send_state_idx_messages;").stepThis().dispose();
|
||||
database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages2 ON messages(mid, send_state, date);").stepThis().dispose();
|
||||
database.executeFast("PRAGMA user_version = 62").stepThis().dispose();
|
||||
version = 62;
|
||||
}
|
||||
if (version == 62) {
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -1487,16 +1494,16 @@ public class MessagesStorage extends BaseController {
|
|||
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||
for (int a = 0; a < chats.size(); a++) {
|
||||
TLRPC.Chat chat = chats.get(a);
|
||||
if (chat != null && (chat.left || chat.migrated_to != null)) {
|
||||
if (chat != null && (ChatObject.isNotInChat(chat) || chat.migrated_to != null)) {
|
||||
long did = -chat.id;
|
||||
database.executeFast("UPDATE dialogs SET unread_count = 0 WHERE did = " + did).stepThis().dispose();
|
||||
database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = 3 WHERE uid = %d AND mid > 0 AND read_state IN(0,2) AND out = 0", did)).stepThis().dispose();
|
||||
chats.remove(a);
|
||||
a--;
|
||||
pushDialogs.remove((long) -chat.id);
|
||||
pushDialogs.remove(did);
|
||||
for (int b = 0; b < messages.size(); b++) {
|
||||
TLRPC.Message message = messages.get(b);
|
||||
if (message.dialog_id == -chat.id) {
|
||||
if (message.dialog_id == did) {
|
||||
messages.remove(b);
|
||||
b--;
|
||||
}
|
||||
|
@ -1715,68 +1722,6 @@ public class MessagesStorage extends BaseController {
|
|||
});
|
||||
}
|
||||
|
||||
public void getBlockedUsers() {
|
||||
storageQueue.postRunnable(() -> {
|
||||
try {
|
||||
SparseIntArray ids = new SparseIntArray();
|
||||
ArrayList<TLRPC.User> users = new ArrayList<>();
|
||||
SQLiteCursor cursor = database.queryFinalized("SELECT * FROM blocked_users WHERE 1");
|
||||
StringBuilder usersToLoad = new StringBuilder();
|
||||
while (cursor.next()) {
|
||||
int user_id = cursor.intValue(0);
|
||||
ids.put(user_id, 1);
|
||||
if (usersToLoad.length() != 0) {
|
||||
usersToLoad.append(",");
|
||||
}
|
||||
usersToLoad.append(user_id);
|
||||
}
|
||||
cursor.dispose();
|
||||
|
||||
if (usersToLoad.length() != 0) {
|
||||
getUsersInternal(usersToLoad.toString(), users);
|
||||
}
|
||||
|
||||
getMessagesController().processLoadedBlockedUsers(ids, users, true);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void deleteBlockedUser(final int id) {
|
||||
storageQueue.postRunnable(() -> {
|
||||
try {
|
||||
database.executeFast("DELETE FROM blocked_users WHERE uid = " + id).stepThis().dispose();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void putBlockedUsers(final SparseIntArray ids, final boolean replace) {
|
||||
if (ids == null || ids.size() == 0) {
|
||||
return;
|
||||
}
|
||||
storageQueue.postRunnable(() -> {
|
||||
try {
|
||||
if (replace) {
|
||||
database.executeFast("DELETE FROM blocked_users WHERE 1").stepThis().dispose();
|
||||
}
|
||||
database.beginTransaction();
|
||||
SQLitePreparedStatement state = database.executeFast("REPLACE INTO blocked_users VALUES(?)");
|
||||
for (int a = 0, size = ids.size(); a < size; a++) {
|
||||
state.requery();
|
||||
state.bindInteger(1, ids.keyAt(a));
|
||||
state.step();
|
||||
}
|
||||
state.dispose();
|
||||
database.commitTransaction();
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void deleteUserChannelHistory(final int channelId, final int uid) {
|
||||
storageQueue.postRunnable(() -> {
|
||||
try {
|
||||
|
@ -1793,27 +1738,7 @@ public class MessagesStorage extends BaseController {
|
|||
data.reuse();
|
||||
if (message != null && message.from_id == uid && message.id != 1) {
|
||||
mids.add(message.id);
|
||||
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
for (int a = 0, N = message.media.photo.sizes.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.photo.sizes.get(a);
|
||||
File file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
File file = FileLoader.getPathToAttach(message.media.document);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
for (int a = 0, N = message.media.document.thumbs.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.document.thumbs.get(a);
|
||||
file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
addFilesToDelete(message, filesToDelete, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1822,7 +1747,7 @@ public class MessagesStorage extends BaseController {
|
|||
}
|
||||
cursor.dispose();
|
||||
AndroidUtilities.runOnUIThread(() -> getMessagesController().markChannelDialogMessageAsDeleted(mids, channelId));
|
||||
markMessagesAsDeletedInternal(mids, channelId);
|
||||
markMessagesAsDeletedInternal(mids, channelId, false);
|
||||
updateDialogsWithDeletedMessagesInternal(mids, null, channelId);
|
||||
getFileLoader().deleteFiles(filesToDelete, 0);
|
||||
if (!mids.isEmpty()) {
|
||||
|
@ -1834,6 +1759,36 @@ public class MessagesStorage extends BaseController {
|
|||
});
|
||||
}
|
||||
|
||||
private boolean addFilesToDelete(TLRPC.Message message, ArrayList<File> filesToDelete, boolean forceCache) {
|
||||
if (message == null) {
|
||||
return false;
|
||||
}
|
||||
if (message.media instanceof TLRPC.TL_messageMediaPhoto && message.media.photo != null) {
|
||||
for (int a = 0, N = message.media.photo.sizes.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.photo.sizes.get(a);
|
||||
File file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaDocument && message.media.document != null) {
|
||||
File file = FileLoader.getPathToAttach(message.media.document, forceCache);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
for (int a = 0, N = message.media.document.thumbs.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.document.thumbs.get(a);
|
||||
file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void deleteDialog(final long did, final int messagesOnly) {
|
||||
storageQueue.postRunnable(() -> {
|
||||
try {
|
||||
|
@ -1858,29 +1813,7 @@ public class MessagesStorage extends BaseController {
|
|||
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||
data.reuse();
|
||||
if (message != null && message.media != null) {
|
||||
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
for (int a = 0, N = message.media.photo.sizes.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.photo.sizes.get(a);
|
||||
File file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
File file = FileLoader.getPathToAttach(message.media.document);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
for (int a = 0, N = message.media.document.thumbs.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.document.thumbs.get(a);
|
||||
file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addFilesToDelete(message, filesToDelete, false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -2219,29 +2152,7 @@ public class MessagesStorage extends BaseController {
|
|||
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||
data.reuse();
|
||||
if (message.media != null) {
|
||||
if (message.media.document != null) {
|
||||
File file = FileLoader.getPathToAttach(message.media.document, true);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
for (int a = 0, N = message.media.document.thumbs.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.document.thumbs.get(a);
|
||||
file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
message.media.document = new TLRPC.TL_documentEmpty();
|
||||
} else if (message.media.photo != null) {
|
||||
for (int a = 0, N = message.media.photo.sizes.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.photo.sizes.get(a);
|
||||
File file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
message.media.photo = new TLRPC.TL_photoEmpty();
|
||||
} else {
|
||||
if (!addFilesToDelete(message, filesToDelete, true)) {
|
||||
continue;
|
||||
}
|
||||
message.media.flags = message.media.flags &~ 1;
|
||||
|
@ -2747,10 +2658,10 @@ public class MessagesStorage extends BaseController {
|
|||
public void loadChannelAdmins(final int chatId) {
|
||||
storageQueue.postRunnable(() -> {
|
||||
try {
|
||||
SQLiteCursor cursor = database.queryFinalized("SELECT uid FROM channel_admins WHERE did = " + chatId);
|
||||
ArrayList<Integer> ids = new ArrayList<>();
|
||||
SQLiteCursor cursor = database.queryFinalized("SELECT uid, rank FROM channel_admins_v2 WHERE did = " + chatId);
|
||||
SparseArray<String> ids = new SparseArray<>();
|
||||
while (cursor.next()) {
|
||||
ids.add(cursor.intValue(0));
|
||||
ids.put(cursor.intValue(0), cursor.stringValue(1));
|
||||
}
|
||||
cursor.dispose();
|
||||
getMessagesController().processLoadedChannelAdmins(ids, chatId, true);
|
||||
|
@ -2760,17 +2671,18 @@ public class MessagesStorage extends BaseController {
|
|||
});
|
||||
}
|
||||
|
||||
public void putChannelAdmins(final int chatId, final ArrayList<Integer> ids) {
|
||||
public void putChannelAdmins(final int chatId, final SparseArray<String> ids) {
|
||||
storageQueue.postRunnable(() -> {
|
||||
try {
|
||||
database.executeFast("DELETE FROM channel_admins WHERE did = " + chatId).stepThis().dispose();
|
||||
database.executeFast("DELETE FROM channel_admins_v2 WHERE did = " + chatId).stepThis().dispose();
|
||||
database.beginTransaction();
|
||||
SQLitePreparedStatement state = database.executeFast("REPLACE INTO channel_admins VALUES(?, ?)");
|
||||
SQLitePreparedStatement state = database.executeFast("REPLACE INTO channel_admins_v2 VALUES(?, ?, ?)");
|
||||
int date = (int) (System.currentTimeMillis() / 1000);
|
||||
for (int a = 0; a < ids.size(); a++) {
|
||||
state.requery();
|
||||
state.bindInteger(1, chatId);
|
||||
state.bindInteger(2, ids.get(a));
|
||||
state.bindInteger(2, ids.keyAt(a));
|
||||
state.bindString(3, ids.valueAt(a));
|
||||
state.step();
|
||||
}
|
||||
state.dispose();
|
||||
|
@ -3192,7 +3104,8 @@ public class MessagesStorage extends BaseController {
|
|||
return result[0];
|
||||
}
|
||||
|
||||
public void loadChatInfo(final int chat_id, final CountDownLatch countDownLatch, final boolean force, final boolean byChannelUsers) {
|
||||
public TLRPC.ChatFull loadChatInfo(final int chat_id, final CountDownLatch countDownLatch, final boolean force, final boolean byChannelUsers) {
|
||||
TLRPC.ChatFull[] result = new TLRPC.ChatFull[1];
|
||||
storageQueue.postRunnable(() -> {
|
||||
MessageObject pinnedMessageObject = null;
|
||||
TLRPC.ChatFull info = null;
|
||||
|
@ -3269,21 +3182,27 @@ public class MessagesStorage extends BaseController {
|
|||
getUsersInternal(usersToLoad.toString(), loadedUsers);
|
||||
}
|
||||
}
|
||||
if (countDownLatch != null) {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
if (info != null && info.pinned_msg_id != 0) {
|
||||
pinnedMessageObject = getMediaDataController().loadPinnedMessage(-chat_id, info instanceof TLRPC.TL_channelFull ? chat_id : 0, info.pinned_msg_id, false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
} finally {
|
||||
result[0] = info;
|
||||
getMessagesController().processChatInfo(chat_id, info, loadedUsers, true, force, byChannelUsers, pinnedMessageObject);
|
||||
if (countDownLatch != null) {
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (countDownLatch != null) {
|
||||
try {
|
||||
countDownLatch.await();
|
||||
} catch (Throwable ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
|
||||
public void processPendingRead(final long dialog_id, final long maxPositiveId, final long maxNegativeId, final boolean isChannel) {
|
||||
|
@ -3683,6 +3602,7 @@ public class MessagesStorage extends BaseController {
|
|||
ArrayList<Integer> chatsToLoad = new ArrayList<>();
|
||||
ArrayList<Integer> broadcastIds = new ArrayList<>();
|
||||
ArrayList<Integer> encryptedChatIds = new ArrayList<>();
|
||||
|
||||
SQLiteCursor cursor = database.queryFinalized("SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.uid, s.seq_in, s.seq_out, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid LEFT JOIN messages_seq as s ON m.mid = s.mid WHERE (m.mid < 0 AND m.send_state = 1) OR (m.mid > 0 AND m.send_state = 3) ORDER BY m.mid DESC LIMIT " + count);
|
||||
while (cursor.next()) {
|
||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
||||
|
@ -6291,7 +6211,7 @@ public class MessagesStorage extends BaseController {
|
|||
if (!mids.isEmpty()) {
|
||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0));
|
||||
updateDialogsWithReadMessagesInternal(mids, null, null, null);
|
||||
markMessagesAsDeletedInternal(mids, 0);
|
||||
markMessagesAsDeletedInternal(mids, 0, true);
|
||||
updateDialogsWithDeletedMessagesInternal(mids, null, 0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -6308,7 +6228,7 @@ public class MessagesStorage extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
private ArrayList<Long> markMessagesAsDeletedInternal(final ArrayList<Integer> messages, int channelId) {
|
||||
private ArrayList<Long> markMessagesAsDeletedInternal(final ArrayList<Integer> messages, int channelId, boolean deleteFiles) {
|
||||
try {
|
||||
String ids;
|
||||
final ArrayList<Integer> temp = new ArrayList<>(messages);
|
||||
|
@ -6354,7 +6274,7 @@ public class MessagesStorage extends BaseController {
|
|||
unread_count[0]++;
|
||||
}
|
||||
}
|
||||
if ((int) did != 0) {
|
||||
if ((int) did != 0 && !deleteFiles) {
|
||||
continue;
|
||||
}
|
||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
||||
|
@ -6362,29 +6282,7 @@ public class MessagesStorage extends BaseController {
|
|||
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||
data.reuse();
|
||||
if (message != null) {
|
||||
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
for (int a = 0, N = message.media.photo.sizes.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.photo.sizes.get(a);
|
||||
File file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
File file = FileLoader.getPathToAttach(message.media.document);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
for (int a = 0, N = message.media.document.thumbs.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.document.thumbs.get(a);
|
||||
file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addFilesToDelete(message, filesToDelete, false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -6650,19 +6548,19 @@ public class MessagesStorage extends BaseController {
|
|||
}
|
||||
}
|
||||
|
||||
public ArrayList<Long> markMessagesAsDeleted(final ArrayList<Integer> messages, boolean useQueue, final int channelId) {
|
||||
public ArrayList<Long> markMessagesAsDeleted(final ArrayList<Integer> messages, boolean useQueue, final int channelId, boolean deleteFiles) {
|
||||
if (messages.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (useQueue) {
|
||||
storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(messages, channelId));
|
||||
storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(messages, channelId, deleteFiles));
|
||||
} else {
|
||||
return markMessagesAsDeletedInternal(messages, channelId);
|
||||
return markMessagesAsDeletedInternal(messages, channelId, deleteFiles);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ArrayList<Long> markMessagesAsDeletedInternal(final int channelId, final int mid) {
|
||||
private ArrayList<Long> markMessagesAsDeletedInternal(final int channelId, final int mid, boolean deleteFiles) {
|
||||
try {
|
||||
String ids;
|
||||
ArrayList<Long> dialogsIds = new ArrayList<>();
|
||||
|
@ -6695,7 +6593,7 @@ public class MessagesStorage extends BaseController {
|
|||
unread_count[0]++;
|
||||
}
|
||||
}
|
||||
if ((int) did != 0) {
|
||||
if ((int) did != 0 && !deleteFiles) {
|
||||
continue;
|
||||
}
|
||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
||||
|
@ -6703,29 +6601,7 @@ public class MessagesStorage extends BaseController {
|
|||
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||
data.reuse();
|
||||
if (message != null) {
|
||||
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||
for (int a = 0, N = message.media.photo.sizes.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.photo.sizes.get(a);
|
||||
File file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||
File file = FileLoader.getPathToAttach(message.media.document);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
for (int a = 0, N = message.media.document.thumbs.size(); a < N; a++) {
|
||||
TLRPC.PhotoSize photoSize = message.media.document.thumbs.get(a);
|
||||
file = FileLoader.getPathToAttach(photoSize);
|
||||
if (file != null && file.toString().length() > 0) {
|
||||
filesToDelete.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
addFilesToDelete(message, filesToDelete, false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -6768,11 +6644,11 @@ public class MessagesStorage extends BaseController {
|
|||
return null;
|
||||
}
|
||||
|
||||
public ArrayList<Long> markMessagesAsDeleted(final int channelId, final int mid, boolean useQueue) {
|
||||
public ArrayList<Long> markMessagesAsDeleted(final int channelId, final int mid, boolean useQueue, boolean deleteFiles) {
|
||||
if (useQueue) {
|
||||
storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(channelId, mid));
|
||||
storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(channelId, mid, deleteFiles));
|
||||
} else {
|
||||
return markMessagesAsDeletedInternal(channelId, mid);
|
||||
return markMessagesAsDeletedInternal(channelId, mid, deleteFiles);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -7129,6 +7005,7 @@ public class MessagesStorage extends BaseController {
|
|||
int minChannelMessageId = Integer.MAX_VALUE;
|
||||
int maxChannelMessageId = 0;
|
||||
int channelId = 0;
|
||||
ArrayList<File> filesToDelete = new ArrayList<>();
|
||||
for (int a = 0; a < count; a++) {
|
||||
TLRPC.Message message = messages.messages.get(a);
|
||||
|
||||
|
@ -7154,6 +7031,15 @@ public class MessagesStorage extends BaseController {
|
|||
message.attachPath = oldMessage.attachPath;
|
||||
message.ttl = cursor.intValue(2);
|
||||
}
|
||||
boolean sameMedia = false;
|
||||
if (oldMessage.media instanceof TLRPC.TL_messageMediaPhoto && message.media instanceof TLRPC.TL_messageMediaPhoto && oldMessage.media.photo != null && message.media.photo != null) {
|
||||
sameMedia = oldMessage.media.photo.id == message.media.photo.id;
|
||||
} else if (oldMessage.media instanceof TLRPC.TL_messageMediaDocument && message.media instanceof TLRPC.TL_messageMediaDocument && oldMessage.media.document != null && message.media.document != null) {
|
||||
sameMedia = oldMessage.media.document.id == message.media.document.id;
|
||||
}
|
||||
if (!sameMedia) {
|
||||
addFilesToDelete(oldMessage, filesToDelete, false);
|
||||
}
|
||||
}
|
||||
boolean oldMention = cursor.intValue(3) != 0;
|
||||
int readState = cursor.intValue(4);
|
||||
|
@ -7294,6 +7180,7 @@ public class MessagesStorage extends BaseController {
|
|||
if (botKeyboard != null) {
|
||||
getMediaDataController().putBotKeyboard(dialog_id, botKeyboard);
|
||||
}
|
||||
getFileLoader().deleteFiles(filesToDelete, 0);
|
||||
|
||||
putUsersInternal(messages.users);
|
||||
putChatsInternal(messages.chats);
|
||||
|
|
|
@ -93,6 +93,7 @@ public class NotificationCenter {
|
|||
public static final int newPeopleNearbyAvailable = totalEvents++;
|
||||
public static final int stopAllHeavyOperations = totalEvents++;
|
||||
public static final int startAllHeavyOperations = totalEvents++;
|
||||
public static final int sendingMessagesChanged = totalEvents++;
|
||||
|
||||
public static final int httpFileDidLoad = totalEvents++;
|
||||
public static final int httpFileDidFailedLoad = totalEvents++;
|
||||
|
|
|
@ -16,121 +16,130 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class NotificationImageProvider extends ContentProvider implements NotificationCenter.NotificationCenterDelegate{
|
||||
public class NotificationImageProvider extends ContentProvider implements NotificationCenter.NotificationCenterDelegate {
|
||||
|
||||
public static final String AUTHORITY=BuildConfig.APPLICATION_ID+".notification_image_provider";
|
||||
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".notification_image_provider";
|
||||
|
||||
private static final UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);
|
||||
static{
|
||||
private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
|
||||
static {
|
||||
matcher.addURI(AUTHORITY, "msg_media_raw/#/*", 1); // content://org.telegram..../msg_media_raw/account/filename.ext
|
||||
}
|
||||
|
||||
private HashSet<String> waitingForFiles=new HashSet<>();
|
||||
private final Object sync=new Object();
|
||||
private HashMap<String, Long> fileStartTimes=new HashMap<>();
|
||||
private HashSet<String> waitingForFiles = new HashSet<>();
|
||||
private final Object sync = new Object();
|
||||
private HashMap<String, Long> fileStartTimes = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public boolean onCreate(){
|
||||
for(int i=0;i<UserConfig.getActivatedAccountsCount();i++){
|
||||
public boolean onCreate() {
|
||||
for (int i = 0; i < UserConfig.getActivatedAccountsCount(); i++) {
|
||||
NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.fileDidLoad);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown(){
|
||||
for(int i=0;i<UserConfig.getActivatedAccountsCount();i++){
|
||||
public void shutdown() {
|
||||
for (int i = 0; i < UserConfig.getActivatedAccountsCount(); i++) {
|
||||
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.fileDidLoad);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder){
|
||||
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getType(@NonNull Uri uri){
|
||||
public String getType(@NonNull Uri uri) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values){
|
||||
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs){
|
||||
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs){
|
||||
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter){
|
||||
if(mimeTypeFilter.startsWith("*/") || mimeTypeFilter.startsWith("image/"))
|
||||
public String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter) {
|
||||
if (mimeTypeFilter.startsWith("*/") || mimeTypeFilter.startsWith("image/")) {
|
||||
return new String[]{"image/jpeg", "image/png", "image/webp"};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException{
|
||||
if(!"r".equals(mode))
|
||||
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
||||
if (!"r".equals(mode)) {
|
||||
throw new SecurityException("Can only open files for read");
|
||||
switch(matcher.match(uri)){
|
||||
case 1:
|
||||
{
|
||||
List<String> path=uri.getPathSegments();
|
||||
int account=Integer.parseInt(path.get(1));
|
||||
String name=path.get(2);
|
||||
String finalPath=uri.getQueryParameter("final_path");
|
||||
String fallbackPath=uri.getQueryParameter("fallback");
|
||||
File finalFile=new File(finalPath);
|
||||
if(finalFile.exists()){
|
||||
FileLog.d(finalFile+" already exists");
|
||||
return ParcelFileDescriptor.open(finalFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}else{
|
||||
Long _startTime=fileStartTimes.get(name);
|
||||
long startTime=_startTime!=null ? _startTime : System.currentTimeMillis();
|
||||
if(_startTime==null)
|
||||
fileStartTimes.put(name, startTime);
|
||||
while(!finalFile.exists()){
|
||||
if(System.currentTimeMillis()-startTime>=3000){
|
||||
if(BuildVars.LOGS_ENABLED)
|
||||
FileLog.w("Waiting for "+name+" to download timed out");
|
||||
if(TextUtils.isEmpty(fallbackPath))
|
||||
throw new FileNotFoundException("Download timed out");
|
||||
return ParcelFileDescriptor.open(new File(fallbackPath), ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
if (matcher.match(uri) == 1) {
|
||||
List<String> path = uri.getPathSegments();
|
||||
int account = Integer.parseInt(path.get(1));
|
||||
String name = path.get(2);
|
||||
String finalPath = uri.getQueryParameter("final_path");
|
||||
String fallbackPath = uri.getQueryParameter("fallback");
|
||||
File finalFile = new File(finalPath);
|
||||
if (AndroidUtilities.isInternalUri(Uri.fromFile(finalFile))) {
|
||||
throw new SecurityException("trying to read internal file");
|
||||
}
|
||||
if (finalFile.exists()) {
|
||||
return ParcelFileDescriptor.open(finalFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
} else {
|
||||
Long _startTime = fileStartTimes.get(name);
|
||||
long startTime = _startTime != null ? _startTime : System.currentTimeMillis();
|
||||
if (_startTime == null) {
|
||||
fileStartTimes.put(name, startTime);
|
||||
}
|
||||
while (!finalFile.exists()) {
|
||||
if (System.currentTimeMillis() - startTime >= 3000) {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.w("Waiting for " + name + " to download timed out");
|
||||
}
|
||||
synchronized(sync){
|
||||
waitingForFiles.add(name);
|
||||
try{
|
||||
sync.wait(1000);
|
||||
}catch(InterruptedException ignore){
|
||||
}
|
||||
if (TextUtils.isEmpty(fallbackPath)) {
|
||||
throw new FileNotFoundException("Download timed out");
|
||||
}
|
||||
File file = new File(fallbackPath);
|
||||
if (AndroidUtilities.isInternalUri(Uri.fromFile(file))) {
|
||||
throw new SecurityException("trying to read internal file");
|
||||
}
|
||||
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
synchronized (sync) {
|
||||
waitingForFiles.add(name);
|
||||
try {
|
||||
sync.wait(1000);
|
||||
} catch (InterruptedException ignore) {
|
||||
}
|
||||
}
|
||||
return ParcelFileDescriptor.open(finalFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
return ParcelFileDescriptor.open(finalFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
}
|
||||
throw new FileNotFoundException("Invalid URI");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void didReceivedNotification(int id, int account, Object... args){
|
||||
if(id==NotificationCenter.fileDidLoad){
|
||||
synchronized(sync){
|
||||
String name=(String)args[0];
|
||||
if(waitingForFiles.remove(name)){
|
||||
public void didReceivedNotification(int id, int account, Object... args) {
|
||||
if (id == NotificationCenter.fileDidLoad) {
|
||||
synchronized (sync) {
|
||||
String name = (String) args[0];
|
||||
if (waitingForFiles.remove(name)) {
|
||||
fileStartTimes.remove(name);
|
||||
sync.notifyAll();
|
||||
}
|
||||
|
|
|
@ -1045,6 +1045,9 @@ public class SecretChatHelper extends BaseController {
|
|||
newMessage.media.ttl_seconds = newMessage.ttl;
|
||||
newMessage.media.flags |= 4;
|
||||
}
|
||||
if (newMessage.message != null) {
|
||||
newMessage.message = newMessage.message.replace('\u202E', ' ');
|
||||
}
|
||||
return newMessage;
|
||||
} else if (object instanceof TLRPC.TL_decryptedMessageService) {
|
||||
final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService) object;
|
||||
|
|
|
@ -31,6 +31,7 @@ import android.text.TextUtils;
|
|||
import android.util.Base64;
|
||||
import android.util.LongSparseArray;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -68,6 +69,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
private HashMap<String, ArrayList<DelayedMessage>> delayedMessages = new HashMap<>();
|
||||
private SparseArray<MessageObject> unsentMessages = new SparseArray<>();
|
||||
private SparseArray<TLRPC.Message> sendingMessages = new SparseArray<>();
|
||||
private SparseArray<TLRPC.Message> editingMessages = new SparseArray<>();
|
||||
private SparseArray<TLRPC.Message> uploadMessages = new SparseArray<>();
|
||||
private LongSparseArray<Integer> sendingMessagesIdDialogs = new LongSparseArray<>();
|
||||
private LongSparseArray<Integer> uploadingMessagesIdDialogs = new LongSparseArray<>();
|
||||
private HashMap<String, MessageObject> waitingForLocation = new HashMap<>();
|
||||
private HashMap<String, Boolean> waitingForCallback = new HashMap<>();
|
||||
private HashMap<String, byte[]> waitingForVote = new HashMap<>();
|
||||
|
@ -361,6 +366,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, obj.getId());
|
||||
processSentMessage(obj.getId());
|
||||
removeFromUploadingMessages(obj.getId());
|
||||
}
|
||||
delayedMessages.remove( "group_" + groupId);
|
||||
} else {
|
||||
|
@ -368,6 +374,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, obj.getId());
|
||||
processSentMessage(obj.getId());
|
||||
removeFromUploadingMessages(obj.getId());
|
||||
}
|
||||
sendDelayedRequests();
|
||||
}
|
||||
|
@ -407,6 +414,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
delayedMessages.clear();
|
||||
unsentMessages.clear();
|
||||
sendingMessages.clear();
|
||||
editingMessages.clear();
|
||||
sendingMessagesIdDialogs.clear();
|
||||
uploadMessages.clear();
|
||||
uploadingMessagesIdDialogs.clear();
|
||||
waitingForLocation.clear();
|
||||
waitingForCallback.clear();
|
||||
waitingForVote.clear();
|
||||
|
@ -807,6 +818,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
|
||||
public void cancelSendingMessage(ArrayList<MessageObject> objects) {
|
||||
ArrayList<String> keysToRemove = new ArrayList<>();
|
||||
ArrayList<DelayedMessage> checkReadyToSendGroups = new ArrayList<>();
|
||||
ArrayList<Integer> messageIds = new ArrayList<>();
|
||||
boolean enc = false;
|
||||
int channelId = 0;
|
||||
|
@ -830,6 +842,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
messageObject = message.messageObjects.get(b);
|
||||
if (messageObject.getId() == object.getId()) {
|
||||
index = b;
|
||||
removeFromUploadingMessages(object.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -862,13 +875,15 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
||||
messagesRes.messages.add(prevMessage.messageOwner);
|
||||
getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false);
|
||||
|
||||
}
|
||||
sendReadyToSendGroup(message, false, true);
|
||||
if (!checkReadyToSendGroups.contains(message)) {
|
||||
checkReadyToSendGroups.add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (message.obj.getId() == object.getId()) {
|
||||
removeFromUploadingMessages(object.getId());
|
||||
messages.remove(a);
|
||||
message.sendDelayedRequests();
|
||||
MediaController.getInstance().cancelVideoConvert(message.obj);
|
||||
|
@ -893,6 +908,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
stopVideoService(key);
|
||||
delayedMessages.remove(key);
|
||||
}
|
||||
for (int a = 0, N = checkReadyToSendGroups.size(); a < N; a++) {
|
||||
sendReadyToSendGroup(checkReadyToSendGroups.get(a), false, true);
|
||||
}
|
||||
if (objects.size() == 1 && objects.get(0).isEditing() && objects.get(0).previousMedia != null) {
|
||||
revertEditingMessageObject(objects.get(0));
|
||||
} else {
|
||||
|
@ -1381,9 +1399,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
final TLRPC.TL_messages_forwardMessages req = new TLRPC.TL_messages_forwardMessages();
|
||||
req.to_peer = inputPeer;
|
||||
req.grouped = lastGroupedId != 0;
|
||||
if (req.to_peer instanceof TLRPC.TL_inputPeerChannel) {
|
||||
req.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
}
|
||||
req.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
if (msgObj.messageOwner.to_id instanceof TLRPC.TL_peerChannel) {
|
||||
TLRPC.Chat channel = getMessagesController().getChat(msgObj.messageOwner.to_id.channel_id);
|
||||
req.from_peer = new TLRPC.TL_inputPeerChannel();
|
||||
|
@ -2149,7 +2165,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.TL_messages_sendMedia request = new TLRPC.TL_messages_sendMedia();
|
||||
request.peer = peer;
|
||||
if (request.peer instanceof TLRPC.TL_inputPeerChannel) {
|
||||
request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer.channel_id, false);
|
||||
request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + -peer.channel_id, false);
|
||||
} else if (request.peer instanceof TLRPC.TL_inputPeerChat) {
|
||||
request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + -peer.chat_id, false);
|
||||
} else {
|
||||
request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer.user_id, false);
|
||||
}
|
||||
request.random_id = random_id != 0 ? random_id : getNextRandomId();
|
||||
request.message = "";
|
||||
|
@ -2260,7 +2280,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
if (retryMessageObject.isForwarded()) {
|
||||
type = 4;
|
||||
} else {
|
||||
if (retryMessageObject.type == 0) {
|
||||
if (retryMessageObject.type == 0 || retryMessageObject.isAnimatedEmoji()) {
|
||||
if (retryMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
|
||||
//game = retryMessageObject.messageOwner.media.game;
|
||||
} else {
|
||||
|
@ -2284,7 +2304,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
user.restriction_reason = newMsg.media.vcard;
|
||||
user.id = newMsg.media.user_id;
|
||||
type = 6;
|
||||
} else if (retryMessageObject.type == 8 || retryMessageObject.type == 9 || retryMessageObject.type == 13 || retryMessageObject.type == 14) {
|
||||
} else if (retryMessageObject.type == 8 || retryMessageObject.type == 9 || retryMessageObject.type == MessageObject.TYPE_STICKER || retryMessageObject.type == 14 || retryMessageObject.type == MessageObject.TYPE_ANIMATED_STICKER) {
|
||||
document = (TLRPC.TL_document) newMsg.media.document;
|
||||
type = 7;
|
||||
} else if (retryMessageObject.type == 2) {
|
||||
|
@ -2624,8 +2644,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
|
||||
newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING;
|
||||
newMsgObj = new MessageObject(currentAccount, newMsg, true);
|
||||
newMsgObj.replyMessageObject = reply_to_msg;
|
||||
newMsgObj = new MessageObject(currentAccount, newMsg, reply_to_msg, true);
|
||||
if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == 2) && !TextUtils.isEmpty(newMsg.attachPath)) {
|
||||
newMsgObj.attachPathExists = true;
|
||||
}
|
||||
|
@ -2698,9 +2717,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
TLRPC.TL_messages_sendMessage reqSend = new TLRPC.TL_messages_sendMessage();
|
||||
reqSend.message = message;
|
||||
reqSend.clear_draft = retryMessageObject == null;
|
||||
if (newMsg.to_id instanceof TLRPC.TL_peerChannel) {
|
||||
reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
}
|
||||
reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
reqSend.peer = sendToPeer;
|
||||
reqSend.random_id = newMsg.random_id;
|
||||
if (newMsg.reply_to_msg_id != 0) {
|
||||
|
@ -2989,9 +3006,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
} else {
|
||||
request = new TLRPC.TL_messages_sendMultiMedia();
|
||||
request.peer = sendToPeer;
|
||||
if (newMsg.to_id instanceof TLRPC.TL_peerChannel) {
|
||||
request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
}
|
||||
request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
if (newMsg.reply_to_msg_id != 0) {
|
||||
request.flags |= 1;
|
||||
request.reply_to_msg_id = newMsg.reply_to_msg_id;
|
||||
|
@ -3019,9 +3034,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
} else {
|
||||
TLRPC.TL_messages_sendMedia request = new TLRPC.TL_messages_sendMedia();
|
||||
request.peer = sendToPeer;
|
||||
if (newMsg.to_id instanceof TLRPC.TL_peerChannel) {
|
||||
request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
}
|
||||
request.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
if (newMsg.reply_to_msg_id != 0) {
|
||||
request.flags |= 1;
|
||||
request.reply_to_msg_id = newMsg.reply_to_msg_id;
|
||||
|
@ -3353,9 +3366,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
} else {
|
||||
reqSend.from_peer = new TLRPC.TL_inputPeerEmpty();
|
||||
}
|
||||
if (retryMessageObject.messageOwner.to_id instanceof TLRPC.TL_peerChannel) {
|
||||
reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
}
|
||||
reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
reqSend.random_id.add(newMsg.random_id);
|
||||
if (retryMessageObject.getId() >= 0) {
|
||||
reqSend.id.add(retryMessageObject.getId());
|
||||
|
@ -3376,9 +3387,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
reqSend.flags |= 1;
|
||||
reqSend.reply_to_msg_id = newMsg.reply_to_msg_id;
|
||||
}
|
||||
if (newMsg.to_id instanceof TLRPC.TL_peerChannel) {
|
||||
reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
}
|
||||
reqSend.silent = MessagesController.getNotificationsSettings(currentAccount).getBoolean("silent_" + peer, false);
|
||||
reqSend.query_id = Utilities.parseLong(params.get("query_id"));
|
||||
reqSend.id = params.get("id");
|
||||
if (retryMessageObject == null) {
|
||||
|
@ -3440,6 +3449,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
String location = FileLoader.getPathToAttach(message.photoSize).toString();
|
||||
putToDelayedMessages(location, message);
|
||||
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
||||
putToUploadingMessages(message.obj);
|
||||
} else {
|
||||
String location = FileLoader.getPathToAttach(message.photoSize).toString();
|
||||
if (message.sendEncryptedRequest != null && message.photoSize.location.dc_id != 0) {
|
||||
|
@ -3456,6 +3466,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
putToDelayedMessages(location, message);
|
||||
getFileLoader().uploadFile(location, true, true, ConnectionsManager.FileTypePhoto);
|
||||
putToUploadingMessages(message.obj);
|
||||
}
|
||||
}
|
||||
} else if (message.type == 1) {
|
||||
|
@ -3467,6 +3478,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
putToDelayedMessages(location, message);
|
||||
MediaController.getInstance().scheduleVideoConvert(message.obj);
|
||||
putToUploadingMessages(message.obj);
|
||||
} else {
|
||||
if (message.videoEditedInfo != null) {
|
||||
if (message.videoEditedInfo.file != null) {
|
||||
|
@ -3511,10 +3523,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
} else {
|
||||
getFileLoader().uploadFile(location, false, false, ConnectionsManager.FileTypeVideo);
|
||||
}
|
||||
putToUploadingMessages(message.obj);
|
||||
} else {
|
||||
String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg";
|
||||
putToDelayedMessages(location, message);
|
||||
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
||||
putToUploadingMessages(message.obj);
|
||||
}
|
||||
} else {
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
|
@ -3536,6 +3550,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
} else {
|
||||
getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeVideo);
|
||||
}
|
||||
putToUploadingMessages(message.obj);
|
||||
}
|
||||
}
|
||||
} else if (message.type == 2) {
|
||||
|
@ -3556,10 +3571,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
String location = message.obj.messageOwner.attachPath;
|
||||
putToDelayedMessages(location, message);
|
||||
getFileLoader().uploadFile(location, message.sendRequest == null, false, ConnectionsManager.FileTypeFile);
|
||||
putToUploadingMessages(message.obj);
|
||||
} else if (media.thumb == null && message.photoSize != null) {
|
||||
String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg";
|
||||
putToDelayedMessages(location, message);
|
||||
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
||||
putToUploadingMessages(message.obj);
|
||||
}
|
||||
} else {
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
|
@ -3574,12 +3591,14 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
putToDelayedMessages(location, message);
|
||||
getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeFile);
|
||||
putToUploadingMessages(message.obj);
|
||||
}
|
||||
}
|
||||
} else if (message.type == 3) {
|
||||
String location = message.obj.messageOwner.attachPath;
|
||||
putToDelayedMessages(location, message);
|
||||
getFileLoader().uploadFile(location, message.sendRequest == null, true, ConnectionsManager.FileTypeAudio);
|
||||
putToUploadingMessages(message.obj);
|
||||
} else if (message.type == 4) {
|
||||
boolean add = index < 0;
|
||||
if (message.performMediaUpload) {
|
||||
|
@ -3601,6 +3620,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
message.extraHashMap.put(location + "_t", message.photoSize);
|
||||
}
|
||||
MediaController.getInstance().scheduleVideoConvert(messageObject);
|
||||
message.obj = messageObject;
|
||||
putToUploadingMessages(messageObject);
|
||||
} else {
|
||||
TLRPC.Document document = messageObject.getDocument();
|
||||
String documentLocation = messageObject.messageOwner.attachPath;
|
||||
|
@ -3623,6 +3644,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
} else {
|
||||
getFileLoader().uploadFile(documentLocation, false, false, ConnectionsManager.FileTypeVideo);
|
||||
}
|
||||
putToUploadingMessages(messageObject);
|
||||
} else {
|
||||
String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg";
|
||||
putToDelayedMessages(location, message);
|
||||
|
@ -3630,6 +3652,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
message.extraHashMap.put(messageObject, location);
|
||||
message.extraHashMap.put(location, media);
|
||||
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
||||
putToUploadingMessages(messageObject);
|
||||
}
|
||||
} else {
|
||||
TLRPC.TL_messages_sendEncryptedMultiMedia request = (TLRPC.TL_messages_sendEncryptedMultiMedia) message.sendEncryptedRequest;
|
||||
|
@ -3645,6 +3668,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
} else {
|
||||
getFileLoader().uploadFile(documentLocation, true, false, ConnectionsManager.FileTypeVideo);
|
||||
}
|
||||
putToUploadingMessages(messageObject);
|
||||
}
|
||||
}
|
||||
message.videoEditedInfo = null;
|
||||
|
@ -3670,12 +3694,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
message.extraHashMap.put(location, inputMedia);
|
||||
message.extraHashMap.put(messageObject, location);
|
||||
getFileLoader().uploadFile(location, message.sendEncryptedRequest != null, true, ConnectionsManager.FileTypePhoto);
|
||||
putToUploadingMessages(messageObject);
|
||||
message.photoSize = null;
|
||||
}
|
||||
}
|
||||
message.performMediaUpload = false;
|
||||
} else if (!message.messageObjects.isEmpty()) {
|
||||
putToSendingMessages(message.messageObjects.get(message.messageObjects.size() - 1).messageOwner);
|
||||
putToSendingMessages(message.messageObjects.get(message.messageObjects.size() - 1).messageOwner, message.finalGroupMessage != 0);
|
||||
}
|
||||
sendReadyToSendGroup(message, add, true);
|
||||
}
|
||||
|
@ -3805,19 +3830,121 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
|||
}
|
||||
|
||||
protected void putToSendingMessages(TLRPC.Message message) {
|
||||
sendingMessages.put(message.id, message);
|
||||
if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) {
|
||||
AndroidUtilities.runOnUIThread(() -> putToSendingMessages(message, true));
|
||||
} else {
|
||||
putToSendingMessages(message, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected void putToSendingMessages(TLRPC.Message message, boolean notify) {
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
if (message.id > 0) {
|
||||
editingMessages.put(message.id, message);
|
||||
} else {
|
||||
boolean contains = sendingMessages.indexOfKey(message.id) >= 0;
|
||||
removeFromUploadingMessages(message.id);
|
||||
sendingMessages.put(message.id, message);
|
||||
if (!contains) {
|
||||
long did = MessageObject.getDialogId(message);
|
||||
sendingMessagesIdDialogs.put(did, sendingMessagesIdDialogs.get(did, 0) + 1);
|
||||
if (notify) {
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.sendingMessagesChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected TLRPC.Message removeFromSendingMessages(int mid) {
|
||||
TLRPC.Message message = sendingMessages.get(mid);
|
||||
if (message != null) {
|
||||
sendingMessages.remove(mid);
|
||||
TLRPC.Message message;
|
||||
if (mid > 0) {
|
||||
message = editingMessages.get(mid);
|
||||
if (message != null) {
|
||||
editingMessages.remove(mid);
|
||||
}
|
||||
} else {
|
||||
message = sendingMessages.get(mid);
|
||||
if (message != null) {
|
||||
sendingMessages.remove(mid);
|
||||
long did = MessageObject.getDialogId(message);
|
||||
Integer currentCount = sendingMessagesIdDialogs.get(did);
|
||||
if (currentCount != null) {
|
||||
int count = currentCount - 1;
|
||||
if (count <= 0) {
|
||||
sendingMessagesIdDialogs.remove(did);
|
||||
} else {
|
||||
sendingMessagesIdDialogs.put(did, count);
|
||||
}
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.sendingMessagesChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
public int getSendingMessageId(long did) {
|
||||
for (int a = 0; a < sendingMessages.size(); a++) {
|
||||
TLRPC.Message message = sendingMessages.valueAt(a);
|
||||
if (message.dialog_id == did) {
|
||||
return message.id;
|
||||
}
|
||||
}
|
||||
for (int a = 0; a < uploadMessages.size(); a++) {
|
||||
TLRPC.Message message = uploadMessages.valueAt(a);
|
||||
if (message.dialog_id == did) {
|
||||
return message.id;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected void putToUploadingMessages(MessageObject obj) {
|
||||
if (obj == null || obj.getId() > 0) {
|
||||
return;
|
||||
}
|
||||
TLRPC.Message message = obj.messageOwner;
|
||||
boolean contains = uploadMessages.indexOfKey(message.id) >= 0;
|
||||
uploadMessages.put(message.id, message);
|
||||
if (!contains) {
|
||||
long did = MessageObject.getDialogId(message);
|
||||
uploadingMessagesIdDialogs.put(did, uploadingMessagesIdDialogs.get(did, 0) + 1);
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.sendingMessagesChanged);
|
||||
}
|
||||
}
|
||||
|
||||
protected void removeFromUploadingMessages(int mid) {
|
||||
if (mid > 0) {
|
||||
return;
|
||||
}
|
||||
TLRPC.Message message = uploadMessages.get(mid);
|
||||
if (message != null) {
|
||||
uploadMessages.remove(mid);
|
||||
long did = MessageObject.getDialogId(message);
|
||||
Integer currentCount = uploadingMessagesIdDialogs.get(did);
|
||||
if (currentCount != null) {
|
||||
int count = currentCount - 1;
|
||||
if (count <= 0) {
|
||||
uploadingMessagesIdDialogs.remove(did);
|
||||
} else {
|
||||
uploadingMessagesIdDialogs.put(did, count);
|
||||
}
|
||||
getNotificationCenter().postNotificationName(NotificationCenter.sendingMessagesChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSendingMessage(int mid) {
|
||||
return sendingMessages.indexOfKey(mid) >= 0;
|
||||
return sendingMessages.indexOfKey(mid) >= 0 || editingMessages.indexOfKey(mid) >= 0;
|
||||
}
|
||||
|
||||
public boolean isSendingMessageIdDialog(long did) {
|
||||
return sendingMessagesIdDialogs.get(did, 0) > 0;
|
||||
}
|
||||
|
||||
public boolean isUploadingMessageIdDialog(long did) {
|
||||
return uploadingMessagesIdDialogs.get(did, 0) > 0;
|
||||
}
|
||||
|
||||
protected void performSendMessageRequestMulti(final TLRPC.TL_messages_sendMultiMedia req, final ArrayList<MessageObject> msgObjs, final ArrayList<String> originalPaths, final ArrayList<Object> parentObjects, DelayedMessage delayedMessage) {
|
||||
|
|
|
@ -17,6 +17,7 @@ import android.os.Environment;
|
|||
import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.telegram.tgnet.ConnectionsManager;
|
||||
|
@ -53,6 +54,9 @@ public class SharedConfig {
|
|||
public static boolean useFingerprint = true;
|
||||
public static String lastUpdateVersion;
|
||||
public static int suggestStickers;
|
||||
public static boolean loopStickers;
|
||||
public static int keepMedia = 2;
|
||||
public static int lastKeepMediaCheckTime;
|
||||
private static int lastLocalId = -210000;
|
||||
|
||||
private static String passportConfigJson = "";
|
||||
|
@ -72,7 +76,6 @@ public class SharedConfig {
|
|||
public static boolean directShare = true;
|
||||
public static boolean inappCamera = true;
|
||||
public static boolean roundCamera16to9 = true;
|
||||
public static boolean groupPhotosEnabled = true;
|
||||
public static boolean noSoundHintShowed = false;
|
||||
public static boolean streamMedia = true;
|
||||
public static boolean streamAllVideo = false;
|
||||
|
@ -231,7 +234,6 @@ public class SharedConfig {
|
|||
inappCamera = preferences.getBoolean("inappCamera", true);
|
||||
hasCameraCache = preferences.contains("cameraCache");
|
||||
roundCamera16to9 = true;//preferences.getBoolean("roundCamera16to9", false);
|
||||
groupPhotosEnabled = preferences.getBoolean("groupPhotosEnabled", true);
|
||||
repeatMode = preferences.getInt("repeatMode", 0);
|
||||
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
|
||||
allowBigEmoji = preferences.getBoolean("allowBigEmoji", true);
|
||||
|
@ -248,6 +250,9 @@ public class SharedConfig {
|
|||
archiveHidden = preferences.getBoolean("archiveHidden", false);
|
||||
distanceSystemType = preferences.getInt("distanceSystemType", 0);
|
||||
devicePerformanceClass = preferences.getInt("devicePerformanceClass", -1);
|
||||
loopStickers = preferences.getBoolean("loopStickers", true);
|
||||
keepMedia = preferences.getInt("keep_media", 2);
|
||||
lastKeepMediaCheckTime = preferences.getInt("lastKeepMediaCheckTime", 0);
|
||||
|
||||
preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
|
||||
showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true);
|
||||
|
@ -374,6 +379,64 @@ public class SharedConfig {
|
|||
editor.commit();
|
||||
}
|
||||
|
||||
public static void setKeepMedia(int value) {
|
||||
keepMedia = value;
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("keep_media", keepMedia);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void checkKeepMedia() {
|
||||
int time = (int) (System.currentTimeMillis() / 1000);
|
||||
if (keepMedia == 2 || Math.abs(time - lastKeepMediaCheckTime) < 24 * 60 * 60) {
|
||||
return;
|
||||
}
|
||||
lastKeepMediaCheckTime = time;
|
||||
Utilities.globalQueue.postRunnable(() -> {
|
||||
int days;
|
||||
if (keepMedia == 0) {
|
||||
days = 7;
|
||||
} else if (keepMedia == 1) {
|
||||
days = 30;
|
||||
} else {
|
||||
days = 3;
|
||||
}
|
||||
long currentTime = time - 60 * 60 * 24 * days;
|
||||
final SparseArray<File> paths = ImageLoader.getInstance().createMediaPaths();
|
||||
for (int a = 0; a < paths.size(); a++) {
|
||||
if (paths.keyAt(a) == FileLoader.MEDIA_DIR_CACHE) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Utilities.clearDir(paths.valueAt(a).getAbsolutePath(), 0, currentTime);
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt("lastKeepMediaCheckTime", lastKeepMediaCheckTime);
|
||||
editor.commit();
|
||||
});
|
||||
}
|
||||
|
||||
public static void toggleLoopStickers() {
|
||||
loopStickers = !loopStickers;
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putBoolean("loopStickers", loopStickers);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void toggleBigEmoji() {
|
||||
allowBigEmoji = !allowBigEmoji;
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putBoolean("allowBigEmoji", allowBigEmoji);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void toggleShuffleMusic(int type) {
|
||||
if (type == 2) {
|
||||
shuffleMusic = !shuffleMusic;
|
||||
|
@ -545,14 +608,6 @@ public class SharedConfig {
|
|||
editor.commit();
|
||||
}
|
||||
|
||||
public static void toggleGroupPhotosEnabled() {
|
||||
groupPhotosEnabled = !groupPhotosEnabled;
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putBoolean("groupPhotosEnabled", groupPhotosEnabled);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public static void setDistanceSystemType(int type) {
|
||||
distanceSystemType = type;
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package org.telegram.messenger;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Telephony;
|
||||
import android.telephony.SmsMessage;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.google.android.gms.auth.api.phone.SmsRetriever;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@TargetApi(26)
|
||||
public class SmsReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String message = "";
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
String hash = preferences.getString("sms_hash", null);
|
||||
if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
|
||||
if (!AndroidUtilities.isWaitingForSms()) {
|
||||
return;
|
||||
}
|
||||
Bundle bundle = intent.getExtras();
|
||||
message = (String) bundle.get(SmsRetriever.EXTRA_SMS_MESSAGE);
|
||||
} else {
|
||||
if (TextUtils.isEmpty(hash)) {
|
||||
return;
|
||||
}
|
||||
SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent);
|
||||
if (msgs == null || msgs.length <= 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < msgs.length; i++) {
|
||||
message += msgs[i].getMessageBody();
|
||||
}
|
||||
if (!message.contains(hash)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (TextUtils.isEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
Pattern pattern = Pattern.compile("[0-9\\-]+");
|
||||
final Matcher matcher = pattern.matcher(message);
|
||||
if (matcher.find()) {
|
||||
String code = matcher.group(0).replace("-", "");
|
||||
if (code.length() >= 3) {
|
||||
if (preferences != null && hash != null) {
|
||||
preferences.edit().putString("sms_hash_code", hash + "|" + code).commit();
|
||||
}
|
||||
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didReceiveSmsCode, code));
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ public class UserConfig extends BaseController {
|
|||
public int lastBroadcastId = -1;
|
||||
public int contactsSavedCount;
|
||||
public int clientUserId;
|
||||
public boolean blockedUsersLoaded;
|
||||
public int lastContactsSyncTime;
|
||||
public int lastHintsSyncTime;
|
||||
public boolean draftsLoaded;
|
||||
|
@ -118,7 +117,6 @@ public class UserConfig extends BaseController {
|
|||
editor.putInt("lastSendMessageId", lastSendMessageId);
|
||||
editor.putInt("contactsSavedCount", contactsSavedCount);
|
||||
editor.putInt("lastBroadcastId", lastBroadcastId);
|
||||
editor.putBoolean("blockedUsersLoaded", blockedUsersLoaded);
|
||||
editor.putInt("lastContactsSyncTime", lastContactsSyncTime);
|
||||
editor.putInt("lastHintsSyncTime", lastHintsSyncTime);
|
||||
editor.putBoolean("draftsLoaded", draftsLoaded);
|
||||
|
@ -255,7 +253,6 @@ public class UserConfig extends BaseController {
|
|||
lastSendMessageId = preferences.getInt("lastSendMessageId", -210000);
|
||||
contactsSavedCount = preferences.getInt("contactsSavedCount", 0);
|
||||
lastBroadcastId = preferences.getInt("lastBroadcastId", -1);
|
||||
blockedUsersLoaded = preferences.getBoolean("blockedUsersLoaded", false);
|
||||
lastContactsSyncTime = preferences.getInt("lastContactsSyncTime", (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60);
|
||||
lastHintsSyncTime = preferences.getInt("lastHintsSyncTime", (int) (System.currentTimeMillis() / 1000) - 25 * 60 * 60);
|
||||
draftsLoaded = preferences.getBoolean("draftsLoaded", false);
|
||||
|
@ -399,7 +396,6 @@ public class UserConfig extends BaseController {
|
|||
contactsSavedCount = 0;
|
||||
lastSendMessageId = -210000;
|
||||
lastBroadcastId = -1;
|
||||
blockedUsersLoaded = false;
|
||||
notificationsSettingsLoaded = false;
|
||||
notificationsSignUpSettingsLoaded = false;
|
||||
migrateOffsetId = -1;
|
||||
|
|
|
@ -91,11 +91,11 @@ public class Utilities {
|
|||
aesCbcEncryptionByteArray(buffer, key, iv.clone(), offset, length, n, encrypt);
|
||||
}
|
||||
|
||||
public static Integer parseInt(String value) {
|
||||
public static Integer parseInt(CharSequence value) {
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
Integer val = 0;
|
||||
int val = 0;
|
||||
try {
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
if (matcher.find()) {
|
||||
|
@ -112,7 +112,7 @@ public class Utilities {
|
|||
if (value == null) {
|
||||
return 0L;
|
||||
}
|
||||
Long val = 0L;
|
||||
long val = 0L;
|
||||
try {
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
if (matcher.find()) {
|
||||
|
|
|
@ -15,6 +15,8 @@ import java.util.Locale;
|
|||
public class VideoEditedInfo {
|
||||
public long startTime;
|
||||
public long endTime;
|
||||
public float start;
|
||||
public float end;
|
||||
public int rotationValue;
|
||||
public int originalWidth;
|
||||
public int originalHeight;
|
||||
|
|
|
@ -41,7 +41,6 @@ import org.telegram.messenger.support.customtabsclient.shared.ServiceConnectionC
|
|||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.AlertDialog;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.LaunchActivity;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
@ -287,7 +286,7 @@ public class Browser {
|
|||
|
||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getSession());
|
||||
builder.addMenuItem(LocaleController.getString("CopyLink", R.string.CopyLink), copy);
|
||||
builder.setToolbarColor(Theme.getColor(Theme.key_actionBarDefault));
|
||||
builder.setToolbarColor(0xffffffff);
|
||||
builder.setShowTitle(true);
|
||||
builder.setActionButton(BitmapFactory.decodeResource(context.getResources(), R.drawable.abc_ic_menu_share_mtrl_alpha), LocaleController.getString("ShareFile", R.string.ShareFile), PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, share, 0), false);
|
||||
CustomTabsIntent intent = builder.build();
|
||||
|
|
|
@ -242,6 +242,10 @@ public class CameraController implements MediaRecorder.OnInfoListener {
|
|||
return cameraInitied && cameraInfos != null && !cameraInfos.isEmpty();
|
||||
}
|
||||
|
||||
public void runOnThreadPool(Runnable runnable) {
|
||||
threadPool.execute(runnable);
|
||||
}
|
||||
|
||||
public void close(final CameraSession session, final CountDownLatch countDownLatch, final Runnable beforeDestroyRunnable) {
|
||||
session.destroy();
|
||||
threadPool.execute(() -> {
|
||||
|
|
|
@ -38,23 +38,22 @@ public class CameraSession {
|
|||
private final Size previewSize;
|
||||
private final int pictureFormat;
|
||||
private boolean initied;
|
||||
private int maxZoom;
|
||||
private boolean meteringAreaSupported;
|
||||
private int currentOrientation;
|
||||
private int diffOrientation;
|
||||
private int jpegOrientation;
|
||||
private boolean sameTakePictureOrientation;
|
||||
private boolean flipFront = true;
|
||||
private float currentZoom;
|
||||
|
||||
public static final int ORIENTATION_HYSTERESIS = 5;
|
||||
|
||||
private Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
|
||||
@Override
|
||||
public void onAutoFocus(boolean success, Camera camera) {
|
||||
if (success) {
|
||||
private Camera.AutoFocusCallback autoFocusCallback = (success, camera) -> {
|
||||
if (success) {
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -335,6 +334,10 @@ public class CameraSession {
|
|||
params.setPreviewSize(previewSize.getWidth(), previewSize.getHeight());
|
||||
params.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight());
|
||||
params.setPictureFormat(pictureFormat);
|
||||
params.setJpegQuality(100);
|
||||
params.setJpegThumbnailQuality(100);
|
||||
maxZoom = params.getMaxZoom();
|
||||
params.setZoom((int) (currentZoom * maxZoom));
|
||||
|
||||
String desiredMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
|
||||
if (params.getSupportedFocusModes().contains(desiredMode)) {
|
||||
|
@ -380,7 +383,6 @@ public class CameraSession {
|
|||
try {
|
||||
Camera camera = cameraInfo.camera;
|
||||
if (camera != null) {
|
||||
|
||||
camera.cancelAutoFocus();
|
||||
Camera.Parameters parameters = null;
|
||||
try {
|
||||
|
@ -414,6 +416,15 @@ public class CameraSession {
|
|||
}
|
||||
}
|
||||
|
||||
protected int getMaxZoom() {
|
||||
return maxZoom;
|
||||
}
|
||||
|
||||
protected void setZoom(float value) {
|
||||
currentZoom = value;
|
||||
configurePhotoCamera();
|
||||
}
|
||||
|
||||
protected void configureRecorder(int quality, MediaRecorder recorder) {
|
||||
Camera.CameraInfo info = new Camera.CameraInfo();
|
||||
Camera.getCameraInfo(cameraInfo.cameraId, info);
|
||||
|
@ -509,9 +520,10 @@ public class CameraSession {
|
|||
cameraInfo.camera.setPreviewCallback(callback);
|
||||
}
|
||||
|
||||
public void setOneShotPreviewCallback(Camera.PreviewCallback callback){
|
||||
if(cameraInfo!=null && cameraInfo.camera!=null)
|
||||
cameraInfo.camera.setOneShotPreviewCallback(callback);
|
||||
public void setOneShotPreviewCallback(Camera.PreviewCallback callback) {
|
||||
if (cameraInfo != null && cameraInfo.camera != null) {
|
||||
cameraInfo.camera.setOneShotPreviewCallback(callback);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
|
|
|
@ -40,7 +40,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
private boolean initied;
|
||||
private CameraViewDelegate delegate;
|
||||
private int clipTop;
|
||||
private int clipLeft;
|
||||
private int clipBottom;
|
||||
private boolean isFrontface;
|
||||
private Matrix txform = new Matrix();
|
||||
private Matrix matrix = new Matrix();
|
||||
|
@ -90,6 +90,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
return isFrontface;
|
||||
}
|
||||
|
||||
public TextureView getTextureView() {
|
||||
return textureView;
|
||||
}
|
||||
|
||||
public boolean hasFrontFaceCamera() {
|
||||
ArrayList<CameraInfo> cameraInfos = CameraController.getInstance().getCameras();
|
||||
for (int a = 0; a < cameraInfos.size(); a++) {
|
||||
|
@ -168,20 +172,14 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
if (previewSize != null && surfaceTexture != null) {
|
||||
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
||||
cameraSession = new CameraSession(info, previewSize, pictureSize, ImageFormat.JPEG);
|
||||
CameraController.getInstance().open(cameraSession, surfaceTexture, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (cameraSession != null) {
|
||||
cameraSession.setInitied();
|
||||
}
|
||||
checkPreviewMatrix();
|
||||
CameraController.getInstance().open(cameraSession, surfaceTexture, () -> {
|
||||
if (cameraSession != null) {
|
||||
cameraSession.setInitied();
|
||||
}
|
||||
}, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (delegate != null) {
|
||||
delegate.onCameraCreated(cameraSession.cameraInfo.camera);
|
||||
}
|
||||
checkPreviewMatrix();
|
||||
}, () -> {
|
||||
if (delegate != null) {
|
||||
delegate.onCameraCreated(cameraSession.cameraInfo.camera);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -223,8 +221,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
clipTop = value;
|
||||
}
|
||||
|
||||
public void setClipLeft(int value) {
|
||||
clipLeft = value;
|
||||
public void setClipBottom(int value) {
|
||||
clipBottom = value;
|
||||
}
|
||||
|
||||
private void checkPreviewMatrix() {
|
||||
|
@ -244,9 +242,9 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
|
||||
float scale;
|
||||
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
|
||||
scale = Math.max((float) (viewHeight + clipTop) / previewWidth, (float) (viewWidth + clipLeft) / previewHeight);
|
||||
scale = Math.max((float) (viewHeight + clipTop + clipBottom) / previewWidth, (float) (viewWidth) / previewHeight);
|
||||
} else {
|
||||
scale = Math.max((float) (viewHeight + clipTop) / previewHeight, (float) (viewWidth + clipLeft) / previewWidth);
|
||||
scale = Math.max((float) (viewHeight + clipTop + clipBottom) / previewHeight, (float) (viewWidth) / previewWidth);
|
||||
}
|
||||
|
||||
float previewWidthScaled = previewWidth * scale;
|
||||
|
@ -268,8 +266,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
if (mirror) {
|
||||
txform.postScale(-1, 1, viewCenterX, viewCenterY);
|
||||
}
|
||||
if (clipTop != 0 || clipLeft != 0) {
|
||||
txform.postTranslate(-clipLeft / 2, -clipTop / 2);
|
||||
if (clipTop != 0) {
|
||||
txform.postTranslate(0, -clipTop / 2);
|
||||
} else if (clipBottom != 0) {
|
||||
txform.postTranslate(0, clipBottom / 2);
|
||||
}
|
||||
|
||||
textureView.setTransform(txform);
|
||||
|
@ -320,6 +320,12 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
invalidate();
|
||||
}
|
||||
|
||||
public void setZoom(float value) {
|
||||
if (cameraSession != null) {
|
||||
cameraSession.setZoom(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDelegate(CameraViewDelegate cameraViewDelegate) {
|
||||
delegate = cameraViewDelegate;
|
||||
}
|
||||
|
@ -339,6 +345,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
|||
}
|
||||
}
|
||||
|
||||
public Matrix getMatrix() {
|
||||
return txform;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
||||
boolean result = super.drawChild(canvas, child, drawingTime);
|
||||
|
|
|
@ -34,6 +34,8 @@ import androidx.annotation.Nullable;
|
|||
import androidx.annotation.RequiresApi;
|
||||
import android.util.Log;
|
||||
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
@ -162,8 +164,13 @@ public abstract class JobIntentService extends Service {
|
|||
mServiceProcessing = true;
|
||||
// Keep the device awake, but only for at most 10 minutes at a time
|
||||
// (Similar to JobScheduler.)
|
||||
mRunWakeLock.acquire(2 * 60 * 1000L);
|
||||
mLaunchWakeLock.release();
|
||||
try {
|
||||
mRunWakeLock.acquire(2 * 60 * 1000L);
|
||||
mLaunchWakeLock.release();
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
mServiceProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +351,11 @@ public abstract class JobIntentService extends Service {
|
|||
if (DEBUG) Log.d(TAG, "Processing next work: " + work);
|
||||
onHandleWork(work.getIntent());
|
||||
if (DEBUG) Log.d(TAG, "Completing work: " + work);
|
||||
work.complete();
|
||||
try {
|
||||
work.complete();
|
||||
} catch (Throwable ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) Log.d(TAG, "Done processing work!");
|
||||
|
|
|
@ -502,14 +502,7 @@ public class ConnectionsManager extends BaseController {
|
|||
return;
|
||||
}
|
||||
lastDnsRequestTime = System.currentTimeMillis();
|
||||
if (second == 2) {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("start azure dns task");
|
||||
}
|
||||
AzureLoadTask task = new AzureLoadTask(currentAccount);
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||
currentTask = task;
|
||||
} else if (second == 1) {
|
||||
if (second == 1) {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("start dns txt task");
|
||||
}
|
||||
|
@ -631,7 +624,7 @@ public class ConnectionsManager extends BaseController {
|
|||
public static native void native_seSystemLangCode(int currentAccount, String langCode);
|
||||
public static native void native_setJava(boolean useJavaByteBuffers);
|
||||
public static native void native_setPushConnectionEnabled(int currentAccount, boolean value);
|
||||
public static native void native_applyDnsConfig(int currentAccount, long address, String phone);
|
||||
public static native void native_applyDnsConfig(int currentAccount, long address, String phone, int date);
|
||||
public static native long native_checkProxy(int currentAccount, String address, int port, String username, String password, String secret, RequestTimeDelegate requestTimeDelegate);
|
||||
public static native void native_onHostNameResolved(String host, long address, String ip);
|
||||
|
||||
|
@ -832,6 +825,7 @@ public class ConnectionsManager extends BaseController {
|
|||
private static class DnsTxtLoadTask extends AsyncTask<Void, Void, NativeByteBuffer> {
|
||||
|
||||
private int currentAccount;
|
||||
private int responseDate;
|
||||
|
||||
public DnsTxtLoadTask(int instance) {
|
||||
super();
|
||||
|
@ -851,7 +845,7 @@ public class ConnectionsManager extends BaseController {
|
|||
} else {
|
||||
googleDomain = "google.com";
|
||||
}
|
||||
String domain = native_isTestBackend(currentAccount) != 0 ? "tapv2.stel.com" : AccountInstance.getInstance(currentAccount).getMessagesController().dcDomainName;
|
||||
String domain = native_isTestBackend(currentAccount) != 0 ? "tapv3.stel.com" : AccountInstance.getInstance(currentAccount).getMessagesController().dcDomainName;
|
||||
int len = Utilities.random.nextInt(116) + 13;
|
||||
final String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
|
@ -867,6 +861,7 @@ public class ConnectionsManager extends BaseController {
|
|||
httpConnection.setReadTimeout(5000);
|
||||
httpConnection.connect();
|
||||
httpConnectionStream = httpConnection.getInputStream();
|
||||
responseDate = (int) (httpConnection.getDate() / 1000);
|
||||
|
||||
outbuf = new ByteArrayOutputStream();
|
||||
|
||||
|
@ -941,17 +936,13 @@ public class ConnectionsManager extends BaseController {
|
|||
protected void onPostExecute(final NativeByteBuffer result) {
|
||||
Utilities.stageQueue.postRunnable(() -> {
|
||||
if (result != null) {
|
||||
currentTask = null;
|
||||
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone());
|
||||
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone(), responseDate);
|
||||
} else {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("failed to get dns txt result");
|
||||
FileLog.d("start azure task");
|
||||
}
|
||||
AzureLoadTask task = new AzureLoadTask(currentAccount);
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, null, null, null);
|
||||
currentTask = task;
|
||||
}
|
||||
currentTask = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -974,7 +965,7 @@ public class ConnectionsManager extends BaseController {
|
|||
firebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
|
||||
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder().setDeveloperModeEnabled(BuildConfig.DEBUG).build();
|
||||
firebaseRemoteConfig.setConfigSettings(configSettings);
|
||||
String currentValue = firebaseRemoteConfig.getString("ipconfigv2");
|
||||
String currentValue = firebaseRemoteConfig.getString("ipconfigv3");
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("current firebase value = " + currentValue);
|
||||
}
|
||||
|
@ -993,7 +984,8 @@ public class ConnectionsManager extends BaseController {
|
|||
try {
|
||||
NativeByteBuffer buffer = new NativeByteBuffer(bytes.length);
|
||||
buffer.writeBytes(bytes);
|
||||
native_applyDnsConfig(currentAccount, buffer.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone());
|
||||
int date = (int) (firebaseRemoteConfig.getInfo().getFetchTimeMillis() / 1000);
|
||||
native_applyDnsConfig(currentAccount, buffer.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone(), date);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
|
@ -1028,87 +1020,4 @@ public class ConnectionsManager extends BaseController {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
private static class AzureLoadTask extends AsyncTask<Void, Void, NativeByteBuffer> {
|
||||
|
||||
private int currentAccount;
|
||||
|
||||
public AzureLoadTask(int instance) {
|
||||
super();
|
||||
currentAccount = instance;
|
||||
}
|
||||
|
||||
protected NativeByteBuffer doInBackground(Void... voids) {
|
||||
ByteArrayOutputStream outbuf = null;
|
||||
InputStream httpConnectionStream = null;
|
||||
try {
|
||||
URL downloadUrl;
|
||||
if (native_isTestBackend(currentAccount) != 0) {
|
||||
downloadUrl = new URL("https://software-download.microsoft.com/testv2/config.txt");
|
||||
} else {
|
||||
downloadUrl = new URL("https://software-download.microsoft.com/prodv2/config.txt");
|
||||
}
|
||||
URLConnection httpConnection = downloadUrl.openConnection();
|
||||
httpConnection.addRequestProperty("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_0 like Mac OS X) AppleWebKit/602.1.38 (KHTML, like Gecko) Version/10.0 Mobile/14A5297c Safari/602.1");
|
||||
httpConnection.addRequestProperty("Host", "tcdnb.azureedge.net");
|
||||
httpConnection.setConnectTimeout(5000);
|
||||
httpConnection.setReadTimeout(5000);
|
||||
httpConnection.connect();
|
||||
httpConnectionStream = httpConnection.getInputStream();
|
||||
|
||||
outbuf = new ByteArrayOutputStream();
|
||||
|
||||
byte[] data = new byte[1024 * 32];
|
||||
while (true) {
|
||||
if (isCancelled()) {
|
||||
break;
|
||||
}
|
||||
int read = httpConnectionStream.read(data);
|
||||
if (read > 0) {
|
||||
outbuf.write(data, 0, read);
|
||||
} else if (read == -1) {
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
byte[] bytes = Base64.decode(outbuf.toByteArray(), Base64.DEFAULT);
|
||||
NativeByteBuffer buffer = new NativeByteBuffer(bytes.length);
|
||||
buffer.writeBytes(bytes);
|
||||
return buffer;
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
} finally {
|
||||
try {
|
||||
if (httpConnectionStream != null) {
|
||||
httpConnectionStream.close();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
try {
|
||||
if (outbuf != null) {
|
||||
outbuf.close();
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final NativeByteBuffer result) {
|
||||
Utilities.stageQueue.postRunnable(() -> {
|
||||
if (result != null) {
|
||||
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone());
|
||||
} else {
|
||||
if (BuildVars.LOGS_ENABLED) {
|
||||
FileLog.d("failed to get azure result");
|
||||
}
|
||||
}
|
||||
currentTask = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -652,6 +652,10 @@ public class ActionBar extends FrameLayout {
|
|||
menu.setSearchFieldText(text);
|
||||
}
|
||||
|
||||
public void onSearchPressed() {
|
||||
menu.onSearchPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
super.setEnabled(enabled);
|
||||
|
|
|
@ -1112,7 +1112,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
}
|
||||
|
||||
previousFragment.onTransitionAnimationStart(true, true);
|
||||
currentFragment.onTransitionAnimationStart(false, false);
|
||||
currentFragment.onTransitionAnimationStart(false, true);
|
||||
previousFragment.onResume();
|
||||
if (themeAnimatorSet != null) {
|
||||
presentingFragmentDescriptions = previousFragment.getThemeDescriptions();
|
||||
|
@ -1140,7 +1140,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
containerViewBack.setTranslationX(0);
|
||||
}
|
||||
closeLastFragmentInternalRemoveOld(currentFragment);
|
||||
currentFragment.onTransitionAnimationEnd(false, false);
|
||||
currentFragment.onTransitionAnimationEnd(false, true);
|
||||
previousFragmentFinal.onTransitionAnimationEnd(true, true);
|
||||
previousFragmentFinal.onBecomeFullyVisible();
|
||||
};
|
||||
|
@ -1168,7 +1168,7 @@ public class ActionBarLayout extends FrameLayout {
|
|||
currentAnimation = animation;
|
||||
}
|
||||
} else {
|
||||
currentFragment.onTransitionAnimationEnd(false, false);
|
||||
currentFragment.onTransitionAnimationEnd(false, true);
|
||||
previousFragment.onTransitionAnimationEnd(true, true);
|
||||
previousFragment.onBecomeFullyVisible();
|
||||
}
|
||||
|
|
|
@ -219,6 +219,20 @@ public class ActionBarMenu extends LinearLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void onSearchPressed() {
|
||||
int count = getChildCount();
|
||||
for (int a = 0; a < count; a++) {
|
||||
View view = getChildAt(a);
|
||||
if (view instanceof ActionBarMenuItem) {
|
||||
ActionBarMenuItem item = (ActionBarMenuItem) view;
|
||||
if (item.isSearchField()) {
|
||||
item.onSearchPressed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void openSearchField(boolean toggle, String text, boolean animated) {
|
||||
int count = getChildCount();
|
||||
for (int a = 0; a < count; a++) {
|
||||
|
|
|
@ -99,7 +99,8 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
private boolean animationEnabled = true;
|
||||
private boolean ignoreOnTextChange;
|
||||
private CloseProgressDrawable2 progressDrawable;
|
||||
private int additionalOffset;
|
||||
private int additionalYOffset;
|
||||
private int additionalXOffset;
|
||||
private boolean longClickEnabled = true;
|
||||
private boolean animateClear = true;
|
||||
|
||||
|
@ -261,6 +262,13 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
});
|
||||
}
|
||||
|
||||
public void removeAllSubItems() {
|
||||
if (popupLayout == null) {
|
||||
return;
|
||||
}
|
||||
popupLayout.removeInnerViews();
|
||||
}
|
||||
|
||||
public void addSubItem(View view, int width, int height) {
|
||||
createPopupLayout();
|
||||
popupLayout.addView(view, new LinearLayout.LayoutParams(width, height));
|
||||
|
@ -301,6 +309,8 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
textView.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0);
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setMinWidth(AndroidUtilities.dp(196));
|
||||
textView.setSingleLine(true);
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setTag(id);
|
||||
textView.setText(text);
|
||||
popupLayout.addView(textView);
|
||||
|
@ -534,6 +544,12 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void onSearchPressed() {
|
||||
if (listener != null) {
|
||||
listener.onSearchPressed(searchField);
|
||||
}
|
||||
}
|
||||
|
||||
public EditTextBoldCursor getSearchField() {
|
||||
return searchField;
|
||||
}
|
||||
|
@ -827,8 +843,12 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
}
|
||||
}
|
||||
|
||||
public void setAdditionalOffset(int value) {
|
||||
additionalOffset = value;
|
||||
public void setAdditionalYOffset(int value) {
|
||||
additionalYOffset = value;
|
||||
}
|
||||
|
||||
public void setAdditionalXOffset(int value) {
|
||||
additionalXOffset = value;
|
||||
}
|
||||
|
||||
private void updateOrShowPopup(boolean show, boolean update) {
|
||||
|
@ -838,7 +858,7 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
offsetY = -parentMenu.parentActionBar.getMeasuredHeight() + parentMenu.getTop() + parentMenu.getPaddingTop();
|
||||
} else {
|
||||
float scaleY = getScaleY();
|
||||
offsetY = -(int) (getMeasuredHeight() * scaleY - (subMenuOpenSide != 2 ? getTranslationY() : 0) / scaleY) + additionalOffset;
|
||||
offsetY = -(int) (getMeasuredHeight() * scaleY - (subMenuOpenSide != 2 ? getTranslationY() : 0) / scaleY) + additionalYOffset;
|
||||
}
|
||||
offsetY += yOffset;
|
||||
|
||||
|
@ -868,25 +888,25 @@ public class ActionBarMenuItem extends FrameLayout {
|
|||
if (getParent() != null) {
|
||||
View parent = (View) getParent();
|
||||
if (show) {
|
||||
popupWindow.showAsDropDown(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY);
|
||||
popupWindow.showAsDropDown(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY);
|
||||
}
|
||||
if (update) {
|
||||
popupWindow.update(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY, -1, -1);
|
||||
popupWindow.update(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY, -1, -1);
|
||||
}
|
||||
}
|
||||
} else if (subMenuOpenSide == 1) {
|
||||
if (show) {
|
||||
popupWindow.showAsDropDown(this, -AndroidUtilities.dp(8), offsetY);
|
||||
popupWindow.showAsDropDown(this, -AndroidUtilities.dp(8) + additionalXOffset, offsetY);
|
||||
}
|
||||
if (update) {
|
||||
popupWindow.update(this, -AndroidUtilities.dp(8), offsetY, -1, -1);
|
||||
popupWindow.update(this, -AndroidUtilities.dp(8) + additionalXOffset, offsetY, -1, -1);
|
||||
}
|
||||
} else {
|
||||
if (show) {
|
||||
popupWindow.showAsDropDown(this, getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY);
|
||||
popupWindow.showAsDropDown(this, getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY);
|
||||
}
|
||||
if (update) {
|
||||
popupWindow.update(this, getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY, -1, -1);
|
||||
popupWindow.update(this, getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,10 @@
|
|||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
//Thanks to https://github.com/JakeWharton/ActionBarSherlock/
|
||||
|
||||
package org.telegram.ui.ActionBar;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
|
@ -24,6 +23,7 @@ import android.view.KeyEvent;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
@ -37,6 +37,7 @@ import org.telegram.ui.Components.LayoutHelper;
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ActionBarPopupWindow extends PopupWindow {
|
||||
|
@ -79,6 +80,7 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
private int lastStartedChild = 0;
|
||||
private boolean showedFromBotton;
|
||||
private boolean animationEnabled = allowAnimation;
|
||||
private ArrayList<AnimatorSet> itemAnimators;
|
||||
private HashMap<View, Integer> positions = new HashMap<>();
|
||||
|
||||
private ScrollView scrollView;
|
||||
|
@ -141,11 +143,6 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
public void setBackScaleY(float value) {
|
||||
backScaleY = value;
|
||||
if (animationEnabled) {
|
||||
int count = getItemsCount();
|
||||
int visibleCount = 0;
|
||||
for (int a = 0; a < count; a++) {
|
||||
visibleCount += getItemAt(a).getVisibility() == VISIBLE ? 1 : 0;
|
||||
}
|
||||
int height = getMeasuredHeight() - AndroidUtilities.dp(16);
|
||||
if (showedFromBotton) {
|
||||
for (int a = lastStartedChild; a >= 0; a--) {
|
||||
|
@ -161,6 +158,7 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
startChildAnimation(child);
|
||||
}
|
||||
} else {
|
||||
int count = getItemsCount();
|
||||
for (int a = lastStartedChild; a < count; a++) {
|
||||
View child = getItemAt(a);
|
||||
if (child.getVisibility() != VISIBLE) {
|
||||
|
@ -186,11 +184,21 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
if (animationEnabled) {
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(
|
||||
ObjectAnimator.ofFloat(child, "alpha", 0.0f, 1.0f),
|
||||
ObjectAnimator.ofFloat(child, "translationY", AndroidUtilities.dp(showedFromBotton ? 6 : -6), 0));
|
||||
ObjectAnimator.ofFloat(child, View.ALPHA, 0.0f, 1.0f),
|
||||
ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, AndroidUtilities.dp(showedFromBotton ? 6 : -6), 0));
|
||||
animatorSet.setDuration(180);
|
||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
itemAnimators.remove(animatorSet);
|
||||
}
|
||||
});
|
||||
animatorSet.setInterpolator(decelerateInterpolator);
|
||||
animatorSet.start();
|
||||
if (itemAnimators == null) {
|
||||
itemAnimators = new ArrayList<>();
|
||||
}
|
||||
itemAnimators.add(animatorSet);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,6 +245,10 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
}
|
||||
}
|
||||
|
||||
public Drawable getBackgroundDrawable() {
|
||||
return backgroundDrawable;
|
||||
}
|
||||
|
||||
public int getItemsCount() {
|
||||
return linearLayout.getChildCount();
|
||||
}
|
||||
|
@ -337,6 +349,16 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
}
|
||||
}
|
||||
|
||||
public void dimBehind() {
|
||||
View container = getContentView().getRootView();
|
||||
Context context = getContentView().getContext();
|
||||
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
WindowManager.LayoutParams p = (WindowManager.LayoutParams) container.getLayoutParams();
|
||||
p.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
|
||||
p.dimAmount = 0.2f;
|
||||
wm.updateViewLayout(container, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showAsDropDown(View anchor, int xoff, int yoff) {
|
||||
try {
|
||||
|
@ -362,11 +384,11 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
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);
|
||||
child.setAlpha(0.0f);
|
||||
visibleCount++;
|
||||
}
|
||||
if (content.showedFromBotton) {
|
||||
|
@ -388,6 +410,12 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
windowAnimatorSet = null;
|
||||
ActionBarPopupWindowLayout content = (ActionBarPopupWindowLayout) getContentView();
|
||||
int count = content.getItemsCount();
|
||||
for (int a = 0; a < count; a++) {
|
||||
View child = content.getItemAt(a);
|
||||
child.setAlpha(1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -434,10 +462,16 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
windowAnimatorSet.cancel();
|
||||
}
|
||||
ActionBarPopupWindowLayout content = (ActionBarPopupWindowLayout) getContentView();
|
||||
if (content.itemAnimators != null && content.itemAnimators.isEmpty()) {
|
||||
for (int a = 0, N = content.itemAnimators.size(); a < N; a++) {
|
||||
content.itemAnimators.get(a).cancel();
|
||||
}
|
||||
content.itemAnimators.clear();
|
||||
}
|
||||
windowAnimatorSet = new AnimatorSet();
|
||||
windowAnimatorSet.playTogether(
|
||||
ObjectAnimator.ofFloat(content, "translationY", AndroidUtilities.dp(content.showedFromBotton ? 5 : -5)),
|
||||
ObjectAnimator.ofFloat(content, "alpha", 0.0f));
|
||||
ObjectAnimator.ofFloat(content, View.TRANSLATION_Y, AndroidUtilities.dp(content.showedFromBotton ? 5 : -5)),
|
||||
ObjectAnimator.ofFloat(content, View.ALPHA, 0.0f));
|
||||
windowAnimatorSet.setDuration(dismissAnimationDuration);
|
||||
windowAnimatorSet.addListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
|
@ -451,8 +485,8 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
setFocusable(false);
|
||||
try {
|
||||
ActionBarPopupWindow.super.dismiss();
|
||||
} catch (Exception e) {
|
||||
//don't promt
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
unregisterListener();
|
||||
}
|
||||
|
@ -471,8 +505,8 @@ public class ActionBarPopupWindow extends PopupWindow {
|
|||
} else {
|
||||
try {
|
||||
super.dismiss();
|
||||
} catch (Exception e) {
|
||||
//don't promt
|
||||
} catch (Exception ignore) {
|
||||
|
||||
}
|
||||
unregisterListener();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import android.view.ViewGroup;
|
|||
import android.view.Window;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
@ -47,6 +48,7 @@ import org.telegram.messenger.FileLog;
|
|||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.ui.Components.AnimationProperties;
|
||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
|
@ -84,6 +86,7 @@ public class BottomSheet extends Dialog {
|
|||
|
||||
private int touchSlop;
|
||||
private boolean useFastDismiss;
|
||||
protected Interpolator openInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT;
|
||||
|
||||
private TextView titleView;
|
||||
|
||||
|
@ -93,7 +96,7 @@ public class BottomSheet extends Dialog {
|
|||
|
||||
private boolean allowNestedScroll = true;
|
||||
|
||||
private Drawable shadowDrawable;
|
||||
protected Drawable shadowDrawable;
|
||||
protected int backgroundPaddingTop;
|
||||
protected int backgroundPaddingLeft;
|
||||
|
||||
|
@ -107,6 +110,7 @@ public class BottomSheet extends Dialog {
|
|||
private BottomSheetDelegateInterface delegate;
|
||||
|
||||
protected AnimatorSet currentSheetAnimation;
|
||||
protected int currentSheetAnimationType;
|
||||
|
||||
protected View nestedScrollChild;
|
||||
|
||||
|
@ -681,6 +685,27 @@ public class BottomSheet extends Dialog {
|
|||
window.setAttributes(params);
|
||||
}
|
||||
|
||||
public boolean isFocusable() {
|
||||
return focusable;
|
||||
}
|
||||
|
||||
public void setFocusable(boolean value) {
|
||||
if (focusable == value) {
|
||||
return;
|
||||
}
|
||||
focusable = value;
|
||||
Window window = getWindow();
|
||||
WindowManager.LayoutParams params = window.getAttributes();
|
||||
if (focusable) {
|
||||
params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
params.flags &=~ WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||
} else {
|
||||
params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
||||
params.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||
}
|
||||
window.setAttributes(params);
|
||||
}
|
||||
|
||||
public void setShowWithoutAnimation(boolean value) {
|
||||
showWithoutAnimation = value;
|
||||
}
|
||||
|
@ -778,6 +803,7 @@ public class BottomSheet extends Dialog {
|
|||
if (currentSheetAnimation != null) {
|
||||
currentSheetAnimation.cancel();
|
||||
currentSheetAnimation = null;
|
||||
currentSheetAnimationType = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -792,18 +818,20 @@ public class BottomSheet extends Dialog {
|
|||
container.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
}
|
||||
containerView.setTranslationY(containerView.getMeasuredHeight());
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(
|
||||
ObjectAnimator.ofFloat(containerView, "translationY", 0),
|
||||
ObjectAnimator.ofInt(backDrawable, "alpha", dimBehind ? 51 : 0));
|
||||
animatorSet.setDuration(400);
|
||||
animatorSet.setStartDelay(20);
|
||||
animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
|
||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||
currentSheetAnimationType = 1;
|
||||
currentSheetAnimation = new AnimatorSet();
|
||||
currentSheetAnimation.playTogether(
|
||||
ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, 0),
|
||||
ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, dimBehind ? 51 : 0));
|
||||
currentSheetAnimation.setDuration(400);
|
||||
currentSheetAnimation.setStartDelay(20);
|
||||
currentSheetAnimation.setInterpolator(openInterpolator);
|
||||
currentSheetAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||
currentSheetAnimation = null;
|
||||
currentSheetAnimationType = 0;
|
||||
if (delegate != null) {
|
||||
delegate.onOpenAnimationEnd();
|
||||
}
|
||||
|
@ -824,12 +852,12 @@ public class BottomSheet extends Dialog {
|
|||
public void onAnimationCancel(Animator animation) {
|
||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||
currentSheetAnimation = null;
|
||||
currentSheetAnimationType = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
||||
animatorSet.start();
|
||||
currentSheetAnimation = animatorSet;
|
||||
currentSheetAnimation.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -893,18 +921,20 @@ public class BottomSheet extends Dialog {
|
|||
}
|
||||
dismissed = true;
|
||||
cancelSheetAnimation();
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(
|
||||
currentSheetAnimationType = 2;
|
||||
currentSheetAnimation = new AnimatorSet();
|
||||
currentSheetAnimation.playTogether(
|
||||
ObjectAnimator.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)),
|
||||
ObjectAnimator.ofInt(backDrawable, "alpha", 0)
|
||||
);
|
||||
animatorSet.setDuration(180);
|
||||
animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||
currentSheetAnimation.setDuration(180);
|
||||
currentSheetAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
||||
currentSheetAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||
currentSheetAnimation = null;
|
||||
currentSheetAnimationType = 0;
|
||||
if (onClickListener != null) {
|
||||
onClickListener.onClick(BottomSheet.this, item);
|
||||
}
|
||||
|
@ -923,12 +953,12 @@ public class BottomSheet extends Dialog {
|
|||
public void onAnimationCancel(Animator animation) {
|
||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||
currentSheetAnimation = null;
|
||||
currentSheetAnimationType = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
||||
animatorSet.start();
|
||||
currentSheetAnimation = animatorSet;
|
||||
currentSheetAnimation.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -942,24 +972,26 @@ public class BottomSheet extends Dialog {
|
|||
dismissed = true;
|
||||
cancelSheetAnimation();
|
||||
if (!allowCustomAnimation || !onCustomCloseAnimation()) {
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(
|
||||
currentSheetAnimationType = 2;
|
||||
currentSheetAnimation = new AnimatorSet();
|
||||
currentSheetAnimation.playTogether(
|
||||
ObjectAnimator.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)),
|
||||
ObjectAnimator.ofInt(backDrawable, "alpha", 0)
|
||||
);
|
||||
if (useFastDismiss) {
|
||||
int height = containerView.getMeasuredHeight();
|
||||
animatorSet.setDuration(Math.max(60, (int) (180 * (height - containerView.getTranslationY()) / (float) height)));
|
||||
currentSheetAnimation.setDuration(Math.max(60, (int) (180 * (height - containerView.getTranslationY()) / (float) height)));
|
||||
useFastDismiss = false;
|
||||
} else {
|
||||
animatorSet.setDuration(180);
|
||||
currentSheetAnimation.setDuration(180);
|
||||
}
|
||||
animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||
currentSheetAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
||||
currentSheetAnimation.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||
currentSheetAnimation = null;
|
||||
currentSheetAnimationType = 0;
|
||||
AndroidUtilities.runOnUIThread(() -> {
|
||||
try {
|
||||
dismissInternal();
|
||||
|
@ -975,12 +1007,12 @@ public class BottomSheet extends Dialog {
|
|||
public void onAnimationCancel(Animator animation) {
|
||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||
currentSheetAnimation = null;
|
||||
currentSheetAnimationType = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
||||
animatorSet.start();
|
||||
currentSheetAnimation = animatorSet;
|
||||
currentSheetAnimation.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -136,12 +136,6 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
textWidth = (int) Math.ceil(layout.getLineWidth(0));
|
||||
textHeight = layout.getLineBottom(0);
|
||||
|
||||
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
|
||||
offsetY = (getMeasuredHeight() - textHeight) / 2;
|
||||
} else {
|
||||
offsetY = 0;
|
||||
}
|
||||
|
||||
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT) {
|
||||
offsetX = -(int) layout.getLineLeft(0);
|
||||
} else if (layout.getLineLeft(0) == 0) {
|
||||
|
@ -207,6 +201,12 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
finalHeight = textHeight;
|
||||
}
|
||||
setMeasuredDimension(width, finalHeight);
|
||||
|
||||
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
|
||||
offsetY = (getMeasuredHeight() - textHeight) / 2;
|
||||
} else {
|
||||
offsetY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -306,7 +306,13 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
|||
|
||||
private boolean recreateLayoutMaybe() {
|
||||
if (wasLayout && getMeasuredHeight() != 0) {
|
||||
return createLayout(getMeasuredWidth());
|
||||
boolean result = createLayout(getMeasuredWidth() - getPaddingLeft() - getPaddingRight());
|
||||
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
|
||||
offsetY = (getMeasuredHeight() - textHeight) / 2;
|
||||
} else {
|
||||
offsetY = 0;
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
requestLayout();
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import android.graphics.Canvas;
|
|||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
|
@ -207,91 +206,6 @@ public class Theme {
|
|||
public static double autoNightLocationLatitude = 10000;
|
||||
public static double autoNightLocationLongitude = 10000;
|
||||
|
||||
private static class AttachCameraDrawable extends Drawable {
|
||||
|
||||
private Path segment;
|
||||
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
|
||||
public AttachCameraDrawable() {
|
||||
int size = AndroidUtilities.dp(54);
|
||||
RectF rect = new RectF(0, 0, size, size);
|
||||
|
||||
segment = new Path();
|
||||
segment.moveTo(AndroidUtilities.dp(23), AndroidUtilities.dp(20));
|
||||
segment.lineTo(AndroidUtilities.dp(23), 0);
|
||||
segment.arcTo(rect, -98, 50, false);
|
||||
segment.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
canvas.save();
|
||||
int cx = AndroidUtilities.dp(27);
|
||||
canvas.rotate(-90, cx, cx);
|
||||
for (int a = 0; a < 6; a++) {
|
||||
switch (a) {
|
||||
case 0:
|
||||
paint.setColor(getColor(key_chat_attachCameraIcon1));
|
||||
break;
|
||||
case 1:
|
||||
paint.setColor(getColor(key_chat_attachCameraIcon2));
|
||||
break;
|
||||
case 2:
|
||||
paint.setColor(getColor(key_chat_attachCameraIcon3));
|
||||
break;
|
||||
case 3:
|
||||
paint.setColor(getColor(key_chat_attachCameraIcon4));
|
||||
break;
|
||||
case 4:
|
||||
paint.setColor(getColor(key_chat_attachCameraIcon5));
|
||||
break;
|
||||
case 5:
|
||||
paint.setColor(getColor(key_chat_attachCameraIcon6));
|
||||
break;
|
||||
}
|
||||
canvas.rotate(60, cx, cx);
|
||||
canvas.drawPath(segment, paint);
|
||||
}
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSPARENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return AndroidUtilities.dp(54);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
return AndroidUtilities.dp(54);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumWidth() {
|
||||
return AndroidUtilities.dp(54);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinimumHeight() {
|
||||
return AndroidUtilities.dp(54);
|
||||
}
|
||||
}
|
||||
|
||||
private static Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
public static ArrayList<ThemeInfo> themes;
|
||||
|
@ -505,7 +419,8 @@ public class Theme {
|
|||
public static Drawable chat_msgCallDownGreenDrawable;
|
||||
|
||||
public static Drawable chat_msgAvatarLiveLocationDrawable;
|
||||
public static Drawable[] chat_attachButtonDrawables = new Drawable[10];
|
||||
public static Drawable chat_attachEmptyDrawable;
|
||||
public static Drawable[] chat_attachButtonDrawables = new Drawable[6];
|
||||
public static Drawable[] chat_locationDrawable = new Drawable[2];
|
||||
public static Drawable[] chat_contactDrawable = new Drawable[2];
|
||||
public static Drawable[] chat_cornerOuter = new Drawable[4];
|
||||
|
@ -772,41 +687,29 @@ public class Theme {
|
|||
public static final String key_chats_actionUnreadBackground = "chats_actionUnreadBackground";
|
||||
public static final String key_chats_actionUnreadPressedBackground = "chats_actionUnreadPressedBackground";
|
||||
|
||||
public static final String key_chat_attachCameraIcon1 = "chat_attachCameraIcon1";
|
||||
public static final String key_chat_attachCameraIcon2 = "chat_attachCameraIcon2";
|
||||
public static final String key_chat_attachCameraIcon3 = "chat_attachCameraIcon3";
|
||||
public static final String key_chat_attachCameraIcon4 = "chat_attachCameraIcon4";
|
||||
public static final String key_chat_attachCameraIcon5 = "chat_attachCameraIcon5";
|
||||
public static final String key_chat_attachCameraIcon6 = "chat_attachCameraIcon6";
|
||||
public static final String key_chat_attachMediaBanBackground = "chat_attachMediaBanBackground";
|
||||
public static final String key_chat_attachMediaBanText = "chat_attachMediaBanText";
|
||||
public static final String key_chat_attachCheckBoxCheck = "chat_attachCheckBoxCheck";
|
||||
public static final String key_chat_attachCheckBoxBackground = "chat_attachCheckBoxBackground";
|
||||
public static final String key_chat_attachPhotoBackground = "chat_attachPhotoBackground";
|
||||
public static final String key_chat_attachActiveTab = "chat_attachActiveTab";
|
||||
public static final String key_chat_attachUnactiveTab = "chat_attachUnactiveTab";
|
||||
public static final String key_chat_attachPermissionImage = "chat_attachPermissionImage";
|
||||
public static final String key_chat_attachPermissionMark = "chat_attachPermissionMark";
|
||||
public static final String key_chat_attachPermissionText = "chat_attachPermissionText";
|
||||
public static final String key_chat_attachEmptyImage = "chat_attachEmptyImage";
|
||||
|
||||
public static final String key_chat_attachGalleryBackground = "chat_attachGalleryBackground";
|
||||
//public static final String key_chat_attachGalleryBackgroundPressed = "chat_attachGalleryBackgroundPressed";
|
||||
public static final String key_chat_attachGalleryIcon = "chat_attachGalleryIcon";
|
||||
public static final String key_chat_attachVideoBackground = "chat_attachVideoBackground";
|
||||
//public static final String key_chat_attachVideoBackgroundPressed = "chat_attachVideoBackgroundPressed";
|
||||
public static final String key_chat_attachVideoIcon = "chat_attachVideoIcon";
|
||||
public static final String key_chat_attachAudioBackground = "chat_attachAudioBackground";
|
||||
//public static final String key_chat_attachAudioBackgroundPressed = "chat_attachAudioBackgroundPressed";
|
||||
public static final String key_chat_attachAudioIcon = "chat_attachAudioIcon";
|
||||
public static final String key_chat_attachFileBackground = "chat_attachFileBackground";
|
||||
//public static final String key_chat_attachFileBackgroundPressed = "chat_attachFileBackgroundPressed";
|
||||
public static final String key_chat_attachFileIcon = "chat_attachFileIcon";
|
||||
public static final String key_chat_attachContactBackground = "chat_attachContactBackground";
|
||||
//public static final String key_chat_attachContactBackgroundPressed = "chat_attachContactBackgroundPressed";
|
||||
public static final String key_chat_attachContactIcon = "chat_attachContactIcon";
|
||||
public static final String key_chat_attachLocationBackground = "chat_attachLocationBackground";
|
||||
//public static final String key_chat_attachLocationBackgroundPressed = "chat_attachLocationBackgroundPressed";
|
||||
public static final String key_chat_attachLocationIcon = "chat_attachLocationIcon";
|
||||
public static final String key_chat_attachHideBackground = "chat_attachHideBackground";
|
||||
//public static final String key_chat_attachHideBackgroundPressed = "chat_attachHideBackgroundPressed";
|
||||
public static final String key_chat_attachHideIcon = "chat_attachHideIcon";
|
||||
public static final String key_chat_attachSendBackground = "chat_attachSendBackground";
|
||||
//public static final String key_chat_attachSendBackgroundPressed = "chat_attachSendBackgroundPressed";
|
||||
public static final String key_chat_attachSendIcon = "chat_attachSendIcon";
|
||||
public static final String key_chat_attachPollBackground = "chat_attachPollBackground";
|
||||
//public static final String key_chat_attachPollBackgroundPressed = "chat_attachPollBackgroundPressed";
|
||||
public static final String key_chat_attachPollIcon = "chat_attachPollIcon";
|
||||
|
||||
public static final String key_chat_status = "chat_status";
|
||||
|
@ -964,6 +867,7 @@ public class Theme {
|
|||
public static final String key_chat_messagePanelHint = "chat_messagePanelHint";
|
||||
public static final String key_chat_messagePanelIcons = "chat_messagePanelIcons";
|
||||
public static final String key_chat_messagePanelSend = "chat_messagePanelSend";
|
||||
public static final String key_chat_messagePanelSendPressed = "chat_messagePanelPressedSend";
|
||||
public static final String key_chat_messagePanelVoiceLock = "key_chat_messagePanelVoiceLock";
|
||||
public static final String key_chat_messagePanelVoiceLockBackground = "key_chat_messagePanelVoiceLockBackground";
|
||||
public static final String key_chat_messagePanelVoiceLockShadow = "key_chat_messagePanelVoiceLockShadow";
|
||||
|
@ -1405,40 +1309,29 @@ public class Theme {
|
|||
defaultColors.put(key_chats_actionUnreadPressedBackground, 0xfff2f2f2);
|
||||
defaultColors.put(key_chats_menuTopBackgroundCats, 0xff598fba);
|
||||
|
||||
defaultColors.put(key_chat_attachCameraIcon1, 0xffff7d30);
|
||||
defaultColors.put(key_chat_attachCameraIcon2, 0xffeb5850);
|
||||
defaultColors.put(key_chat_attachCameraIcon3, 0xff43a9f2);
|
||||
defaultColors.put(key_chat_attachCameraIcon4, 0xffb455e0);
|
||||
defaultColors.put(key_chat_attachCameraIcon5, 0xff61d061);
|
||||
defaultColors.put(key_chat_attachCameraIcon6, 0xfffec125);
|
||||
defaultColors.put(key_chat_attachMediaBanBackground, 0xff464646);
|
||||
defaultColors.put(key_chat_attachMediaBanText, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachCheckBoxCheck, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachCheckBoxBackground, 0xff39b2f7);
|
||||
defaultColors.put(key_chat_attachPhotoBackground, 0x08000000);
|
||||
defaultColors.put(key_chat_attachActiveTab, 0xff33a7f5);
|
||||
defaultColors.put(key_chat_attachUnactiveTab, 0xff92999e);
|
||||
defaultColors.put(key_chat_attachPermissionImage, 0xff333333);
|
||||
defaultColors.put(key_chat_attachPermissionMark, 0xffe25050);
|
||||
defaultColors.put(key_chat_attachPermissionText, 0xff6f777a);
|
||||
defaultColors.put(key_chat_attachEmptyImage, 0xffcccccc);
|
||||
|
||||
defaultColors.put(key_chat_attachGalleryBackground, 0xffa47ad9);
|
||||
//defaultColors.put(key_chat_attachGalleryBackgroundPressed, 0xffa47ad9);
|
||||
defaultColors.put(key_chat_attachGalleryBackground, 0xff459df5);
|
||||
defaultColors.put(key_chat_attachGalleryIcon, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachVideoBackground, 0xffe37179);
|
||||
//defaultColors.put(key_chat_attachVideoBackgroundPressed, 0xffe37179);
|
||||
defaultColors.put(key_chat_attachVideoIcon, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachAudioBackground, 0xfff68751);
|
||||
//defaultColors.put(key_chat_attachAudioBackgroundPressed, 0xfff68751);
|
||||
defaultColors.put(key_chat_attachAudioBackground, 0xffeb6060);
|
||||
defaultColors.put(key_chat_attachAudioIcon, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachFileBackground, 0xff34a0f4);
|
||||
//defaultColors.put(key_chat_attachFileBackgroundPressed, 0xff34a0f4);
|
||||
defaultColors.put(key_chat_attachFileBackground, 0xff34b9f1);
|
||||
defaultColors.put(key_chat_attachFileIcon, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachContactBackground, 0xff3ebffa);
|
||||
//defaultColors.put(key_chat_attachContactBackgroundPressed, 0xff3ebffa);
|
||||
defaultColors.put(key_chat_attachContactBackground, 0xfff2c04b);
|
||||
defaultColors.put(key_chat_attachContactIcon, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachLocationBackground, 0xff3fc87a);
|
||||
//defaultColors.put(key_chat_attachLocationBackgroundPressed, 0xff3fc87a);
|
||||
defaultColors.put(key_chat_attachLocationBackground, 0xff36c766);
|
||||
defaultColors.put(key_chat_attachLocationIcon, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachHideBackground, 0xffaeaab8);
|
||||
//defaultColors.put(key_chat_attachHideBackgroundPressed, 0xffaeaab8);
|
||||
defaultColors.put(key_chat_attachHideIcon, 0xffffffff);
|
||||
defaultColors.put(key_chat_attachSendBackground, 0xff3ebffa);
|
||||
//defaultColors.put(key_chat_attachSendBackgroundPressed, 0xff3ebffa);
|
||||
defaultColors.put(key_chat_attachPollBackground, 0xfff5c34d);
|
||||
//defaultColors.put(key_chat_attachPollBackgroundPressed, 0xfff68751);
|
||||
defaultColors.put(key_chat_attachPollBackground, 0xfff2c04b);
|
||||
defaultColors.put(key_chat_attachPollIcon, 0xffffffff);
|
||||
|
||||
|
||||
|
@ -1446,7 +1339,6 @@ public class Theme {
|
|||
defaultColors.put(key_chat_inGreenCall, 0xff00c853);
|
||||
defaultColors.put(key_chat_inRedCall, 0xffff4848);
|
||||
defaultColors.put(key_chat_outGreenCall, 0xff00c853);
|
||||
defaultColors.put(key_chat_attachSendIcon, 0xffffffff);
|
||||
defaultColors.put(key_chat_shareBackground, 0x66728fa6);
|
||||
defaultColors.put(key_chat_shareBackgroundSelected, 0x99728fa6);
|
||||
defaultColors.put(key_chat_lockIcon, 0xffffffff);
|
||||
|
@ -1652,6 +1544,7 @@ public class Theme {
|
|||
defaultColors.put(key_chat_recordedVoiceProgressInner, 0xffffffff);
|
||||
defaultColors.put(key_chat_recordVoiceCancel, 0xff999999);
|
||||
defaultColors.put(key_chat_messagePanelSend, 0xff62b0eb);
|
||||
defaultColors.put(key_chat_messagePanelSendPressed, 0xffffffff);
|
||||
defaultColors.put(key_chat_messagePanelVoiceLock, 0xffa4a4a4);
|
||||
defaultColors.put(key_chat_messagePanelVoiceLockBackground, 0xffffffff);
|
||||
defaultColors.put(key_chat_messagePanelVoiceLockShadow, 0xff000000);
|
||||
|
@ -1893,6 +1786,13 @@ public class Theme {
|
|||
fallbackKeys.put(key_actionBarTabSelector, key_actionBarDefaultSelector);
|
||||
fallbackKeys.put(key_profile_status, key_avatar_subtitleInProfileBlue);
|
||||
fallbackKeys.put(key_chats_menuTopBackgroundCats, key_avatar_backgroundActionBarBlue);
|
||||
fallbackKeys.put(key_chat_messagePanelSendPressed, key_chat_messagePanelVoicePressed);
|
||||
//fallbackKeys.put(key_chat_attachActiveTab, 0xff33a7f5); //TODO fallback
|
||||
//fallbackKeys.put(key_chat_attachUnactiveTab, 0xff92999e); //TODO fallback
|
||||
fallbackKeys.put(key_chat_attachPermissionImage, key_dialogTextBlack);
|
||||
fallbackKeys.put(key_chat_attachPermissionMark, key_chat_sentError);
|
||||
fallbackKeys.put(key_chat_attachPermissionText, key_dialogTextBlack);
|
||||
fallbackKeys.put(key_chat_attachEmptyImage, key_emptyListPlaceholder);
|
||||
|
||||
themes = new ArrayList<>();
|
||||
otherThemes = new ArrayList<>();
|
||||
|
@ -2407,30 +2307,45 @@ public class Theme {
|
|||
}
|
||||
|
||||
public static Drawable createSelectorDrawable(int color) {
|
||||
return createSelectorDrawable(color, 1);
|
||||
return createSelectorDrawable(color, 1, -1);
|
||||
}
|
||||
|
||||
public static Drawable createSelectorDrawable(int color, int maskType) {
|
||||
return createSelectorDrawable(color, maskType, -1);
|
||||
}
|
||||
|
||||
public static Drawable createSelectorDrawable(int color, int maskType, int radius) {
|
||||
Drawable drawable;
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
Drawable maskDrawable = null;
|
||||
if ((maskType == 1 || maskType == 5) && Build.VERSION.SDK_INT >= 23) {
|
||||
maskDrawable = null;
|
||||
} else if (maskType == 1 || maskType == 3 || maskType == 4 || maskType == 5) {
|
||||
} else if (maskType == 1 || maskType == 3 || maskType == 4 || maskType == 5 || maskType == 6 || maskType == 7) {
|
||||
maskPaint.setColor(0xffffffff);
|
||||
maskDrawable = new Drawable() {
|
||||
|
||||
RectF rect;
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
android.graphics.Rect bounds = getBounds();
|
||||
int rad;
|
||||
if (maskType == 1) {
|
||||
rad = AndroidUtilities.dp(20);
|
||||
} else if (maskType == 3) {
|
||||
rad = (Math.max(bounds.width(), bounds.height()) / 2);
|
||||
if (maskType == 7) {
|
||||
if (rect == null) {
|
||||
rect = new RectF();
|
||||
}
|
||||
rect.set(bounds);
|
||||
canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), maskPaint);
|
||||
} else {
|
||||
rad = (int) Math.ceil(Math.sqrt((bounds.left - bounds.centerX()) * (bounds.left - bounds.centerX()) + (bounds.top - bounds.centerY()) * (bounds.top - bounds.centerY())));
|
||||
int rad;
|
||||
if (maskType == 1 || maskType == 6) {
|
||||
rad = AndroidUtilities.dp(20);
|
||||
} else if (maskType == 3) {
|
||||
rad = (Math.max(bounds.width(), bounds.height()) / 2);
|
||||
} else {
|
||||
rad = (int) Math.ceil(Math.sqrt((bounds.left - bounds.centerX()) * (bounds.left - bounds.centerX()) + (bounds.top - bounds.centerY()) * (bounds.top - bounds.centerY())));
|
||||
}
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), rad, maskPaint);
|
||||
}
|
||||
canvas.drawCircle(bounds.centerX(), bounds.centerY(), rad, maskPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2458,7 +2373,7 @@ public class Theme {
|
|||
RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, null, maskDrawable);
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
if (maskType == 1) {
|
||||
rippleDrawable.setRadius(AndroidUtilities.dp(20));
|
||||
rippleDrawable.setRadius(radius <= 0 ? AndroidUtilities.dp(20) : radius);
|
||||
} else if (maskType == 5) {
|
||||
rippleDrawable.setRadius(RippleDrawable.RADIUS_AUTO);
|
||||
}
|
||||
|
@ -3352,16 +3267,13 @@ public class Theme {
|
|||
|
||||
chat_contextResult_shadowUnderSwitchDrawable = resources.getDrawable(R.drawable.header_shadow).mutate();
|
||||
|
||||
chat_attachButtonDrawables[0] = new AttachCameraDrawable();
|
||||
chat_attachButtonDrawables[1] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_gallery);
|
||||
chat_attachButtonDrawables[2] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_video);
|
||||
chat_attachButtonDrawables[3] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_audio);
|
||||
chat_attachButtonDrawables[4] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_file);
|
||||
chat_attachButtonDrawables[5] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_contact);
|
||||
chat_attachButtonDrawables[6] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_location);
|
||||
chat_attachButtonDrawables[7] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_close);
|
||||
chat_attachButtonDrawables[8] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_send);
|
||||
chat_attachButtonDrawables[9] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_polls);
|
||||
chat_attachButtonDrawables[0] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_gallery);
|
||||
chat_attachButtonDrawables[1] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_audio);
|
||||
chat_attachButtonDrawables[2] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_file);
|
||||
chat_attachButtonDrawables[3] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_contact);
|
||||
chat_attachButtonDrawables[4] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_location);
|
||||
chat_attachButtonDrawables[5] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_polls);
|
||||
chat_attachEmptyDrawable = resources.getDrawable(R.drawable.nophotos3);
|
||||
|
||||
chat_cornerOuter[0] = resources.getDrawable(R.drawable.corner_out_tl);
|
||||
chat_cornerOuter[1] = resources.getDrawable(R.drawable.corner_out_tr);
|
||||
|
@ -3667,43 +3579,20 @@ public class Theme {
|
|||
|
||||
setDrawableColorByKey(chat_composeShadowDrawable, key_chat_messagePanelShadow);
|
||||
|
||||
/*for (int a = 1; a < 3; a++) {
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 1], getColor(a == 1 ? key_chat_attachGalleryBackground : key_chat_attachGalleryBackgroundPressed), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 1], getColor(key_chat_attachGalleryIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 2], getColor(a == 1 ? key_chat_attachVideoBackground : key_chat_attachVideoBackgroundPressed), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 2], getColor(key_chat_attachVideoIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 3], getColor(a == 1 ? key_chat_attachAudioBackground : key_chat_attachAudioBackgroundPressed), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 3], getColor(key_chat_attachAudioIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 4], getColor(a == 1 ? key_chat_attachFileBackground : key_chat_attachFileBackgroundPressed), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 4], getColor(key_chat_attachFileIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 5], getColor(a == 1 ? key_chat_attachContactBackground : key_chat_attachContactBackgroundPressed), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 5], getColor(key_chat_attachContactIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 6], getColor(a == 1 ? key_chat_attachLocationBackground : key_chat_attachLocationBackgroundPressed), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 6], getColor(key_chat_attachLocationIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 7], getColor(a == 1 ? key_chat_attachHideBackground : key_chat_attachHideBackgroundPressed), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 7], getColor(key_chat_attachHideIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 8], getColor(a == 1 ? key_chat_attachSendBackground : key_chat_attachSendBackgroundPressed), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 8], getColor(key_chat_attachSendIcon), true);
|
||||
}*/
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[0], getColor(key_chat_attachGalleryBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[0], getColor(key_chat_attachGalleryIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[1], getColor(key_chat_attachAudioBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[1], getColor(key_chat_attachAudioIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[2], getColor(key_chat_attachFileBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[2], getColor(key_chat_attachFileIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[3], getColor(key_chat_attachContactBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[3], getColor(key_chat_attachContactIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[4], getColor(key_chat_attachLocationBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[4], getColor(key_chat_attachLocationIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[5], getColor(key_chat_attachPollBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[5], getColor(key_chat_attachPollIcon), true);
|
||||
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[1], getColor(key_chat_attachGalleryBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[1], getColor(key_chat_attachGalleryIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[2], getColor(key_chat_attachVideoBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[2], getColor(key_chat_attachVideoIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[3], getColor(key_chat_attachAudioBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[3], getColor(key_chat_attachAudioIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[4], getColor(key_chat_attachFileBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[4], getColor(key_chat_attachFileIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[5], getColor(key_chat_attachContactBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[5], getColor(key_chat_attachContactIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[6], getColor(key_chat_attachLocationBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[6], getColor(key_chat_attachLocationIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[7], getColor(key_chat_attachHideBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[7], getColor(key_chat_attachHideIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[8], getColor(key_chat_attachSendBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[8], getColor(key_chat_attachSendIcon), true);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9], getColor(key_chat_attachPollBackground), false);
|
||||
setCombinedDrawableColor(chat_attachButtonDrawables[9], getColor(key_chat_attachPollIcon), true);
|
||||
setDrawableColor(chat_attachEmptyDrawable, getColor(key_chat_attachEmptyImage));
|
||||
|
||||
applyChatServiceMessageColor();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package org.telegram.ui.ActionBar;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
|
@ -96,6 +97,7 @@ public class ThemeDescription {
|
|||
public static int FLAG_AB_SUBMENUBACKGROUND = 0x80000000;
|
||||
|
||||
private View viewToInvalidate;
|
||||
private int alphaOverride = -1;
|
||||
private Paint[] paintToUpdate;
|
||||
private Drawable[] drawablesToUpdate;
|
||||
private Class[] listClasses;
|
||||
|
@ -157,6 +159,10 @@ public class ThemeDescription {
|
|||
}
|
||||
|
||||
public ThemeDescription(View view, int flags, Class[] classes, String[] classesFields, Paint[] paint, Drawable[] drawables, ThemeDescriptionDelegate themeDescriptionDelegate, String key) {
|
||||
this(view, flags, classes, classesFields, paint, drawables, -1, themeDescriptionDelegate, key);
|
||||
}
|
||||
|
||||
public ThemeDescription(View view, int flags, Class[] classes, String[] classesFields, Paint[] paint, Drawable[] drawables, int alpha, ThemeDescriptionDelegate themeDescriptionDelegate, String key) {
|
||||
currentKey = key;
|
||||
paintToUpdate = paint;
|
||||
drawablesToUpdate = drawables;
|
||||
|
@ -164,6 +170,7 @@ public class ThemeDescription {
|
|||
changeFlags = flags;
|
||||
listClasses = classes;
|
||||
listClassesFieldName = classesFields;
|
||||
alphaOverride = alpha;
|
||||
delegate = themeDescriptionDelegate;
|
||||
cachedFields = new HashMap<>();
|
||||
notFoundCachedFields = new HashMap<>();
|
||||
|
@ -211,6 +218,10 @@ public class ThemeDescription {
|
|||
if (save) {
|
||||
Theme.setColor(currentKey, color, useDefault);
|
||||
}
|
||||
currentColor = color;
|
||||
if (alphaOverride > 0) {
|
||||
color = Color.argb(alphaOverride, Color.red(color), Color.green(color), Color.blue(color));
|
||||
}
|
||||
if (paintToUpdate != null) {
|
||||
for (int a = 0; a < paintToUpdate.length; a++) {
|
||||
if ((changeFlags & FLAG_LINKCOLOR) != 0 && paintToUpdate[a] instanceof TextPaint) {
|
||||
|
@ -465,7 +476,6 @@ public class ThemeDescription {
|
|||
}
|
||||
processViewColor(viewToInvalidate, color);
|
||||
}
|
||||
currentColor = color;
|
||||
if (delegate != null) {
|
||||
delegate.didSetColor();
|
||||
}
|
||||
|
|
|
@ -236,6 +236,16 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement
|
|||
lastSticker = emoji.toString();
|
||||
stickersToLoad.clear();
|
||||
boolean isValidEmoji = searchEmoji && (Emoji.isValidEmoji(originalEmoji) || Emoji.isValidEmoji(lastSticker));
|
||||
if (isValidEmoji) {
|
||||
TLRPC.Document animatedSticker = MediaDataController.getInstance(currentAccount).getEmojiAnimatedSticker(emoji);
|
||||
if (animatedSticker != null) {
|
||||
ArrayList<TLRPC.TL_messages_stickerSet> sets = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_EMOJI);
|
||||
File f = FileLoader.getPathToAttach(animatedSticker, true);
|
||||
if (!f.exists()) {
|
||||
FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(animatedSticker), sets.get(0), null, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (emojiOnly || SharedConfig.suggestStickers == 2 || !isValidEmoji) {
|
||||
if (visible && (keywordResults == null || keywordResults.isEmpty())) {
|
||||
visible = false;
|
||||
|
|
|
@ -40,6 +40,7 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.FileProvider;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
|
@ -49,12 +50,14 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import android.text.Layout;
|
||||
import android.text.Selection;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.MetricAffectingSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.util.LongSparseArray;
|
||||
|
@ -156,6 +159,7 @@ import org.telegram.ui.Components.TextPaintSpan;
|
|||
import org.telegram.ui.Components.TextPaintUrlSpan;
|
||||
import org.telegram.ui.Components.TextPaintWebpageUrlSpan;
|
||||
import org.telegram.ui.Components.TypefaceSpan;
|
||||
import org.telegram.ui.Components.URLSpanNoUnderline;
|
||||
import org.telegram.ui.Components.VideoPlayer;
|
||||
import org.telegram.ui.Components.WebPlayerView;
|
||||
|
||||
|
@ -3707,7 +3711,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
captionTextViewNext = new TextView(activity);
|
||||
captionTextViewNext.setMaxLines(10);
|
||||
captionTextViewNext.setBackgroundColor(0x7f000000);
|
||||
captionTextViewNext.setMovementMethod(new PhotoViewer.LinkMovementMethodMy());
|
||||
captionTextViewNext.setMovementMethod(new LinkMovementMethodMy());
|
||||
captionTextViewNext.setPadding(AndroidUtilities.dp(20), AndroidUtilities.dp(8), AndroidUtilities.dp(20), AndroidUtilities.dp(8));
|
||||
captionTextViewNext.setLinkTextColor(0xffffffff);
|
||||
captionTextViewNext.setTextColor(0xffffffff);
|
||||
|
@ -3720,7 +3724,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
captionTextView = new TextView(activity);
|
||||
captionTextView.setMaxLines(10);
|
||||
captionTextView.setBackgroundColor(0x7f000000);
|
||||
captionTextView.setMovementMethod(new PhotoViewer.LinkMovementMethodMy());
|
||||
captionTextView.setMovementMethod(new LinkMovementMethodMy());
|
||||
captionTextView.setPadding(AndroidUtilities.dp(20), AndroidUtilities.dp(8), AndroidUtilities.dp(20), AndroidUtilities.dp(8));
|
||||
captionTextView.setLinkTextColor(0xffffffff);
|
||||
captionTextView.setTextColor(0xffffffff);
|
||||
|
@ -10409,6 +10413,22 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
|||
|
||||
//------------ photo viewer
|
||||
|
||||
private class LinkMovementMethodMy extends LinkMovementMethod {
|
||||
@Override
|
||||
public boolean onTouchEvent(@NonNull TextView widget, @NonNull Spannable buffer, @NonNull MotionEvent event) {
|
||||
try {
|
||||
boolean result = super.onTouchEvent(widget, buffer, event);
|
||||
if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
Selection.removeSelection(buffer);
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int[] coords = new int[2];
|
||||
|
||||
private boolean isPhotoVisible;
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
|
||||
package org.telegram.ui;
|
||||
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -22,8 +19,6 @@ import org.telegram.SQLite.SQLiteCursor;
|
|||
import org.telegram.SQLite.SQLiteDatabase;
|
||||
import org.telegram.SQLite.SQLitePreparedStatement;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.ClearCacheService;
|
||||
import org.telegram.messenger.MediaDataController;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
import org.telegram.messenger.FileLog;
|
||||
|
@ -32,6 +27,7 @@ import org.telegram.messenger.LocaleController;
|
|||
import org.telegram.messenger.MessagesController;
|
||||
import org.telegram.messenger.MessagesStorage;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.messenger.Utilities;
|
||||
import org.telegram.tgnet.NativeByteBuffer;
|
||||
|
@ -252,26 +248,19 @@ public class CacheControlActivity extends BaseFragment {
|
|||
if (position == keepMediaRow) {
|
||||
BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity());
|
||||
builder.setItems(new CharSequence[]{LocaleController.formatPluralString("Days", 3), LocaleController.formatPluralString("Weeks", 1), LocaleController.formatPluralString("Months", 1), LocaleController.getString("KeepMediaForever", R.string.KeepMediaForever)}, (dialog, which) -> {
|
||||
SharedPreferences.Editor editor = MessagesController.getGlobalMainSettings().edit();
|
||||
if (which == 0) {
|
||||
editor.putInt("keep_media", 3);
|
||||
SharedConfig.setKeepMedia(3);
|
||||
} else if (which == 1) {
|
||||
editor.putInt("keep_media", 0);
|
||||
SharedConfig.setKeepMedia(0);
|
||||
} else if (which == 2) {
|
||||
editor.putInt("keep_media", 1);
|
||||
SharedConfig.setKeepMedia(1);
|
||||
} else if (which == 3) {
|
||||
editor.putInt("keep_media", 2);
|
||||
SharedConfig.setKeepMedia(2);
|
||||
}
|
||||
editor.commit();
|
||||
if (listAdapter != null) {
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
PendingIntent pintent = PendingIntent.getService(ApplicationLoader.applicationContext, 1, new Intent(ApplicationLoader.applicationContext, ClearCacheService.class), 0);
|
||||
AlarmManager alarmManager = (AlarmManager) ApplicationLoader.applicationContext.getSystemService(Context.ALARM_SERVICE);
|
||||
alarmManager.cancel(pintent);
|
||||
if (which != 3) {
|
||||
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, 0, AlarmManager.INTERVAL_DAY, pintent);
|
||||
}
|
||||
SharedConfig.checkKeepMedia();
|
||||
});
|
||||
showDialog(builder.create());
|
||||
} else if (position == databaseRow) {
|
||||
|
@ -280,6 +269,9 @@ public class CacheControlActivity extends BaseFragment {
|
|||
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
||||
builder.setMessage(LocaleController.getString("LocalDatabaseClear", R.string.LocalDatabaseClear));
|
||||
builder.setPositiveButton(LocaleController.getString("CacheClear", R.string.CacheClear), (dialogInterface, i) -> {
|
||||
if (getParentActivity() == null) {
|
||||
return;
|
||||
}
|
||||
final AlertDialog progressDialog = new AlertDialog(getParentActivity(), 3);
|
||||
progressDialog.setCanCacnel(false);
|
||||
progressDialog.show();
|
||||
|
@ -507,7 +499,7 @@ public class CacheControlActivity extends BaseFragment {
|
|||
}
|
||||
} else if (position == keepMediaRow) {
|
||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||
int keepMedia = preferences.getInt("keep_media", 2);
|
||||
int keepMedia = SharedConfig.keepMedia;
|
||||
String value;
|
||||
if (keepMedia == 0) {
|
||||
value = LocaleController.formatPluralString("Weeks", 1);
|
||||
|
|
|
@ -13,12 +13,9 @@ import android.animation.AnimatorListenerAdapter;
|
|||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
@ -29,7 +26,6 @@ import android.graphics.drawable.Drawable;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
import android.telephony.SmsManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
|
@ -50,12 +46,10 @@ import android.widget.TextView;
|
|||
import org.telegram.PhoneFormat.PhoneFormat;
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.BuildVars;
|
||||
import org.telegram.messenger.FileLog;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.NotificationCenter;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.SmsReceiver;
|
||||
import org.telegram.tgnet.ConnectionsManager;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.ActionBar;
|
||||
|
@ -388,24 +382,7 @@ public class CancelAccountDeletionActivity extends BaseFragment {
|
|||
req.hash = hash;
|
||||
req.settings = new TLRPC.TL_codeSettings();
|
||||
req.settings.allow_flashcall = false;//simcardAvailable && allowCall;
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
try {
|
||||
req.settings.app_hash = SmsManager.getDefault().createAppSpecificSmsToken(PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, new Intent(ApplicationLoader.applicationContext, SmsReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
} catch (Throwable e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
} else {
|
||||
req.settings.app_hash = BuildVars.SMS_HASH;
|
||||
req.settings.app_hash_persistent = true;
|
||||
}
|
||||
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
|
||||
if (!TextUtils.isEmpty(req.settings.app_hash)) {
|
||||
req.settings.flags |= 8;
|
||||
preferences.edit().putString("sms_hash", req.settings.app_hash).commit();
|
||||
} else {
|
||||
preferences.edit().remove("sms_hash").commit();
|
||||
}
|
||||
|
||||
req.settings.allow_app_hash = ApplicationLoader.hasPlayServices;
|
||||
if (req.settings.allow_flashcall) {
|
||||
try {
|
||||
@SuppressLint("HardwareIds") String number = tm.getLine1Number();
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.telegram.messenger.FileLoader;
|
|||
import org.telegram.messenger.ImageLocation;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MessageObject;
|
||||
import org.telegram.messenger.SharedConfig;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
|
@ -100,20 +100,38 @@ public class ArchivedStickerSetCell extends FrameLayout {
|
|||
textView.setText(stickersSet.set.title);
|
||||
|
||||
valueTextView.setText(LocaleController.formatPluralString("Stickers", set.set.count));
|
||||
TLRPC.PhotoSize thumb = set.cover != null ? FileLoader.getClosestPhotoSizeWithSize(set.cover.thumbs, 90) : null;
|
||||
if (thumb != null && thumb.location != null) {
|
||||
if (MessageObject.canAutoplayAnimatedSticker(set.cover)) {
|
||||
imageView.setImage(ImageLocation.getForDocument(set.cover), "80_80", ImageLocation.getForDocument(thumb, set.cover), null, 0, set);
|
||||
} else {
|
||||
imageView.setImage(ImageLocation.getForDocument(thumb, set.cover), null, "webp", null, set);
|
||||
}
|
||||
|
||||
TLRPC.Document sticker;
|
||||
if (set.cover != null) {
|
||||
sticker = set.cover;
|
||||
} else if (!set.covers.isEmpty()) {
|
||||
TLRPC.Document document = set.covers.get(0);
|
||||
thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
|
||||
if (MessageObject.canAutoplayAnimatedSticker(document)) {
|
||||
imageView.setImage(ImageLocation.getForDocument(document), "80_80", ImageLocation.getForDocument(thumb, document), null, 0, set);
|
||||
sticker = set.covers.get(0);
|
||||
} else {
|
||||
sticker = null;
|
||||
}
|
||||
if (sticker != null) {
|
||||
TLObject object;
|
||||
if (set.set.thumb instanceof TLRPC.TL_photoSize) {
|
||||
object = set.set.thumb;
|
||||
} else {
|
||||
imageView.setImage(ImageLocation.getForDocument(thumb, document), null, "webp", null, set);
|
||||
object = sticker;
|
||||
}
|
||||
ImageLocation imageLocation;
|
||||
|
||||
if (object instanceof TLRPC.Document) {
|
||||
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90);
|
||||
imageLocation = ImageLocation.getForDocument(thumb, sticker);
|
||||
} else {
|
||||
TLRPC.PhotoSize thumb = (TLRPC.PhotoSize) object;
|
||||
imageLocation = ImageLocation.getForSticker(thumb, sticker);
|
||||
}
|
||||
|
||||
if (object instanceof TLRPC.Document && MessageObject.isAnimatedStickerDocument(sticker)) {
|
||||
imageView.setImage(ImageLocation.getForDocument(sticker), "50_50", imageLocation, null, 0, set);
|
||||
} else if (imageLocation != null && imageLocation.lottieAnimation) {
|
||||
imageView.setImage(imageLocation, "50_50", "tgs", null, set);
|
||||
} else {
|
||||
imageView.setImage(imageLocation, "50_50", "webp", null, set);
|
||||
}
|
||||
} else {
|
||||
imageView.setImage(null, null, "webp", null, set);
|
||||
|
|
|
@ -133,7 +133,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
default void didPressReplyMessage(ChatMessageCell cell, int id) {
|
||||
}
|
||||
|
||||
default void didPressUrl(MessageObject messageObject, CharacterStyle url, boolean longPress) {
|
||||
default void didPressUrl(ChatMessageCell cell, CharacterStyle url, boolean longPress) {
|
||||
}
|
||||
|
||||
default void needOpenWebView(String url, String title, String description, String originalUrl, int w, int h) {
|
||||
|
@ -157,8 +157,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
default void didPressInstantButton(ChatMessageCell cell, int type) {
|
||||
}
|
||||
|
||||
default boolean isChatAdminCell(int uid) {
|
||||
return false;
|
||||
default String getAdminRank(int uid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
default boolean needPlayMessage(MessageObject messageObject) {
|
||||
|
@ -174,6 +174,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
|
||||
default void didStartVideoStream(MessageObject message) {
|
||||
}
|
||||
|
||||
default boolean shouldRepeatSticker(MessageObject message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
default void setShouldNotRepeatSticker(MessageObject message) {
|
||||
}
|
||||
}
|
||||
|
||||
private final static int DOCUMENT_ATTACH_TYPE_NONE = 0;
|
||||
|
@ -751,7 +758,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
return true;
|
||||
} else {
|
||||
if (link[0] == pressedLink) {
|
||||
delegate.didPressUrl(currentMessageObject, pressedLink, false);
|
||||
delegate.didPressUrl(this, pressedLink, false);
|
||||
resetPressedLink(1);
|
||||
return true;
|
||||
}
|
||||
|
@ -817,7 +824,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
FileLog.e(e);
|
||||
}
|
||||
} else if (pressedLinkType == 3) {
|
||||
delegate.didPressUrl(currentMessageObject, pressedLink, false);
|
||||
delegate.didPressUrl(this, pressedLink, false);
|
||||
resetPressedLink(3);
|
||||
return true;
|
||||
}
|
||||
|
@ -1256,7 +1263,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
imagePressed = true;
|
||||
result = true;
|
||||
}
|
||||
} else if (!currentMessageObject.isAnyKindOfSticker() || currentMessageObject.getInputStickerSet() != null) {
|
||||
} else if (!currentMessageObject.isAnyKindOfSticker() || currentMessageObject.getInputStickerSet() != null || currentMessageObject.isAnimatedEmoji()) {
|
||||
if (x >= photoImage.getImageX() && x <= photoImage.getImageX() + photoImage.getImageWidth() && y >= photoImage.getImageY() && y <= photoImage.getImageY() + photoImage.getImageHeight()) {
|
||||
imagePressed = true;
|
||||
result = true;
|
||||
|
@ -1652,7 +1659,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
}
|
||||
|
||||
if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) {
|
||||
if (PhotoViewer.isPlayingMessage(currentMessageObject) || MediaController.getInstance().isGoingToShowMessageObject(currentMessageObject)) {
|
||||
if (infoLayout != null && (PhotoViewer.isPlayingMessage(currentMessageObject) || MediaController.getInstance().isGoingToShowMessageObject(currentMessageObject))) {
|
||||
return;
|
||||
}
|
||||
int duration = 0;
|
||||
|
@ -2973,6 +2980,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1);
|
||||
}
|
||||
} else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) {
|
||||
boolean isWebpSticker = messageObject.isSticker();
|
||||
if (SharedConfig.loopStickers || isWebpSticker) {
|
||||
photoImage.setAutoRepeat(1);
|
||||
} else {
|
||||
currentPhotoFilter = String.format(Locale.US, "%d_%d_nr_%s", width, height, messageObject.toString());
|
||||
photoImage.setAutoRepeat(delegate.shouldRepeatSticker(messageObject) ? 2 : 3);
|
||||
}
|
||||
photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, documentAttach), "b1", documentAttach.size, "webp", messageObject, 1);
|
||||
} else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) {
|
||||
photoImage.setNeedsQualityThumb(true);
|
||||
|
@ -3618,14 +3632,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
} else if (messageObject.isAnyKindOfSticker()) { //sticker
|
||||
drawBackground = false;
|
||||
boolean isWebpSticker = messageObject.type == MessageObject.TYPE_STICKER;
|
||||
for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = messageObject.messageOwner.media.document.attributes.get(a);
|
||||
for (int a = 0; a < messageObject.getDocument().attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = messageObject.getDocument().attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeImageSize) {
|
||||
photoWidth = attribute.w;
|
||||
photoHeight = attribute.h;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (photoWidth == 0 && photoHeight == 0 && messageObject.isAnimatedSticker()) {
|
||||
if (messageObject.isAnimatedSticker() && photoWidth == 0 && photoHeight == 0) {
|
||||
photoWidth = photoHeight = 512;
|
||||
}
|
||||
float maxHeight;
|
||||
|
@ -3635,15 +3650,34 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
} else {
|
||||
maxHeight = maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f;
|
||||
}
|
||||
if (photoWidth == 0) {
|
||||
photoHeight = (int) maxHeight;
|
||||
photoWidth = photoHeight + AndroidUtilities.dp(100);
|
||||
String filter;
|
||||
if (messageObject.isAnimatedEmoji()) {
|
||||
float zoom = MessagesController.getInstance(currentAccount).animatedEmojisZoom;
|
||||
photoWidth = (int) ((photoWidth / 512.0f) * maxWidth * zoom);
|
||||
photoHeight = (int) ((photoHeight / 512.0f) * maxHeight * zoom);
|
||||
} else {
|
||||
if (photoWidth == 0) {
|
||||
photoHeight = (int) maxHeight;
|
||||
photoWidth = photoHeight + AndroidUtilities.dp(100);
|
||||
}
|
||||
photoHeight *= maxWidth / photoWidth;
|
||||
photoWidth = (int) maxWidth;
|
||||
if (photoHeight > maxHeight) {
|
||||
photoWidth *= maxHeight / photoHeight;
|
||||
photoHeight = (int) maxHeight;
|
||||
}
|
||||
}
|
||||
photoHeight *= maxWidth / photoWidth;
|
||||
photoWidth = (int) maxWidth;
|
||||
if (photoHeight > maxHeight) {
|
||||
photoWidth *= maxHeight / photoHeight;
|
||||
photoHeight = (int) maxHeight;
|
||||
Object parentObject = messageObject;
|
||||
if (messageObject.isAnimatedEmoji()) {
|
||||
filter = String.format(Locale.US, "%d_%d_nr_%s" + messageObject.emojiAnimatedStickerColor, photoWidth, photoHeight, messageObject.toString());
|
||||
photoImage.setAutoRepeat(delegate.shouldRepeatSticker(messageObject) ? 2 : 3);
|
||||
parentObject = MessageObject.getInputStickerSet(messageObject.emojiAnimatedSticker);
|
||||
} else if (SharedConfig.loopStickers || isWebpSticker) {
|
||||
filter = String.format(Locale.US, "%d_%d", photoWidth, photoHeight);
|
||||
photoImage.setAutoRepeat(1);
|
||||
} else {
|
||||
filter = String.format(Locale.US, "%d_%d_nr_%s", photoWidth, photoHeight, messageObject.toString());
|
||||
photoImage.setAutoRepeat(delegate.shouldRepeatSticker(messageObject) ? 2 : 3);
|
||||
}
|
||||
documentAttachType = DOCUMENT_ATTACH_TYPE_STICKER;
|
||||
availableTimeWidth = photoWidth - AndroidUtilities.dp(14);
|
||||
|
@ -3652,13 +3686,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40);
|
||||
photoParentObject = messageObject.photoThumbsObject;
|
||||
if (messageObject.attachPathExists) {
|
||||
photoImage.setImage(ImageLocation.getForPath(messageObject.messageOwner.attachPath), String.format(Locale.US, "%d_%d", photoWidth, photoHeight),
|
||||
photoImage.setImage(ImageLocation.getForPath(messageObject.messageOwner.attachPath), filter,
|
||||
ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), "b1",
|
||||
messageObject.messageOwner.media.document.size, isWebpSticker ? "webp" : null, messageObject, 1);
|
||||
} else if (messageObject.messageOwner.media.document.id != 0) {
|
||||
photoImage.setImage(ImageLocation.getForDocument(messageObject.messageOwner.media.document), String.format(Locale.US, "%d_%d", photoWidth, photoHeight),
|
||||
messageObject.getDocument().size, isWebpSticker ? "webp" : null, parentObject, 1);
|
||||
} else if (messageObject.getDocument().id != 0) {
|
||||
photoImage.setImage(ImageLocation.getForDocument(messageObject.getDocument()), filter,
|
||||
ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), "b1",
|
||||
messageObject.messageOwner.media.document.size, isWebpSticker ? "webp" : null, messageObject, 1);
|
||||
messageObject.getDocument().size, isWebpSticker ? "webp" : null, parentObject, 1);
|
||||
}
|
||||
} else {
|
||||
currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize());
|
||||
|
@ -3780,8 +3814,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
}
|
||||
|
||||
if ((w == 0 || h == 0) && messageObject.type == 8) {
|
||||
for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = messageObject.messageOwner.media.document.attributes.get(a);
|
||||
for (int a = 0; a < messageObject.getDocument().attributes.size(); a++) {
|
||||
TLRPC.DocumentAttribute attribute = messageObject.getDocument().attributes.get(a);
|
||||
if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) {
|
||||
float scale = (float) attribute.w / (float) photoWidth;
|
||||
w = (int) (attribute.w / scale);
|
||||
|
@ -4068,8 +4102,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
if (autoPlayingMedia) {
|
||||
photoImage.setAllowStartAnimation(true);
|
||||
photoImage.startAnimation();
|
||||
TLRPC.Document document = messageObject.messageOwner.media.document;
|
||||
photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, null, messageObject.messageOwner.media.document.size, null, messageObject, 0);
|
||||
TLRPC.Document document = messageObject.getDocument();
|
||||
photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, null, messageObject.getDocument().size, null, messageObject, 0);
|
||||
} else if (messageObject.type == 1) {
|
||||
if (messageObject.useCustomPhoto) {
|
||||
photoImage.setImageBitmap(getResources().getDrawable(R.drawable.theme_preview_image));
|
||||
|
@ -4097,7 +4131,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
}
|
||||
}
|
||||
} else if (messageObject.type == 8 || messageObject.type == MessageObject.TYPE_ROUND_VIDEO) {
|
||||
String fileName = FileLoader.getAttachFileName(messageObject.messageOwner.media.document);
|
||||
String fileName = FileLoader.getAttachFileName(messageObject.getDocument());
|
||||
int localFile = 0;
|
||||
if (messageObject.attachPathExists) {
|
||||
DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
|
||||
|
@ -4106,17 +4140,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
localFile = 2;
|
||||
}
|
||||
boolean autoDownload = false;
|
||||
if (MessageObject.isGifDocument(messageObject.messageOwner.media.document) || messageObject.type == MessageObject.TYPE_ROUND_VIDEO) {
|
||||
if (MessageObject.isGifDocument(messageObject.getDocument()) || messageObject.type == MessageObject.TYPE_ROUND_VIDEO) {
|
||||
autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject);
|
||||
}
|
||||
if (!messageObject.isSending() && !messageObject.isEditing() && (localFile != 0 || FileLoader.getInstance(currentAccount).isLoadingFile(fileName) || autoDownload)) {
|
||||
if (localFile != 1 && !messageObject.needDrawBluredPreview() && (localFile != 0 || messageObject.canStreamVideo() && autoDownload)) {
|
||||
autoPlayingMedia = true;
|
||||
photoImage.setImage(ImageLocation.getForDocument(messageObject.messageOwner.media.document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, messageObject.messageOwner.media.document.size, null, messageObject, 0);
|
||||
photoImage.setImage(ImageLocation.getForDocument(messageObject.getDocument()), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, messageObject.getDocument().size, null, messageObject, 0);
|
||||
} else if (localFile == 1) {
|
||||
photoImage.setImage(ImageLocation.getForPath(messageObject.isSendError() ? null : messageObject.messageOwner.attachPath), null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0);
|
||||
} else {
|
||||
photoImage.setImage(ImageLocation.getForDocument(messageObject.messageOwner.media.document), null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, messageObject.messageOwner.media.document.size, null, messageObject, 0);
|
||||
photoImage.setImage(ImageLocation.getForDocument(messageObject.getDocument()), null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, null, messageObject.getDocument().size, null, messageObject, 0);
|
||||
}
|
||||
} else {
|
||||
photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0);
|
||||
|
@ -4423,16 +4457,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
@Override
|
||||
protected void onLongPress() {
|
||||
if (pressedLink instanceof URLSpanMono) {
|
||||
delegate.didPressUrl(currentMessageObject, pressedLink, true);
|
||||
delegate.didPressUrl(this, pressedLink, true);
|
||||
return;
|
||||
} else if (pressedLink instanceof URLSpanNoUnderline) {
|
||||
URLSpanNoUnderline url = (URLSpanNoUnderline) pressedLink;
|
||||
if (url.getURL().startsWith("/")) {
|
||||
delegate.didPressUrl(currentMessageObject, pressedLink, true);
|
||||
delegate.didPressUrl(this, pressedLink, true);
|
||||
return;
|
||||
}
|
||||
} else if (pressedLink instanceof URLSpan) {
|
||||
delegate.didPressUrl(currentMessageObject, pressedLink, true);
|
||||
delegate.didPressUrl(this, pressedLink, true);
|
||||
return;
|
||||
}
|
||||
resetPressedLink(-1);
|
||||
|
@ -4591,7 +4625,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
if (messageObject.type == 0) {
|
||||
documentAttach = messageObject.messageOwner.media.webpage.document;
|
||||
} else {
|
||||
documentAttach = messageObject.messageOwner.media.document;
|
||||
documentAttach = messageObject.getDocument();
|
||||
}
|
||||
if (documentAttach == null) {
|
||||
return 0;
|
||||
|
@ -4701,7 +4735,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
if (infoWidth < 0) {
|
||||
infoWidth = AndroidUtilities.dp(10);
|
||||
}
|
||||
infoLayout = new StaticLayout(str2, Theme.chat_infoPaint, infoWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
infoLayout = new StaticLayout(str2, Theme.chat_infoPaint, infoWidth + AndroidUtilities.dp(6), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
|
||||
} catch (Exception e) {
|
||||
FileLog.e(e);
|
||||
}
|
||||
|
@ -5510,7 +5544,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
imageDrawn = photoImage.draw(canvas);
|
||||
}
|
||||
}
|
||||
if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) {
|
||||
if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) {
|
||||
videoButtonX = photoImage.getImageX() + AndroidUtilities.dp(8);
|
||||
videoButtonY = photoImage.getImageY() + AndroidUtilities.dp(8);
|
||||
videoRadialProgress.setProgressRect(videoButtonX, videoButtonY, videoButtonX + AndroidUtilities.dp(24), videoButtonY + AndroidUtilities.dp(24));
|
||||
|
@ -6007,7 +6041,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
int x = button.x + button.width - AndroidUtilities.dp(9 + 3) + addX;
|
||||
rect.set(x, y + AndroidUtilities.dp(4), x + AndroidUtilities.dp(8), y + AndroidUtilities.dp(8 + 4));
|
||||
canvas.drawArc(rect, button.angle, 220, false, Theme.chat_botProgressPaint);
|
||||
invalidate((int) rect.left - AndroidUtilities.dp(2), (int) rect.top - AndroidUtilities.dp(2), (int) rect.right + AndroidUtilities.dp(2), (int) rect.bottom + AndroidUtilities.dp(2));
|
||||
invalidate();
|
||||
long newTime = System.currentTimeMillis();
|
||||
if (Math.abs(button.lastUpdateTime - System.currentTimeMillis()) < 1000) {
|
||||
long delta = (newTime - button.lastUpdateTime);
|
||||
|
@ -6556,7 +6590,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
photoImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForObject(thumb, document), thumbFilter, document.size, null, currentMessageObject, 0);
|
||||
}
|
||||
} else if (currentMessageObject.type == 9) {
|
||||
FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 0, 0);
|
||||
FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 1, 0);
|
||||
} else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) {
|
||||
FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 1, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0);
|
||||
} else if (currentMessageObject.type == 0 && documentAttachType != DOCUMENT_ATTACH_TYPE_NONE) {
|
||||
|
@ -6603,7 +6637,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
ImageLoader.getInstance().cancelForceLoadingForImageReceiver(photoImage);
|
||||
photoImage.cancelLoadImage();
|
||||
} else if (currentMessageObject.type == 9) {
|
||||
FileLoader.getInstance(currentAccount).cancelLoadFile(currentMessageObject.messageOwner.media.document);
|
||||
FileLoader.getInstance(currentAccount).cancelLoadFile(currentMessageObject.getDocument());
|
||||
}
|
||||
buttonState = 0;
|
||||
if (video) {
|
||||
|
@ -6733,6 +6767,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationReady(ImageReceiver imageReceiver) {
|
||||
if (currentMessageObject != null && imageReceiver == photoImage && currentMessageObject.isAnimatedSticker()) {
|
||||
delegate.setShouldNotRepeatSticker(currentMessageObject);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressDownload(String fileName, float progress) {
|
||||
if (drawVideoImageButton) {
|
||||
|
@ -7004,12 +7045,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
}
|
||||
int adminWidth;
|
||||
String adminString;
|
||||
String adminLabel;
|
||||
if (isMegagroup && currentChat != null && currentMessageObject.isForwardedChannelPost()) {
|
||||
adminString = LocaleController.getString("DiscussChannel", R.string.DiscussChannel);
|
||||
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
|
||||
nameWidth -= adminWidth;
|
||||
} else if (currentUser != null && !currentMessageObject.isOutOwner() && !currentMessageObject.isAnyKindOfSticker() && currentMessageObject.type != 5 && delegate.isChatAdminCell(currentUser.id)) {
|
||||
adminString = LocaleController.getString("ChatAdmin", R.string.ChatAdmin);
|
||||
} else if (currentUser != null && !currentMessageObject.isOutOwner() && !currentMessageObject.isAnyKindOfSticker() && currentMessageObject.type != 5 && (adminLabel = delegate.getAdminRank(currentUser.id)) != null) {
|
||||
if (adminLabel.length() == 0) {
|
||||
adminLabel = LocaleController.getString("ChatAdmin", R.string.ChatAdmin);
|
||||
}
|
||||
adminString = adminLabel;
|
||||
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
|
||||
nameWidth -= adminWidth;
|
||||
} else {
|
||||
|
@ -7838,13 +7883,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
|
||||
public void setCheckBoxVisible(boolean visible, boolean animated) {
|
||||
if (visible && checkBox == null) {
|
||||
checkBox = new CheckBoxBase(this);
|
||||
checkBox = new CheckBoxBase(this, 21);
|
||||
if (attachedToWindow) {
|
||||
checkBox.onAttachedToWindow();
|
||||
}
|
||||
}
|
||||
if (visible && photoCheckBox == null && currentMessagesGroup != null && currentMessagesGroup.messages.size() > 1) {
|
||||
photoCheckBox = new CheckBoxBase(this);
|
||||
photoCheckBox = new CheckBoxBase(this, 21);
|
||||
photoCheckBox.setUseDefaultCheck(true);
|
||||
if (attachedToWindow) {
|
||||
photoCheckBox.onAttachedToWindow();
|
||||
|
@ -9002,7 +9047,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
if (virtualViewId >= LINK_IDS_START) {
|
||||
ClickableSpan link = getLinkById(virtualViewId);
|
||||
if (link != null) {
|
||||
delegate.didPressUrl(currentMessageObject, link, false);
|
||||
delegate.didPressUrl(ChatMessageCell.this, link, false);
|
||||
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||
}
|
||||
} else if (virtualViewId >= BOT_BUTTONS_START) {
|
||||
|
@ -9041,7 +9086,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
|||
} else if (action == AccessibilityNodeInfo.ACTION_LONG_CLICK) {
|
||||
ClickableSpan link = getLinkById(virtualViewId);
|
||||
if (link != null) {
|
||||
delegate.didPressUrl(currentMessageObject, link, true);
|
||||
delegate.didPressUrl(ChatMessageCell.this, link, true);
|
||||
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -637,6 +637,11 @@ public class ContextLinkCell extends View implements DownloadController.FileDown
|
|||
}
|
||||
|
||||
if (!mediaWebpage) {
|
||||
if (drawLinkImageView && !PhotoViewer.isShowingImage(inlineResult)) {
|
||||
letterDrawable.setAlpha((int) (255 * (1.0f - linkImageView.getCurrentAlpha())));
|
||||
} else {
|
||||
letterDrawable.setAlpha(255);
|
||||
}
|
||||
if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) {
|
||||
radialProgress.setProgressColor(Theme.getColor(buttonPressed ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress));
|
||||
radialProgress.draw(canvas);
|
||||
|
|
|
@ -216,9 +216,8 @@ public class DialogCell extends BaseCell {
|
|||
useForceThreeLines = forceThreeLines;
|
||||
|
||||
if (needCheck) {
|
||||
checkBox = new CheckBox2(context);
|
||||
checkBox = new CheckBox2(context, 21);
|
||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||
checkBox.setSize(21);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
checkBox.setDrawBackgroundAsArc(3);
|
||||
addView(checkBox);
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.telegram.messenger.LocaleController;
|
|||
import org.telegram.messenger.MessageObject;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.messenger.UserConfig;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
|
@ -228,21 +229,38 @@ public class FeaturedStickerSetCell extends FrameLayout {
|
|||
}
|
||||
|
||||
valueTextView.setText(LocaleController.formatPluralString("Stickers", set.set.count));
|
||||
TLRPC.PhotoSize thumb = set.cover != null ? FileLoader.getClosestPhotoSizeWithSize(set.cover.thumbs, 90) : null;
|
||||
|
||||
if (thumb != null && thumb.location != null) {
|
||||
if (MessageObject.canAutoplayAnimatedSticker(set.cover)) {
|
||||
imageView.setImage(ImageLocation.getForDocument(set.cover), "80_80", ImageLocation.getForDocument(thumb, set.cover), null, 0, set);
|
||||
} else {
|
||||
imageView.setImage(ImageLocation.getForDocument(thumb, set.cover), null, "webp", null, set);
|
||||
}
|
||||
TLRPC.Document sticker;
|
||||
if (set.cover != null) {
|
||||
sticker = set.cover;
|
||||
} else if (!set.covers.isEmpty()) {
|
||||
TLRPC.Document document = set.covers.get(0);
|
||||
thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
|
||||
if (MessageObject.canAutoplayAnimatedSticker(document)) {
|
||||
imageView.setImage(ImageLocation.getForDocument(document), "80_80", ImageLocation.getForDocument(thumb, document), null, 0, set);
|
||||
sticker = set.covers.get(0);
|
||||
} else {
|
||||
sticker = null;
|
||||
}
|
||||
if (sticker != null) {
|
||||
TLObject object;
|
||||
if (set.set.thumb instanceof TLRPC.TL_photoSize) {
|
||||
object = set.set.thumb;
|
||||
} else {
|
||||
imageView.setImage(ImageLocation.getForDocument(thumb, document), null, "webp", null, set);
|
||||
object = sticker;
|
||||
}
|
||||
ImageLocation imageLocation;
|
||||
|
||||
if (object instanceof TLRPC.Document) {
|
||||
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90);
|
||||
imageLocation = ImageLocation.getForDocument(thumb, sticker);
|
||||
} else {
|
||||
TLRPC.PhotoSize thumb = (TLRPC.PhotoSize) object;
|
||||
imageLocation = ImageLocation.getForSticker(thumb, sticker);
|
||||
}
|
||||
|
||||
if (object instanceof TLRPC.Document && MessageObject.isAnimatedStickerDocument(sticker)) {
|
||||
imageView.setImage(ImageLocation.getForDocument(sticker), "50_50", imageLocation, null, 0, set);
|
||||
} else if (imageLocation != null && imageLocation.lottieAnimation) {
|
||||
imageView.setImage(imageLocation, "50_50", "tgs", null, set);
|
||||
} else {
|
||||
imageView.setImage(imageLocation, "50_50", "webp", null, set);
|
||||
}
|
||||
} else {
|
||||
imageView.setImage(null, null, "webp", null, set);
|
||||
|
|
|
@ -68,9 +68,8 @@ public class GroupCreateUserCell extends FrameLayout {
|
|||
addView(statusTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 28 : 72) + padding, 32, (LocaleController.isRTL ? 72 : 28) + padding, 0));
|
||||
|
||||
if (needCheck) {
|
||||
checkBox = new CheckBox2(context);
|
||||
checkBox = new CheckBox2(context, 21);
|
||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||
checkBox.setSize(21);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
checkBox.setDrawBackgroundAsArc(3);
|
||||
addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 40, 33, LocaleController.isRTL ? 39 : 0, 0));
|
||||
|
|
|
@ -53,9 +53,8 @@ public class InviteUserCell extends FrameLayout {
|
|||
addView(statusTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 28 : 72, 39, LocaleController.isRTL ? 72 : 28, 0));
|
||||
|
||||
if (needCheck) {
|
||||
checkBox = new CheckBox2(context);
|
||||
checkBox = new CheckBox2(context, 21);
|
||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||
checkBox.setSize(21);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
checkBox.setDrawBackgroundAsArc(3);
|
||||
addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 40, 40, LocaleController.isRTL ? 39 : 0, 0));
|
||||
|
|
|
@ -10,35 +10,59 @@ package org.telegram.ui.Cells;
|
|||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.ApplicationLoader;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public class PhotoAttachCameraCell extends FrameLayout {
|
||||
|
||||
private ImageView imageView;
|
||||
private ImageView backgroundView;
|
||||
private int itemSize;
|
||||
|
||||
public PhotoAttachCameraCell(Context context) {
|
||||
super(context);
|
||||
|
||||
backgroundView = new ImageView(context);
|
||||
backgroundView.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
//backgroundView.setAdjustViewBounds(false);
|
||||
addView(backgroundView, LayoutHelper.createFrame(80, 80));
|
||||
|
||||
imageView = new ImageView(context);
|
||||
imageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||
imageView.setImageResource(R.drawable.instant_camera);
|
||||
imageView.setBackgroundColor(0xff000000);
|
||||
addView(imageView, LayoutHelper.createFrame(80, 80));
|
||||
setFocusable(true);
|
||||
|
||||
itemSize = AndroidUtilities.dp(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(86), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), MeasureSpec.EXACTLY));
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(itemSize + AndroidUtilities.dp(5), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemSize + AndroidUtilities.dp(5), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setItemSize(int size) {
|
||||
itemSize = size;
|
||||
|
||||
LayoutParams layoutParams = (LayoutParams) imageView.getLayoutParams();
|
||||
layoutParams.width = layoutParams.height = itemSize;
|
||||
|
||||
layoutParams = (LayoutParams) backgroundView.getLayoutParams();
|
||||
layoutParams.width = layoutParams.height = itemSize;
|
||||
}
|
||||
|
||||
public ImageView getImageView() {
|
||||
|
@ -50,4 +74,19 @@ public class PhotoAttachCameraCell extends FrameLayout {
|
|||
super.onAttachedToWindow();
|
||||
imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogCameraIcon), PorterDuff.Mode.MULTIPLY));
|
||||
}
|
||||
|
||||
public void updateBitmap() {
|
||||
Bitmap bitmap = null;
|
||||
try {
|
||||
File file = new File(ApplicationLoader.getFilesDirFixed(), "cthumb.jpg");
|
||||
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
|
||||
} catch (Throwable ignore) {
|
||||
|
||||
}
|
||||
if (bitmap != null) {
|
||||
backgroundView.setImageBitmap(bitmap);
|
||||
} else {
|
||||
backgroundView.setImageResource(R.drawable.icplaceholder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 5.x.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package org.telegram.ui.Cells;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
public class PhotoAttachPermissionCell extends FrameLayout {
|
||||
|
||||
private ImageView imageView;
|
||||
private ImageView imageView2;
|
||||
private TextView textView;
|
||||
private int itemSize;
|
||||
|
||||
public PhotoAttachPermissionCell(Context context) {
|
||||
super(context);
|
||||
|
||||
imageView = new ImageView(context);
|
||||
imageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||
imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_attachPermissionImage), PorterDuff.Mode.MULTIPLY));
|
||||
addView(imageView, LayoutHelper.createFrame(44, 44, Gravity.CENTER, 5, 0, 0, 27));
|
||||
|
||||
imageView2 = new ImageView(context);
|
||||
imageView2.setScaleType(ImageView.ScaleType.CENTER);
|
||||
imageView2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_attachPermissionMark), PorterDuff.Mode.MULTIPLY));
|
||||
addView(imageView2, LayoutHelper.createFrame(44, 44, Gravity.CENTER, 5, 0, 0, 27));
|
||||
|
||||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_chat_attachPermissionText));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
|
||||
textView.setGravity(Gravity.CENTER);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 5, 13, 5, 0));
|
||||
|
||||
itemSize = AndroidUtilities.dp(80);
|
||||
}
|
||||
|
||||
public void setItemSize(int size) {
|
||||
itemSize = size;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
if (type == 0) {
|
||||
imageView.setImageResource(R.drawable.permissions_camera1);
|
||||
imageView2.setImageResource(R.drawable.permissions_camera2);
|
||||
textView.setText(LocaleController.getString("CameraPermissionText", R.string.CameraPermissionText));
|
||||
|
||||
imageView.setLayoutParams(LayoutHelper.createFrame(44, 44, Gravity.CENTER, 5, 0, 0, 27));
|
||||
imageView2.setLayoutParams(LayoutHelper.createFrame(44, 44, Gravity.CENTER, 5, 0, 0, 27));
|
||||
} else {
|
||||
imageView.setImageResource(R.drawable.permissions_gallery1);
|
||||
imageView2.setImageResource(R.drawable.permissions_gallery2);
|
||||
textView.setText(LocaleController.getString("GalleryPermissionText", R.string.GalleryPermissionText));
|
||||
|
||||
imageView.setLayoutParams(LayoutHelper.createFrame(44, 44, Gravity.CENTER, 0, 0, 2, 27));
|
||||
imageView2.setLayoutParams(LayoutHelper.createFrame(44, 44, Gravity.CENTER, 0, 0, 2, 27));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(itemSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemSize + AndroidUtilities.dp(5), MeasureSpec.EXACTLY));
|
||||
}
|
||||
}
|
|
@ -13,7 +13,10 @@ import android.animation.AnimatorListenerAdapter;
|
|||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
|
@ -33,16 +36,18 @@ import org.telegram.messenger.AndroidUtilities;
|
|||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MediaController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.CheckBox;
|
||||
import org.telegram.ui.Components.CheckBox2;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.PhotoViewer;
|
||||
|
||||
public class PhotoAttachPhotoCell extends FrameLayout {
|
||||
|
||||
private BackupImageView imageView;
|
||||
private FrameLayout container;
|
||||
private FrameLayout checkFrame;
|
||||
private CheckBox checkBox;
|
||||
private CheckBox2 checkBox;
|
||||
private TextView videoTextView;
|
||||
private FrameLayout videoInfoContainer;
|
||||
private AnimatorSet animatorSet;
|
||||
|
@ -50,8 +55,13 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
private boolean pressed;
|
||||
private static Rect rect = new Rect();
|
||||
private PhotoAttachPhotoCellDelegate delegate;
|
||||
private boolean isVertical;
|
||||
private boolean itemSizeChanged;
|
||||
private boolean needCheckShow;
|
||||
private int itemSize;
|
||||
private boolean isVertical;
|
||||
|
||||
private Paint backgroundPaint = new Paint();
|
||||
private AnimatorSet animator;
|
||||
|
||||
public interface PhotoAttachPhotoCellDelegate {
|
||||
void onCheckClick(PhotoAttachPhotoCell v);
|
||||
|
@ -62,46 +72,85 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
public PhotoAttachPhotoCell(Context context) {
|
||||
super(context);
|
||||
|
||||
imageView = new BackupImageView(context);
|
||||
addView(imageView, LayoutHelper.createFrame(80, 80));
|
||||
checkFrame = new FrameLayout(context);
|
||||
addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.LEFT | Gravity.TOP, 38, 0, 0, 0));
|
||||
setWillNotDraw(false);
|
||||
|
||||
videoInfoContainer = new FrameLayout(context);
|
||||
videoInfoContainer.setBackgroundResource(R.drawable.phototime);
|
||||
videoInfoContainer.setPadding(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(3), 0);
|
||||
addView(videoInfoContainer, LayoutHelper.createFrame(80, 16, Gravity.BOTTOM | Gravity.LEFT));
|
||||
container = new FrameLayout(context);
|
||||
addView(container, LayoutHelper.createFrame(80, 80));
|
||||
|
||||
imageView = new BackupImageView(context);
|
||||
container.addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
videoInfoContainer = new FrameLayout(context) {
|
||||
|
||||
private RectF rect = new RectF();
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
|
||||
canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_timeBackgroundPaint);
|
||||
}
|
||||
};
|
||||
videoInfoContainer.setWillNotDraw(false);
|
||||
videoInfoContainer.setPadding(AndroidUtilities.dp(5), 0, AndroidUtilities.dp(5), 0);
|
||||
container.addView(videoInfoContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 17, Gravity.BOTTOM | Gravity.LEFT, 4, 0, 0, 4));
|
||||
|
||||
ImageView imageView1 = new ImageView(context);
|
||||
imageView1.setImageResource(R.drawable.ic_video);
|
||||
imageView1.setImageResource(R.drawable.play_mini_video);
|
||||
videoInfoContainer.addView(imageView1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL));
|
||||
|
||||
videoTextView = new TextView(context);
|
||||
videoTextView.setTextColor(0xffffffff);
|
||||
videoTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
videoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
|
||||
videoTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
videoInfoContainer.addView(videoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 18, -0.7f, 0, 0));
|
||||
videoInfoContainer.addView(videoTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 13, -0.7f, 0, 0));
|
||||
|
||||
checkBox = new CheckBox(context, R.drawable.checkbig);
|
||||
checkBox.setSize(30);
|
||||
checkBox.setCheckOffset(AndroidUtilities.dp(1));
|
||||
checkBox.setDrawBackground(true);
|
||||
checkBox.setColor(0xff3ccaef, 0xffffffff);
|
||||
addView(checkBox, LayoutHelper.createFrame(30, 30, Gravity.LEFT | Gravity.TOP, 46, 4, 0, 0));
|
||||
checkBox = new CheckBox2(context, 24);
|
||||
checkBox.setDrawBackgroundAsArc(7);
|
||||
checkBox.setColor(Theme.key_chat_attachCheckBoxBackground, Theme.key_chat_attachPhotoBackground, Theme.key_chat_attachCheckBoxCheck);
|
||||
addView(checkBox, LayoutHelper.createFrame(26, 26, Gravity.LEFT | Gravity.TOP, 52, 4, 0, 0));
|
||||
checkBox.setVisibility(VISIBLE);
|
||||
setFocusable(true);
|
||||
|
||||
checkFrame = new FrameLayout(context);
|
||||
addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.LEFT | Gravity.TOP, 38, 0, 0, 0));
|
||||
|
||||
itemSize = AndroidUtilities.dp(80);
|
||||
}
|
||||
|
||||
public void setIsVertical(boolean value) {
|
||||
isVertical = value;
|
||||
}
|
||||
|
||||
public void setItemSize(int size) {
|
||||
itemSize = size;
|
||||
|
||||
LayoutParams layoutParams = (LayoutParams) container.getLayoutParams();
|
||||
layoutParams.width = layoutParams.height = itemSize;
|
||||
|
||||
layoutParams = (LayoutParams) checkFrame.getLayoutParams();
|
||||
layoutParams.gravity = Gravity.RIGHT | Gravity.TOP;
|
||||
layoutParams.leftMargin = 0;
|
||||
|
||||
layoutParams = (LayoutParams) checkBox.getLayoutParams();
|
||||
layoutParams.gravity = Gravity.RIGHT | Gravity.TOP;
|
||||
layoutParams.leftMargin = 0;
|
||||
layoutParams.rightMargin = layoutParams.topMargin = AndroidUtilities.dp(5);
|
||||
checkBox.setDrawBackgroundAsArc(6);
|
||||
|
||||
itemSizeChanged = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (isVertical) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80 + (isLast ? 0 : 6)), MeasureSpec.EXACTLY));
|
||||
if (itemSizeChanged) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(itemSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemSize + AndroidUtilities.dp(5), MeasureSpec.EXACTLY));
|
||||
} else {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80 + (isLast ? 0 : 6)), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), MeasureSpec.EXACTLY));
|
||||
if (isVertical) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80 + (isLast ? 0 : 6)), MeasureSpec.EXACTLY));
|
||||
} else {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80 + (isLast ? 0 : 6)), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), MeasureSpec.EXACTLY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,7 +162,11 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
return imageView;
|
||||
}
|
||||
|
||||
public CheckBox getCheckBox() {
|
||||
public float getScale() {
|
||||
return container.getScaleX();
|
||||
}
|
||||
|
||||
public CheckBox2 getCheckBox() {
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
|
@ -139,16 +192,16 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
videoInfoContainer.setVisibility(INVISIBLE);
|
||||
}
|
||||
if (photoEntry.thumbPath != null) {
|
||||
imageView.setImage(photoEntry.thumbPath, null, getResources().getDrawable(R.drawable.nophotos));
|
||||
imageView.setImage(photoEntry.thumbPath, null, Theme.chat_attachEmptyDrawable);
|
||||
} else if (photoEntry.path != null) {
|
||||
if (photoEntry.isVideo) {
|
||||
imageView.setImage("vthumb://" + photoEntry.imageId + ":" + photoEntry.path, null, getResources().getDrawable(R.drawable.nophotos));
|
||||
imageView.setImage("vthumb://" + photoEntry.imageId + ":" + photoEntry.path, null, Theme.chat_attachEmptyDrawable);
|
||||
} else {
|
||||
imageView.setOrientation(photoEntry.orientation, true);
|
||||
imageView.setImage("thumb://" + photoEntry.imageId + ":" + photoEntry.path, null, getResources().getDrawable(R.drawable.nophotos));
|
||||
imageView.setImage("thumb://" + photoEntry.imageId + ":" + photoEntry.path, null, Theme.chat_attachEmptyDrawable);
|
||||
}
|
||||
} else {
|
||||
imageView.setImageResource(R.drawable.nophotos);
|
||||
imageView.setImageDrawable(Theme.chat_attachEmptyDrawable);
|
||||
}
|
||||
boolean showing = needCheckShow && PhotoViewer.isShowingImage(photoEntry.path);
|
||||
imageView.getImageReceiver().setVisible(!showing, true);
|
||||
|
@ -157,8 +210,43 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
requestLayout();
|
||||
}
|
||||
|
||||
public void setChecked(int num, boolean value, boolean animated) {
|
||||
checkBox.setChecked(num, value, animated);
|
||||
public void setChecked(int num, boolean checked, boolean animated) {
|
||||
checkBox.setChecked(num, checked, animated);
|
||||
if (itemSizeChanged) {
|
||||
if (animator != null) {
|
||||
animator.cancel();
|
||||
animator = null;
|
||||
}
|
||||
if (animated) {
|
||||
animator = new AnimatorSet();
|
||||
animator.playTogether(
|
||||
ObjectAnimator.ofFloat(container, View.SCALE_X, checked ? 0.787f : 1.0f),
|
||||
ObjectAnimator.ofFloat(container, View.SCALE_Y, checked ? 0.787f : 1.0f));
|
||||
animator.setDuration(200);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (animator != null && animator.equals(animation)) {
|
||||
animator = null;
|
||||
if (!checked) {
|
||||
setBackgroundColor(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
if (animator != null && animator.equals(animation)) {
|
||||
animator = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
} else {
|
||||
container.setScaleX(checked ? 0.787f : 1.0f);
|
||||
container.setScaleY(checked ? 0.787f : 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setNum(int num) {
|
||||
|
@ -193,8 +281,8 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
animatorSet.setInterpolator(new DecelerateInterpolator());
|
||||
animatorSet.setDuration(180);
|
||||
animatorSet.playTogether(
|
||||
ObjectAnimator.ofFloat(videoInfoContainer, "alpha", show ? 1.0f : 0.0f),
|
||||
ObjectAnimator.ofFloat(checkBox, "alpha", show ? 1.0f : 0.0f));
|
||||
ObjectAnimator.ofFloat(videoInfoContainer, View.ALPHA, show ? 1.0f : 0.0f),
|
||||
ObjectAnimator.ofFloat(checkBox, View.ALPHA, show ? 1.0f : 0.0f));
|
||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
|
@ -206,6 +294,18 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
animatorSet.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearAnimation() {
|
||||
super.clearAnimation();
|
||||
if (animator != null) {
|
||||
animator.cancel();
|
||||
animator = null;
|
||||
|
||||
container.setScaleX(checkBox.isChecked() ? 0.787f : 1.0f);
|
||||
container.setScaleY(checkBox.isChecked() ? 0.787f : 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
boolean result = false;
|
||||
|
@ -242,6 +342,14 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (checkBox.isChecked() || container.getScaleX() != 1.0f || !imageView.getImageReceiver().hasNotThumb() || imageView.getImageReceiver().getCurrentAlpha() != 1.0f || PhotoViewer.isShowingImage(photoEntry.path)) {
|
||||
backgroundPaint.setColor(Theme.getColor(Theme.key_chat_attachPhotoBackground));
|
||||
canvas.drawRect(0, 0, imageView.getMeasuredWidth(), imageView.getMeasuredHeight(), backgroundPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
|
@ -251,8 +359,9 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
} else {
|
||||
info.setText(LocaleController.getString("AttachPhoto", R.string.AttachPhoto));
|
||||
}
|
||||
if (checkBox.isChecked())
|
||||
if (checkBox.isChecked()) {
|
||||
info.setSelected(true);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.acc_action_open_photo, LocaleController.getString("Open", R.string.Open)));
|
||||
}
|
||||
|
@ -261,7 +370,7 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
|||
@Override
|
||||
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
||||
if (action == R.id.acc_action_open_photo) {
|
||||
View parent = (View)getParent();
|
||||
View parent = (View) getParent();
|
||||
parent.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, getLeft(), getTop() + getHeight() - 1, 0));
|
||||
parent.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, getLeft(), getTop() + getHeight() - 1, 0));
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
package org.telegram.ui.Cells;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
|
@ -21,7 +23,6 @@ import android.widget.TextView;
|
|||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.MediaController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
@ -36,6 +37,7 @@ public class PhotoPickerAlbumsCell extends FrameLayout {
|
|||
private MediaController.AlbumEntry[] albumEntries;
|
||||
private int albumsCount;
|
||||
private PhotoPickerAlbumsCellDelegate delegate;
|
||||
private Paint backgroundPaint = new Paint();
|
||||
|
||||
private class AlbumView extends FrameLayout {
|
||||
|
||||
|
@ -85,6 +87,14 @@ public class PhotoPickerAlbumsCell extends FrameLayout {
|
|||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (!imageView.getImageReceiver().hasNotThumb() || imageView.getImageReceiver().getCurrentAlpha() != 1.0f) {
|
||||
backgroundPaint.setColor(Theme.getColor(Theme.key_chat_attachPhotoBackground));
|
||||
canvas.drawRect(0, 0, imageView.getMeasuredWidth(), imageView.getMeasuredHeight(), backgroundPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PhotoPickerAlbumsCell(Context context) {
|
||||
|
@ -96,12 +106,9 @@ public class PhotoPickerAlbumsCell extends FrameLayout {
|
|||
addView(albumViews[a]);
|
||||
albumViews[a].setVisibility(INVISIBLE);
|
||||
albumViews[a].setTag(a);
|
||||
albumViews[a].setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (delegate != null) {
|
||||
delegate.didSelectAlbum(albumEntries[(Integer) v.getTag()]);
|
||||
}
|
||||
albumViews[a].setOnClickListener(v -> {
|
||||
if (delegate != null) {
|
||||
delegate.didSelectAlbum(albumEntries[(Integer) v.getTag()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -127,12 +134,12 @@ public class PhotoPickerAlbumsCell extends FrameLayout {
|
|||
if (albumEntry.coverPhoto != null && albumEntry.coverPhoto.path != null) {
|
||||
albumView.imageView.setOrientation(albumEntry.coverPhoto.orientation, true);
|
||||
if (albumEntry.coverPhoto.isVideo) {
|
||||
albumView.imageView.setImage("vthumb://" + albumEntry.coverPhoto.imageId + ":" + albumEntry.coverPhoto.path, null, getContext().getResources().getDrawable(R.drawable.nophotos));
|
||||
albumView.imageView.setImage("vthumb://" + albumEntry.coverPhoto.imageId + ":" + albumEntry.coverPhoto.path, null, Theme.chat_attachEmptyDrawable);
|
||||
} else {
|
||||
albumView.imageView.setImage("thumb://" + albumEntry.coverPhoto.imageId + ":" + albumEntry.coverPhoto.path, null, getContext().getResources().getDrawable(R.drawable.nophotos));
|
||||
albumView.imageView.setImage("thumb://" + albumEntry.coverPhoto.imageId + ":" + albumEntry.coverPhoto.path, null, Theme.chat_attachEmptyDrawable);
|
||||
}
|
||||
} else {
|
||||
albumView.imageView.setImageResource(R.drawable.nophotos);
|
||||
albumView.imageView.setImageDrawable(Theme.chat_attachEmptyDrawable);
|
||||
}
|
||||
albumView.nameTextView.setText(albumEntry.bucketName);
|
||||
albumView.countTextView.setText(String.format("%d", albumEntry.photos.size()));
|
||||
|
|
|
@ -13,9 +13,12 @@ import android.animation.AnimatorListenerAdapter;
|
|||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
@ -24,17 +27,20 @@ import android.widget.TextView;
|
|||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.FileLoader;
|
||||
import org.telegram.messenger.ImageLocation;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MediaController;
|
||||
import org.telegram.messenger.MessageObject;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
import org.telegram.ui.Components.CheckBox;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
import org.telegram.ui.PhotoViewer;
|
||||
|
||||
public class PhotoPickerPhotoCell extends FrameLayout {
|
||||
|
||||
public BackupImageView photoImage;
|
||||
public BackupImageView imageView;
|
||||
public FrameLayout checkFrame;
|
||||
public CheckBox checkBox;
|
||||
public TextView videoTextView;
|
||||
|
@ -43,14 +49,17 @@ public class PhotoPickerPhotoCell extends FrameLayout {
|
|||
private AnimatorSet animatorSet;
|
||||
public int itemWidth;
|
||||
private boolean zoomOnSelect;
|
||||
private Paint backgroundPaint = new Paint();
|
||||
private MediaController.PhotoEntry photoEntry;
|
||||
|
||||
public PhotoPickerPhotoCell(Context context, boolean zoom) {
|
||||
super(context);
|
||||
setWillNotDraw(false);
|
||||
|
||||
zoomOnSelect = zoom;
|
||||
|
||||
photoImage = new BackupImageView(context);
|
||||
addView(photoImage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
imageView = new BackupImageView(context);
|
||||
addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
checkFrame = new FrameLayout(context);
|
||||
addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.RIGHT | Gravity.TOP));
|
||||
|
@ -111,21 +120,45 @@ public class PhotoPickerPhotoCell extends FrameLayout {
|
|||
checkBox.setNum(num);
|
||||
}
|
||||
|
||||
public void setImage(MediaController.PhotoEntry entry) {
|
||||
Drawable thumb = zoomOnSelect ? Theme.chat_attachEmptyDrawable : getResources().getDrawable(R.drawable.nophotos);
|
||||
photoEntry = entry;
|
||||
if (photoEntry.thumbPath != null) {
|
||||
imageView.setImage(photoEntry.thumbPath, null, thumb);
|
||||
} else if (photoEntry.path != null) {
|
||||
imageView.setOrientation(photoEntry.orientation, true);
|
||||
if (photoEntry.isVideo) {
|
||||
videoInfoContainer.setVisibility(View.VISIBLE);
|
||||
int minutes = photoEntry.duration / 60;
|
||||
int seconds = photoEntry.duration - minutes * 60;
|
||||
videoTextView.setText(String.format("%d:%02d", minutes, seconds));
|
||||
setContentDescription(LocaleController.getString("AttachVideo", R.string.AttachVideo) + ", " + LocaleController.formatCallDuration(photoEntry.duration));
|
||||
imageView.setImage("vthumb://" + photoEntry.imageId + ":" + photoEntry.path, null, thumb);
|
||||
} else {
|
||||
videoInfoContainer.setVisibility(View.INVISIBLE);
|
||||
setContentDescription(LocaleController.getString("AttachPhoto", R.string.AttachPhoto));
|
||||
imageView.setImage("thumb://" + photoEntry.imageId + ":" + photoEntry.path, null, thumb);
|
||||
}
|
||||
} else {
|
||||
imageView.setImageDrawable(thumb);
|
||||
}
|
||||
}
|
||||
|
||||
public void setImage(MediaController.SearchImage searchImage) {
|
||||
Drawable thumb = getResources().getDrawable(R.drawable.nophotos);
|
||||
Drawable thumb = zoomOnSelect ? Theme.chat_attachEmptyDrawable : getResources().getDrawable(R.drawable.nophotos);
|
||||
if (searchImage.thumbPhotoSize != null) {
|
||||
photoImage.setImage(ImageLocation.getForPhoto(searchImage.thumbPhotoSize, searchImage.photo), null, thumb, searchImage);
|
||||
imageView.setImage(ImageLocation.getForPhoto(searchImage.thumbPhotoSize, searchImage.photo), null, thumb, searchImage);
|
||||
} else if (searchImage.photoSize != null) {
|
||||
photoImage.setImage(ImageLocation.getForPhoto(searchImage.photoSize, searchImage.photo), "80_80", thumb, searchImage);
|
||||
imageView.setImage(ImageLocation.getForPhoto(searchImage.photoSize, searchImage.photo), "80_80", thumb, searchImage);
|
||||
} else if (searchImage.thumbPath != null) {
|
||||
photoImage.setImage(searchImage.thumbPath, null, thumb);
|
||||
imageView.setImage(searchImage.thumbPath, null, thumb);
|
||||
} else if (searchImage.thumbUrl != null && searchImage.thumbUrl.length() > 0) {
|
||||
photoImage.setImage(searchImage.thumbUrl, null, thumb);
|
||||
imageView.setImage(searchImage.thumbUrl, null, thumb);
|
||||
} else if (MessageObject.isDocumentHasThumb(searchImage.document)) {
|
||||
TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(searchImage.document.thumbs, 320);
|
||||
photoImage.setImage(ImageLocation.getForDocument(photoSize, searchImage.document), null, thumb, searchImage);
|
||||
imageView.setImage(ImageLocation.getForDocument(photoSize, searchImage.document), null, thumb, searchImage);
|
||||
} else {
|
||||
photoImage.setImageDrawable(thumb);
|
||||
imageView.setImageDrawable(thumb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,12 +170,9 @@ public class PhotoPickerPhotoCell extends FrameLayout {
|
|||
}
|
||||
if (zoomOnSelect) {
|
||||
if (animated) {
|
||||
if (checked) {
|
||||
setBackgroundColor(0xff0a0a0a);
|
||||
}
|
||||
animator = new AnimatorSet();
|
||||
animator.playTogether(ObjectAnimator.ofFloat(photoImage, "scaleX", checked ? 0.85f : 1.0f),
|
||||
ObjectAnimator.ofFloat(photoImage, "scaleY", checked ? 0.85f : 1.0f));
|
||||
animator.playTogether(ObjectAnimator.ofFloat(imageView, View.SCALE_X, checked ? 0.85f : 1.0f),
|
||||
ObjectAnimator.ofFloat(imageView, View.SCALE_Y, checked ? 0.85f : 1.0f));
|
||||
animator.setDuration(200);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
|
@ -164,10 +194,20 @@ public class PhotoPickerPhotoCell extends FrameLayout {
|
|||
});
|
||||
animator.start();
|
||||
} else {
|
||||
setBackgroundColor(checked ? 0xff0A0A0A : 0);
|
||||
photoImage.setScaleX(checked ? 0.85f : 1.0f);
|
||||
photoImage.setScaleY(checked ? 0.85f : 1.0f);
|
||||
imageView.setScaleX(checked ? 0.85f : 1.0f);
|
||||
imageView.setScaleY(checked ? 0.85f : 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (!zoomOnSelect) {
|
||||
return;
|
||||
}
|
||||
if (checkBox.isChecked() || imageView.getScaleX() != 1.0f || !imageView.getImageReceiver().hasNotThumb() || imageView.getImageReceiver().getCurrentAlpha() != 1.0f || photoEntry != null && PhotoViewer.isShowingImage(photoEntry.path)) {
|
||||
backgroundPaint.setColor(Theme.getColor(Theme.key_chat_attachPhotoBackground));
|
||||
canvas.drawRect(0, 0, imageView.getMeasuredWidth(), imageView.getMeasuredHeight(), backgroundPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* This is the source code of Telegram for Android v. 2.0.x.
|
||||
* It is licensed under GNU GPL v. 2 or later.
|
||||
* You should have received a copy of the license in this archive (see LICENSE).
|
||||
*
|
||||
* Copyright Nikolai Kudashov, 2013-2018.
|
||||
*/
|
||||
|
||||
package org.telegram.ui.Cells;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.telegram.messenger.AndroidUtilities;
|
||||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.LayoutHelper;
|
||||
|
||||
public class PhotoPickerSearchCell extends LinearLayout {
|
||||
|
||||
public interface PhotoPickerSearchCellDelegate {
|
||||
void didPressedSearchButton(int index);
|
||||
}
|
||||
|
||||
private class SearchButton extends FrameLayout {
|
||||
|
||||
private TextView textView1;
|
||||
private TextView textView2;
|
||||
private ImageView imageView;
|
||||
private View selector;
|
||||
|
||||
public SearchButton(Context context) {
|
||||
super(context);
|
||||
|
||||
setBackgroundColor(0xff1a1a1a);
|
||||
|
||||
selector = new View(context);
|
||||
selector.setBackgroundDrawable(Theme.getSelectorDrawable(false));
|
||||
addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
imageView = new ImageView(context);
|
||||
imageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||
addView(imageView, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
|
||||
|
||||
textView1 = new TextView(context);
|
||||
textView1.setGravity(Gravity.CENTER_VERTICAL);
|
||||
textView1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
|
||||
textView1.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
textView1.setTextColor(0xffffffff);
|
||||
textView1.setSingleLine(true);
|
||||
textView1.setEllipsize(TextUtils.TruncateAt.END);
|
||||
addView(textView1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 51, 8, 4, 0));
|
||||
|
||||
textView2 = new TextView(context);
|
||||
textView2.setGravity(Gravity.CENTER_VERTICAL);
|
||||
textView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 10);
|
||||
textView2.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
textView2.setTextColor(0xff666666);
|
||||
textView2.setSingleLine(true);
|
||||
textView2.setEllipsize(TextUtils.TruncateAt.END);
|
||||
addView(textView2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 51, 26, 4, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
selector.drawableHotspotChanged(event.getX(), event.getY());
|
||||
}
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
private PhotoPickerSearchCellDelegate delegate;
|
||||
|
||||
public PhotoPickerSearchCell(Context context, boolean allowGifs) {
|
||||
super(context);
|
||||
setOrientation(HORIZONTAL);
|
||||
|
||||
SearchButton searchButton = new SearchButton(context);
|
||||
searchButton.textView1.setText(LocaleController.getString("SearchImages", R.string.SearchImages));
|
||||
searchButton.textView2.setText(LocaleController.getString("SearchImagesInfo", R.string.SearchImagesInfo));
|
||||
searchButton.imageView.setImageResource(R.drawable.search_web);
|
||||
addView(searchButton);
|
||||
LayoutParams layoutParams = (LayoutParams) searchButton.getLayoutParams();
|
||||
layoutParams.weight = 0.5f;
|
||||
layoutParams.topMargin = AndroidUtilities.dp(4);
|
||||
layoutParams.height = AndroidUtilities.dp(48);
|
||||
layoutParams.width = 0;
|
||||
searchButton.setLayoutParams(layoutParams);
|
||||
searchButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (delegate != null) {
|
||||
delegate.didPressedSearchButton(0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
FrameLayout frameLayout = new FrameLayout(context);
|
||||
frameLayout.setBackgroundColor(0);
|
||||
addView(frameLayout);
|
||||
layoutParams = (LayoutParams) frameLayout.getLayoutParams();
|
||||
layoutParams.topMargin = AndroidUtilities.dp(4);
|
||||
layoutParams.height = AndroidUtilities.dp(48);
|
||||
layoutParams.width = AndroidUtilities.dp(4);
|
||||
frameLayout.setLayoutParams(layoutParams);
|
||||
|
||||
searchButton = new SearchButton(context);
|
||||
searchButton.textView1.setText(LocaleController.getString("SearchGifs", R.string.SearchGifs));
|
||||
searchButton.textView2.setText("GIPHY");
|
||||
searchButton.imageView.setImageResource(R.drawable.search_gif);
|
||||
addView(searchButton);
|
||||
layoutParams = (LayoutParams) searchButton.getLayoutParams();
|
||||
layoutParams.weight = 0.5f;
|
||||
layoutParams.topMargin = AndroidUtilities.dp(4);
|
||||
layoutParams.height = AndroidUtilities.dp(48);
|
||||
layoutParams.width = 0;
|
||||
searchButton.setLayoutParams(layoutParams);
|
||||
if (allowGifs) {
|
||||
searchButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (delegate != null) {
|
||||
delegate.didPressedSearchButton(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
searchButton.setAlpha(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
public void setDelegate(PhotoPickerSearchCellDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(52), MeasureSpec.EXACTLY));
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import android.content.Context;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
|
@ -143,6 +144,9 @@ public class PollEditTextCell extends FrameLayout {
|
|||
deleteImageView.setTag(null);
|
||||
}
|
||||
textView.setText(text);
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
textView.setSelection(text.length());
|
||||
}
|
||||
textView.setHint(hint);
|
||||
needDivider = divider;
|
||||
setWillNotDraw(!divider);
|
||||
|
|
|
@ -65,8 +65,7 @@ public class ShareDialogCell extends FrameLayout {
|
|||
nameTextView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 66, 6, 0));
|
||||
|
||||
checkBox = new CheckBox2(context);
|
||||
checkBox.setSize(21);
|
||||
checkBox = new CheckBox2(context, 21);
|
||||
checkBox.setColor(Theme.key_dialogRoundCheckBox, Theme.key_dialogBackground, Theme.key_dialogRoundCheckBoxCheck);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
checkBox.setDrawBackgroundAsArc(4);
|
||||
|
|
|
@ -66,10 +66,9 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
|
|||
TAG = DownloadController.getInstance(currentAccount).generateObserverTag();
|
||||
setWillNotDraw(false);
|
||||
|
||||
checkBox = new CheckBox2(context);
|
||||
checkBox = new CheckBox2(context, 21);
|
||||
checkBox.setVisibility(INVISIBLE);
|
||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||
checkBox.setSize(21);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
checkBox.setDrawBackgroundAsArc(3);
|
||||
addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 38, 32, LocaleController.isRTL ? 39 : 0, 0));
|
||||
|
|
|
@ -124,10 +124,9 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle
|
|||
progressView.setProgressColor(Theme.getColor(Theme.key_sharedMedia_startStopLoadIcon));
|
||||
addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 72, 54, LocaleController.isRTL ? 72 : 0, 0));
|
||||
|
||||
checkBox = new CheckBox2(context);
|
||||
checkBox = new CheckBox2(context, 21);
|
||||
checkBox.setVisibility(INVISIBLE);
|
||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||
checkBox.setSize(21);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
checkBox.setDrawBackgroundAsArc(2);
|
||||
addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 33, 28, LocaleController.isRTL ? 33 : 0, 0));
|
||||
|
|
|
@ -157,10 +157,9 @@ public class SharedLinkCell extends FrameLayout {
|
|||
linkImageView.setRoundRadius(AndroidUtilities.dp(4));
|
||||
letterDrawable = new LetterDrawable();
|
||||
|
||||
checkBox = new CheckBox2(context);
|
||||
checkBox = new CheckBox2(context, 21);
|
||||
checkBox.setVisibility(INVISIBLE);
|
||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||
checkBox.setSize(21);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
checkBox.setDrawBackgroundAsArc(2);
|
||||
addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 44, 44, LocaleController.isRTL ? 44 : 0, 0));
|
||||
|
|
|
@ -115,10 +115,9 @@ public class SharedPhotoVideoCell extends FrameLayout {
|
|||
selector.setBackgroundDrawable(Theme.getSelectorDrawable(false));
|
||||
addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||
|
||||
checkBox = new CheckBox2(context);
|
||||
checkBox = new CheckBox2(context, 21);
|
||||
checkBox.setVisibility(INVISIBLE);
|
||||
checkBox.setColor(null, Theme.key_sharedMedia_photoPlaceholder, Theme.key_checkboxCheck);
|
||||
checkBox.setSize(21);
|
||||
checkBox.setDrawUnchecked(false);
|
||||
checkBox.setDrawBackgroundAsArc(1);
|
||||
addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.RIGHT | Gravity.TOP, 0, 1, 1, 0));
|
||||
|
@ -144,8 +143,8 @@ public class SharedPhotoVideoCell extends FrameLayout {
|
|||
if (animated) {
|
||||
animator = new AnimatorSet();
|
||||
animator.playTogether(
|
||||
ObjectAnimator.ofFloat(container, "scaleX", checked ? 0.81f : 1.0f),
|
||||
ObjectAnimator.ofFloat(container, "scaleY", checked ? 0.81f : 1.0f));
|
||||
ObjectAnimator.ofFloat(container, View.SCALE_X, checked ? 0.81f : 1.0f),
|
||||
ObjectAnimator.ofFloat(container, View.SCALE_Y, checked ? 0.81f : 1.0f));
|
||||
animator.setDuration(200);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.telegram.messenger.ImageLocation;
|
|||
import org.telegram.messenger.LocaleController;
|
||||
import org.telegram.messenger.MessageObject;
|
||||
import org.telegram.messenger.R;
|
||||
import org.telegram.tgnet.TLObject;
|
||||
import org.telegram.tgnet.TLRPC;
|
||||
import org.telegram.ui.ActionBar.Theme;
|
||||
import org.telegram.ui.Components.BackupImageView;
|
||||
|
@ -53,12 +54,13 @@ public class StickerSetCell extends FrameLayout {
|
|||
textView = new TextView(context);
|
||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||
textView.setLines(1);
|
||||
textView.setMaxLines(1);
|
||||
textView.setSingleLine(true);
|
||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||
textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 40 : 71, 10, LocaleController.isRTL ? 71 : 40, 0));
|
||||
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 40 : 71, 9, LocaleController.isRTL ? 71 : 40, 0));
|
||||
|
||||
valueTextView = new TextView(context);
|
||||
valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2));
|
||||
|
@ -67,18 +69,18 @@ public class StickerSetCell extends FrameLayout {
|
|||
valueTextView.setMaxLines(1);
|
||||
valueTextView.setSingleLine(true);
|
||||
valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
||||
addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 40 : 71, 35, LocaleController.isRTL ? 71 : 40, 0));
|
||||
addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 40 : 71, 32, LocaleController.isRTL ? 71 : 40, 0));
|
||||
|
||||
imageView = new BackupImageView(context);
|
||||
imageView.setAspectFit(true);
|
||||
imageView.setLayerNum(1);
|
||||
addView(imageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 12, 8, LocaleController.isRTL ? 12 : 0, 0));
|
||||
addView(imageView, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 13, 9, LocaleController.isRTL ? 13 : 0, 0));
|
||||
|
||||
if (option == 2) {
|
||||
progressView = new RadialProgressView(getContext());
|
||||
progressView.setProgressColor(Theme.getColor(Theme.key_dialogProgressCircle));
|
||||
progressView.setSize(AndroidUtilities.dp(30));
|
||||
addView(progressView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 12, 8, LocaleController.isRTL ? 12 : 0, 0));
|
||||
addView(progressView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 12, 5, LocaleController.isRTL ? 12 : 0, 0));
|
||||
} else if (option != 0) {
|
||||
optionsButton = new ImageView(context);
|
||||
optionsButton.setFocusable(false);
|
||||
|
@ -87,18 +89,18 @@ public class StickerSetCell extends FrameLayout {
|
|||
if (option == 1) {
|
||||
optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_stickers_menu), PorterDuff.Mode.MULTIPLY));
|
||||
optionsButton.setImageResource(R.drawable.msg_actions);
|
||||
addView(optionsButton, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP));
|
||||
addView(optionsButton, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL));
|
||||
} else if (option == 3) {
|
||||
optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.MULTIPLY));
|
||||
optionsButton.setImageResource(R.drawable.sticker_added);
|
||||
addView(optionsButton, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, (LocaleController.isRTL ? 10 : 0), 12, (LocaleController.isRTL ? 0 : 10), 0));
|
||||
addView(optionsButton, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, (LocaleController.isRTL ? 10 : 0), 9, (LocaleController.isRTL ? 0 : 10), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
|
||||
super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(58) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
public void setText(String title, String subtitle, int icon, boolean divider) {
|
||||
|
@ -145,15 +147,34 @@ public class StickerSetCell extends FrameLayout {
|
|||
valueTextView.setAlpha(1.0f);
|
||||
imageView.setAlpha(1.0f);
|
||||
}
|
||||
|
||||
ArrayList<TLRPC.Document> documents = set.documents;
|
||||
if (documents != null && !documents.isEmpty()) {
|
||||
valueTextView.setText(LocaleController.formatPluralString("Stickers", documents.size()));
|
||||
TLRPC.Document document = documents.get(0);
|
||||
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
|
||||
if (MessageObject.canAutoplayAnimatedSticker(document)) {
|
||||
imageView.setImage(ImageLocation.getForDocument(document), "80_80", ImageLocation.getForDocument(thumb, document), null, 0, set);
|
||||
|
||||
TLRPC.Document sticker = documents.get(0);
|
||||
TLObject object;
|
||||
if (set.set.thumb instanceof TLRPC.TL_photoSize) {
|
||||
object = set.set.thumb;
|
||||
} else {
|
||||
imageView.setImage(ImageLocation.getForDocument(thumb, document), null, "webp", null, set);
|
||||
object = sticker;
|
||||
}
|
||||
ImageLocation imageLocation;
|
||||
|
||||
if (object instanceof TLRPC.Document) {
|
||||
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(sticker.thumbs, 90);
|
||||
imageLocation = ImageLocation.getForDocument(thumb, sticker);
|
||||
} else {
|
||||
TLRPC.PhotoSize thumb = (TLRPC.PhotoSize) object;
|
||||
imageLocation = ImageLocation.getForSticker(thumb, sticker);
|
||||
}
|
||||
|
||||
if (object instanceof TLRPC.Document && MessageObject.isAnimatedStickerDocument(sticker)) {
|
||||
imageView.setImage(ImageLocation.getForDocument(sticker), "50_50", imageLocation, null, 0, set);
|
||||
} else if (imageLocation != null && imageLocation.lottieAnimation) {
|
||||
imageView.setImage(imageLocation, "50_50", "tgs", null, set);
|
||||
} else {
|
||||
imageView.setImage(imageLocation, "50_50", "webp", null, set);
|
||||
}
|
||||
} else {
|
||||
valueTextView.setText(LocaleController.formatPluralString("Stickers", 0));
|
||||
|
|
|
@ -168,17 +168,13 @@ public class UserCell extends FrameLayout {
|
|||
addButton.setVisibility(value ? VISIBLE : GONE);
|
||||
}
|
||||
|
||||
public void setIsAdmin(int value) {
|
||||
public void setAdminRole(String role) {
|
||||
if (adminTextView == null) {
|
||||
return;
|
||||
}
|
||||
adminTextView.setVisibility(value != 0 ? VISIBLE : GONE);
|
||||
if (value == 1) {
|
||||
adminTextView.setText(LocaleController.getString("ChannelCreator", R.string.ChannelCreator));
|
||||
} else if (value == 2) {
|
||||
adminTextView.setText(LocaleController.getString("ChannelAdmin", R.string.ChannelAdmin));
|
||||
}
|
||||
if (value != 0) {
|
||||
adminTextView.setVisibility(role != null ? VISIBLE : GONE);
|
||||
adminTextView.setText(role);
|
||||
if (role != null) {
|
||||
CharSequence text = adminTextView.getText();
|
||||
int size = (int) Math.ceil(adminTextView.getPaint().measureText(text, 0, text.length()));
|
||||
nameTextView.setPadding(LocaleController.isRTL ? size + AndroidUtilities.dp(6) : 0, 0, !LocaleController.isRTL ? size + AndroidUtilities.dp(6) : 0, 0);
|
||||
|
@ -447,6 +443,8 @@ public class UserCell extends FrameLayout {
|
|||
avatarImageView.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser);
|
||||
} else if (currentChat != null) {
|
||||
avatarImageView.setImage(ImageLocation.getForChat(currentChat, false), "50_50", avatarDrawable, currentChat);
|
||||
} else {
|
||||
avatarImageView.setImageDrawable(avatarDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue