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 ->
|
applicationVariants.all { variant ->
|
||||||
variant.outputs.all { output ->
|
variant.outputs.all { output ->
|
||||||
|
@ -276,7 +276,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionName "5.9.0"
|
versionName "5.10.0"
|
||||||
|
|
||||||
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']
|
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.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.CALL_PHONE" />
|
<uses-permission android:name="android.permission.CALL_PHONE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<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"/>
|
<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.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.CALL_PHONE" />
|
<uses-permission android:name="android.permission.CALL_PHONE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<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"/>
|
<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)
|
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_C_INCLUDES += ./jni/boringssl/include/
|
||||||
LOCAL_ARM_MODE := arm
|
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 := -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 += -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_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_LDLIBS := -ljnigraphics -llog -lz -lEGL -lGLESv2 -landroid
|
||||||
LOCAL_STATIC_LIBRARIES := webp sqlite lz4 rlottie tgnet swscale avformat avcodec avresample avutil voip flac
|
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);
|
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);
|
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) {
|
if (phoneStr != 0) {
|
||||||
env->ReleaseStringUTFChars(phone, phoneStr);
|
env->ReleaseStringUTFChars(phone, phoneStr);
|
||||||
}
|
}
|
||||||
|
@ -436,7 +436,7 @@ static JNINativeMethod ConnectionsManagerMethods[] = {
|
||||||
{"native_setNetworkAvailable", "(IZIZ)V", (void *) setNetworkAvailable},
|
{"native_setNetworkAvailable", "(IZIZ)V", (void *) setNetworkAvailable},
|
||||||
{"native_setPushConnectionEnabled", "(IZ)V", (void *) setPushConnectionEnabled},
|
{"native_setPushConnectionEnabled", "(IZ)V", (void *) setPushConnectionEnabled},
|
||||||
{"native_setJava", "(Z)V", (void *) setJava},
|
{"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_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}
|
{"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();
|
VideoInfo *info = new VideoInfo();
|
||||||
|
|
||||||
char const *srcString = env->GetStringUTFChars(src, 0);
|
char const *srcString = env->GetStringUTFChars(src, 0);
|
||||||
|
@ -377,6 +377,9 @@ jlong Java_org_telegram_ui_Components_AnimatedFileDrawable_createDecoder(JNIEnv
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
info->fmt_ctx->flags |= AVFMT_FLAG_FAST_SEEK;
|
info->fmt_ctx->flags |= AVFMT_FLAG_FAST_SEEK;
|
||||||
|
if (preview) {
|
||||||
|
info->fmt_ctx->flags |= AVFMT_FLAG_NOBUFFER;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((ret = avformat_open_input(&info->fmt_ctx, info->src, NULL, NULL)) < 0) {
|
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));
|
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;
|
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) {
|
if (ptr == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -491,6 +494,9 @@ void Java_org_telegram_ui_Components_AnimatedFileDrawable_seekToMs(JNIEnv *env,
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
avcodec_flush_buffers(info->video_dec_ctx);
|
avcodec_flush_buffers(info->video_dec_ctx);
|
||||||
|
if (!precise) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int got_frame = 0;
|
int got_frame = 0;
|
||||||
int32_t tries = 1000;
|
int32_t tries = 1000;
|
||||||
while (tries > 0) {
|
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) {
|
if (ptr == NULL || bitmap == nullptr) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -552,7 +558,8 @@ jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *
|
||||||
VideoInfo *info = (VideoInfo *) (intptr_t) ptr;
|
VideoInfo *info = (VideoInfo *) (intptr_t) ptr;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int got_frame = 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) {
|
while (!info->stopped && triesCount != 0) {
|
||||||
if (info->pkt.size == 0) {
|
if (info->pkt.size == 0) {
|
||||||
ret = av_read_frame(info->fmt_ctx, &info->pkt);
|
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);
|
LOGE("can't decode packet flushed %s", info->src);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (got_frame == 0) {
|
if (!preview && got_frame == 0) {
|
||||||
if (info->has_decoded_frames) {
|
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) {
|
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));
|
LOGE("can't seek to begin of file %s, %s", info->src, av_err2str(ret));
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <lz4.h>
|
#include <lz4.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <map>
|
||||||
#include <tgnet/ConnectionsManager.h>
|
#include <tgnet/ConnectionsManager.h>
|
||||||
#include <tgnet/FileLog.h>
|
#include <tgnet/FileLog.h>
|
||||||
#include "c_utils.h"
|
#include "c_utils.h"
|
||||||
|
@ -35,12 +36,24 @@ typedef struct LottieInfo {
|
||||||
bool nextFrameIsCacheFrame = false;
|
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();
|
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);
|
char const *srcString = env->GetStringUTFChars(src, 0);
|
||||||
info->path = srcString;
|
info->path = srcString;
|
||||||
info->animation = rlottie::Animation::loadFromFile(info->path);
|
info->animation = rlottie::Animation::loadFromFile(info->path, colors);
|
||||||
if (srcString != 0) {
|
if (srcString != 0) {
|
||||||
env->ReleaseStringUTFChars(src, srcString);
|
env->ReleaseStringUTFChars(src, srcString);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef LOT_BUILD
|
#ifdef LOT_BUILD
|
||||||
|
@ -257,7 +258,7 @@ public:
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
static std::unique_ptr<Animation>
|
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.
|
* @brief Constructs an animation object from JSON string data.
|
||||||
|
|
|
@ -136,7 +136,7 @@ std::unique_ptr<Animation> Animation::loadFromData(
|
||||||
return nullptr;
|
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()) {
|
if (path.empty()) {
|
||||||
vWarning << "File path is empty";
|
vWarning << "File path is empty";
|
||||||
|
@ -144,7 +144,7 @@ std::unique_ptr<Animation> Animation::loadFromFile(const std::string &path)
|
||||||
}
|
}
|
||||||
|
|
||||||
LottieLoader loader;
|
LottieLoader loader;
|
||||||
if (loader.load(path)) {
|
if (loader.load(path, colorReplacement)) {
|
||||||
auto animation = std::unique_ptr<Animation>(new Animation);
|
auto animation = std::unique_ptr<Animation>(new Animation);
|
||||||
animation->d->init(loader.model());
|
animation->d->init(loader.model());
|
||||||
return animation;
|
return animation;
|
||||||
|
|
|
@ -75,7 +75,7 @@ static std::string dirname(const std::string &path)
|
||||||
return std::string(path, 0, len);
|
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);
|
mModel = LottieFileCache::instance().find(path);
|
||||||
if (mModel) return true;
|
if (mModel) return true;
|
||||||
|
@ -90,7 +90,7 @@ bool LottieLoader::load(const std::string &path)
|
||||||
std::stringstream buf;
|
std::stringstream buf;
|
||||||
buf << f.rdbuf();
|
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()) {
|
if (parser.hasParsingError()) {
|
||||||
f.close();
|
f.close();
|
||||||
return false;
|
return false;
|
||||||
|
@ -110,8 +110,8 @@ bool LottieLoader::loadFromData(std::string &&jsonData, const std::string &key,
|
||||||
mModel = LottieFileCache::instance().find(key);
|
mModel = LottieFileCache::instance().find(key);
|
||||||
if (mModel) return true;
|
if (mModel) return true;
|
||||||
|
|
||||||
LottieParser parser(const_cast<char *>(jsonData.c_str()),
|
std::map<int32_t, int32_t> colors;
|
||||||
resourcePath.c_str());
|
LottieParser parser(const_cast<char *>(jsonData.c_str()), resourcePath.c_str(), colors);
|
||||||
mModel = parser.model();
|
mModel = parser.model();
|
||||||
LottieFileCache::instance().add(key, mModel);
|
LottieFileCache::instance().add(key, mModel);
|
||||||
|
|
||||||
|
|
|
@ -19,14 +19,15 @@
|
||||||
#ifndef LOTTIELOADER_H
|
#ifndef LOTTIELOADER_H
|
||||||
#define LOTTIELOADER_H
|
#define LOTTIELOADER_H
|
||||||
|
|
||||||
#include<sstream>
|
#include <sstream>
|
||||||
#include<memory>
|
#include <memory>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
class LOTModel;
|
class LOTModel;
|
||||||
class LottieLoader
|
class LottieLoader
|
||||||
{
|
{
|
||||||
public:
|
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);
|
bool loadFromData(std::string &&jsonData, const std::string &key, const std::string &resourcePath);
|
||||||
std::shared_ptr<LOTModel> model();
|
std::shared_ptr<LOTModel> model();
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -210,7 +210,7 @@ void LOTGradient::populate(VGradientStops &stops, int frameNo)
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i = 0; i < colorPoints; i++) {
|
for (int i = 0; i < colorPoints; i++) {
|
||||||
float colorStop = ptr[0];
|
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 (opacityArraySize) {
|
||||||
if (j == opacityArraySize) {
|
if (j == opacityArraySize) {
|
||||||
// already reached the end
|
// already reached the end
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <tgnet/FileLog.h>
|
||||||
|
|
||||||
#include "lottiemodel.h"
|
#include "lottiemodel.h"
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
|
@ -181,8 +182,8 @@ protected:
|
||||||
|
|
||||||
class LottieParserImpl : protected LookaheadParserHandler {
|
class LottieParserImpl : protected LookaheadParserHandler {
|
||||||
public:
|
public:
|
||||||
LottieParserImpl(char *str, const char *dir_path)
|
LottieParserImpl(char *str, const char *dir_path, std::map<int32_t, int32_t> &colorReplacement)
|
||||||
: LookaheadParserHandler(str), mDirPath(dir_path)
|
: LookaheadParserHandler(str), mDirPath(dir_path), colorMap(colorReplacement)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,6 +287,8 @@ protected:
|
||||||
std::vector<std::shared_ptr<LOTLayerData>> mLayersToUpdate;
|
std::vector<std::shared_ptr<LOTLayerData>> mLayersToUpdate;
|
||||||
std::string mDirPath;
|
std::string mDirPath;
|
||||||
std::vector<LayerInfo> mLayerInfoList;
|
std::vector<LayerInfo> mLayerInfoList;
|
||||||
|
std::map<int32_t, int32_t> colorMap;
|
||||||
|
|
||||||
void SkipOut(int depth);
|
void SkipOut(int depth);
|
||||||
bool parsingError{false};
|
bool parsingError{false};
|
||||||
};
|
};
|
||||||
|
@ -840,17 +843,31 @@ LottieColor LottieParserImpl::toColor(const char *str)
|
||||||
}
|
}
|
||||||
|
|
||||||
char tmp[3] = {'\0', '\0', '\0'};
|
char tmp[3] = {'\0', '\0', '\0'};
|
||||||
|
|
||||||
tmp[0] = str[1];
|
tmp[0] = str[1];
|
||||||
tmp[1] = str[2];
|
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[0] = str[3];
|
||||||
tmp[1] = str[4];
|
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[0] = str[5];
|
||||||
tmp[1] = str[6];
|
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;
|
return color;
|
||||||
}
|
}
|
||||||
|
@ -1095,6 +1112,10 @@ std::shared_ptr<LOTMaskData> LottieParserImpl::parseMaskObject()
|
||||||
obj->mInv = GetBool();
|
obj->mInv = GetBool();
|
||||||
} else if (0 == strcmp(key, "mode")) {
|
} else if (0 == strcmp(key, "mode")) {
|
||||||
const char *str = GetString();
|
const char *str = GetString();
|
||||||
|
if (str == nullptr) {
|
||||||
|
parsingError = true;
|
||||||
|
return sharedMask;
|
||||||
|
}
|
||||||
switch (str[0]) {
|
switch (str[0]) {
|
||||||
case 'n':
|
case 'n':
|
||||||
obj->mMode = LOTMaskData::Mode::None;
|
obj->mMode = LOTMaskData::Mode::None;
|
||||||
|
@ -1260,7 +1281,9 @@ std::shared_ptr<LOTData> LottieParserImpl::parseGroupObject() {
|
||||||
staticFlag &= child.get()->isStatic();
|
staticFlag &= child.get()->isStatic();
|
||||||
}
|
}
|
||||||
|
|
||||||
group->setStatic(staticFlag && group->mTransform->isStatic());
|
if (group->mTransform) {
|
||||||
|
group->setStatic(staticFlag && group->mTransform->isStatic());
|
||||||
|
}
|
||||||
|
|
||||||
return sharedGroup;
|
return sharedGroup;
|
||||||
}
|
}
|
||||||
|
@ -2005,6 +2028,20 @@ void LottieParserImpl::getValue(LottieColor &color)
|
||||||
parsingError = true;
|
parsingError = true;
|
||||||
return;
|
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.r = val[2];
|
||||||
color.g = val[1];
|
color.g = val[1];
|
||||||
color.b = val[0];
|
color.b = val[0];
|
||||||
|
@ -2590,8 +2627,8 @@ LottieParser::~LottieParser()
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
LottieParser::LottieParser(char *str, const char *dir_path)
|
LottieParser::LottieParser(char *str, const char *dir_path, std::map<int32_t, int32_t> &colorReplacement)
|
||||||
: d(new LottieParserImpl(str, dir_path))
|
: d(new LottieParserImpl(str, dir_path, colorReplacement))
|
||||||
{
|
{
|
||||||
d->parseComposition();
|
d->parseComposition();
|
||||||
if (d->hasParsingError()) {
|
if (d->hasParsingError()) {
|
||||||
|
|
|
@ -20,12 +20,13 @@
|
||||||
#define LOTTIEPARSER_H
|
#define LOTTIEPARSER_H
|
||||||
|
|
||||||
#include "lottiemodel.h"
|
#include "lottiemodel.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
class LottieParserImpl;
|
class LottieParserImpl;
|
||||||
class LottieParser {
|
class LottieParser {
|
||||||
public:
|
public:
|
||||||
~LottieParser();
|
~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();
|
std::shared_ptr<LOTModel> model();
|
||||||
bool hasParsingError();
|
bool hasParsingError();
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -209,6 +209,9 @@ VPath VDasher::dashed(const VPath &path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mResult.points().size() > SHRT_MAX) {
|
||||||
|
mResult.reset();
|
||||||
|
}
|
||||||
return std::move(mResult);
|
return std::move(mResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "vraster.h"
|
#include "vraster.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <tgnet/FileLog.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "v_ft_raster.h"
|
#include "v_ft_raster.h"
|
||||||
#include "v_ft_stroker.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<VPath::Element> &elements = path.elements();
|
||||||
const std::vector<VPointF> & points = path.points();
|
const std::vector<VPointF> & points = path.points();
|
||||||
|
if (points.size() > SHRT_MAX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
grow(points.size(), path.segments());
|
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) {
|
InputPeer *InputPeer::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||||
if (TL_auth_authorization::constructor != constructor) {
|
InputPeer *result = nullptr;
|
||||||
error = true;
|
switch (constructor) {
|
||||||
if (LOGS_ENABLED) DEBUG_E("can't parse magic %x in TL_auth_authorization", constructor);
|
case 0x7da07ec9:
|
||||||
return nullptr;
|
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);
|
result->readParams(stream, instanceNum, error);
|
||||||
return result;
|
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) {
|
void TL_auth_authorization::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error) {
|
||||||
flags = stream->readInt32(&error);
|
flags = stream->readInt32(&error);
|
||||||
if ((flags & 1) != 0) {
|
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));
|
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) {
|
TL_auth_exportedAuthorization *TL_auth_exportedAuthorization::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) {
|
||||||
if (TL_auth_exportedAuthorization::constructor != constructor) {
|
if (TL_auth_exportedAuthorization::constructor != constructor) {
|
||||||
error = true;
|
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) {
|
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) {
|
void TL_auth_importAuthorization::serializeToStream(NativeByteBuffer *stream) {
|
||||||
|
|
|
@ -315,7 +315,354 @@ public:
|
||||||
void serializeToStream(NativeByteBuffer *stream);
|
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:
|
public:
|
||||||
static const uint32_t constructor = 0xcd050916;
|
static const uint32_t constructor = 0xcd050916;
|
||||||
|
@ -324,8 +671,8 @@ public:
|
||||||
int32_t tmp_sessions;
|
int32_t tmp_sessions;
|
||||||
std::unique_ptr<User> user;
|
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 readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error);
|
||||||
|
void serializeToStream(NativeByteBuffer *stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TL_auth_exportedAuthorization : public TLObject {
|
class TL_auth_exportedAuthorization : public TLObject {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
#include <algorithm>
|
||||||
#include "Connection.h"
|
#include "Connection.h"
|
||||||
#include "ConnectionsManager.h"
|
#include "ConnectionsManager.h"
|
||||||
#include "BuffersStorage.h"
|
#include "BuffersStorage.h"
|
||||||
|
@ -219,7 +220,7 @@ void Connection::onReceivedData(NativeByteBuffer *buffer) {
|
||||||
len = currentPacketLength + 4;
|
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);
|
if (LOGS_ENABLED) DEBUG_D("connection(%p, account%u, dc%u, type %d) received invalid packet length", this, currentDatacenter->instanceNum, currentDatacenter->getDatacenterId(), connectionType);
|
||||||
reconnect();
|
reconnect();
|
||||||
return;
|
return;
|
||||||
|
@ -348,7 +349,7 @@ void Connection::connect() {
|
||||||
lastPacketLength = 0;
|
lastPacketLength = 0;
|
||||||
wasConnected = false;
|
wasConnected = false;
|
||||||
hasSomeDataSinceLastConnect = 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) {
|
if (connectionType == ConnectionTypeProxy) {
|
||||||
setTimeout(5);
|
setTimeout(5);
|
||||||
} else if (connectionType == ConnectionTypePush) {
|
} else if (connectionType == ConnectionTypePush) {
|
||||||
|
@ -408,7 +409,7 @@ void Connection::setHasUsefullData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::allowsCustomPadding() {
|
bool Connection::allowsCustomPadding() {
|
||||||
return currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeEF;
|
return currentProtocolType == ProtocolTypeTLS || currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted) {
|
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) {
|
if (useSecret != 0) {
|
||||||
std::string *currentSecret = getCurrentSecret(useSecret);
|
std::string *currentSecret = getCurrentSecret(useSecret);
|
||||||
if (currentSecret->length() == 34 && (*currentSecret)[0] == 'd' && (*currentSecret)[1] == 'd') {
|
if (currentSecret->length() >= 17 && (*currentSecret)[0] == '\xdd') {
|
||||||
currentProtocolType = ProtocolTypeDD;
|
currentProtocolType = ProtocolTypeDD;
|
||||||
|
} else if (currentSecret->length() > 17 && (*currentSecret)[0] == '\xee') {
|
||||||
|
currentProtocolType = ProtocolTypeTLS;
|
||||||
} else {
|
} else {
|
||||||
currentProtocolType = ProtocolTypeEF;
|
currentProtocolType = ProtocolTypeEF;
|
||||||
}
|
}
|
||||||
|
@ -464,7 +467,7 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
packetLength = buff->limit();
|
packetLength = buff->limit();
|
||||||
if (currentProtocolType == ProtocolTypeDD) {
|
if (currentProtocolType == ProtocolTypeDD || currentProtocolType == ProtocolTypeTLS) {
|
||||||
RAND_bytes((uint8_t *) &additinalPacketSize, 4);
|
RAND_bytes((uint8_t *) &additinalPacketSize, 4);
|
||||||
if (!encrypted) {
|
if (!encrypted) {
|
||||||
additinalPacketSize = additinalPacketSize % 257;
|
additinalPacketSize = additinalPacketSize % 257;
|
||||||
|
@ -506,10 +509,10 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck, bool encrypted
|
||||||
RAND_bytes(bytes, 64);
|
RAND_bytes(bytes, 64);
|
||||||
uint32_t val = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0]);
|
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]);
|
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) {
|
if (currentProtocolType == ProtocolTypeEF) {
|
||||||
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xef;
|
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;
|
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xdd;
|
||||||
} else if (currentProtocolType == ProtocolTypeEE) {
|
} else if (currentProtocolType == ProtocolTypeEE) {
|
||||||
bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xee;
|
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) {
|
inline std::string *Connection::getCurrentSecret(uint8_t secretType) {
|
||||||
if (secretType == 2) {
|
if (secretType == 2) {
|
||||||
return &secret;
|
return &secret;
|
||||||
|
@ -630,16 +622,18 @@ inline void Connection::encryptKeyWithSecret(uint8_t *bytes, uint8_t secretType)
|
||||||
}
|
}
|
||||||
std::string *currentSecret = getCurrentSecret(secretType);
|
std::string *currentSecret = getCurrentSecret(secretType);
|
||||||
size_t a = 0;
|
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;
|
a = 1;
|
||||||
|
size = 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA256_CTX sha256Ctx;
|
SHA256_CTX sha256Ctx;
|
||||||
SHA256_Init(&sha256Ctx);
|
SHA256_Init(&sha256Ctx);
|
||||||
SHA256_Update(&sha256Ctx, bytes, 32);
|
SHA256_Update(&sha256Ctx, bytes, 32);
|
||||||
char b[1];
|
char b[1];
|
||||||
for (; a < currentSecret->size() / 2; a++) {
|
for (; a < size; a++) {
|
||||||
b[0] = (char) (char2int((*currentSecret)[a * 2]) * 16 + char2int((*currentSecret)[a * 2 + 1]));
|
b[0] = (char) (*currentSecret)[a];
|
||||||
SHA256_Update(&sha256Ctx, b, 1);
|
SHA256_Update(&sha256Ctx, b, 1);
|
||||||
}
|
}
|
||||||
SHA256_Final(bytes, &sha256Ctx);
|
SHA256_Final(bytes, &sha256Ctx);
|
||||||
|
|
|
@ -64,7 +64,8 @@ private:
|
||||||
enum ProtocolType {
|
enum ProtocolType {
|
||||||
ProtocolTypeEF,
|
ProtocolTypeEF,
|
||||||
ProtocolTypeEE,
|
ProtocolTypeEE,
|
||||||
ProtocolTypeDD
|
ProtocolTypeDD,
|
||||||
|
ProtocolTypeTLS
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void encryptKeyWithSecret(uint8_t *array, uint8_t secretType);
|
inline void encryptKeyWithSecret(uint8_t *array, uint8_t secretType);
|
||||||
|
|
|
@ -8,12 +8,15 @@
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <cerrno>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/hmac.h>
|
||||||
|
#include <algorithm>
|
||||||
#include "ByteStream.h"
|
#include "ByteStream.h"
|
||||||
#include "ConnectionSocket.h"
|
#include "ConnectionSocket.h"
|
||||||
#include "FileLog.h"
|
#include "FileLog.h"
|
||||||
|
@ -23,11 +26,197 @@
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
#include "NativeByteBuffer.h"
|
#include "NativeByteBuffer.h"
|
||||||
#include "BuffersStorage.h"
|
#include "BuffersStorage.h"
|
||||||
|
#include "Connection.h"
|
||||||
|
|
||||||
#ifndef EPOLLRDHUP
|
#ifndef EPOLLRDHUP
|
||||||
#define EPOLLRDHUP 0x2000
|
#define EPOLLRDHUP 0x2000
|
||||||
#endif
|
#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) {
|
ConnectionSocket::ConnectionSocket(int32_t instance) {
|
||||||
instanceNum = instance;
|
instanceNum = instance;
|
||||||
outgoingByteStream = new ByteStream();
|
outgoingByteStream = new ByteStream();
|
||||||
|
@ -44,15 +233,24 @@ ConnectionSocket::~ConnectionSocket() {
|
||||||
delete eventObject;
|
delete eventObject;
|
||||||
eventObject = nullptr;
|
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;
|
currentNetworkType = networkType;
|
||||||
isIpv6 = ipv6;
|
isIpv6 = ipv6;
|
||||||
currentAddress = address;
|
currentAddress = address;
|
||||||
currentPort = port;
|
currentPort = port;
|
||||||
waitingForHostResolve = "";
|
waitingForHostResolve = "";
|
||||||
adjustWriteOpAfterResolve = false;
|
adjustWriteOpAfterResolve = false;
|
||||||
|
tlsState = 0;
|
||||||
ConnectionsManager::getInstance(instanceNum).attachConnection(this);
|
ConnectionsManager::getInstance(instanceNum).attachConnection(this);
|
||||||
|
|
||||||
memset(&socketAddress, 0, sizeof(sockaddr_in));
|
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;
|
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 ((socketFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) can't create proxy socket", this);
|
if (LOGS_ENABLED) DEBUG_E("connection(%p) can't create proxy socket", this);
|
||||||
closeSocket(1, -1);
|
closeSocket(1, -1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
uint32_t tempBuffLength;
|
||||||
if (proxySecret->empty()) {
|
if (proxySecret->empty()) {
|
||||||
proxyAuthState = 1;
|
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 {
|
} else {
|
||||||
proxyAuthState = 0;
|
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_family = AF_INET;
|
||||||
socketAddress.sin_port = htons(proxyPort);
|
socketAddress.sin_port = htons(proxyPort);
|
||||||
|
@ -145,6 +360,24 @@ void ConnectionSocket::openConnection(std::string address, uint16_t port, bool i
|
||||||
return;
|
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);
|
openConnectionInternal(ipv6);
|
||||||
|
@ -197,7 +430,7 @@ void ConnectionSocket::closeSocket(int32_t reason, int32_t error) {
|
||||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||||
ConnectionsManager::getInstance(instanceNum).detachConnection(this);
|
ConnectionsManager::getInstance(instanceNum).detachConnection(this);
|
||||||
if (socketFd >= 0) {
|
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 (close(socketFd) != 0) {
|
||||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) unable to close socket", this);
|
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 = "";
|
waitingForHostResolve = "";
|
||||||
adjustWriteOpAfterResolve = false;
|
adjustWriteOpAfterResolve = false;
|
||||||
proxyAuthState = 0;
|
proxyAuthState = 0;
|
||||||
|
tlsState = 0;
|
||||||
onConnectedSent = false;
|
onConnectedSent = false;
|
||||||
outgoingByteStream->clean();
|
outgoingByteStream->clean();
|
||||||
|
if (tlsBuffer != nullptr) {
|
||||||
|
tlsBuffer->reuse();
|
||||||
|
tlsBuffer = nullptr;
|
||||||
|
}
|
||||||
onDisconnected(reason, error);
|
onDisconnected(reason, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,6 +460,7 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
||||||
NativeByteBuffer *buffer = ConnectionsManager::getInstance(instanceNum).networkBuffer;
|
NativeByteBuffer *buffer = ConnectionsManager::getInstance(instanceNum).networkBuffer;
|
||||||
while (true) {
|
while (true) {
|
||||||
buffer->rewind();
|
buffer->rewind();
|
||||||
|
Connection *connection = (Connection *) this;
|
||||||
readCount = recv(socketFd, buffer->bytes(), READ_BUFFER_SIZE, 0);
|
readCount = recv(socketFd, buffer->bytes(), READ_BUFFER_SIZE, 0);
|
||||||
if (readCount < 0) {
|
if (readCount < 0) {
|
||||||
closeSocket(1, -1);
|
closeSocket(1, -1);
|
||||||
|
@ -231,7 +470,75 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
||||||
if (readCount > 0) {
|
if (readCount > 0) {
|
||||||
buffer->limit((uint32_t) readCount);
|
buffer->limit((uint32_t) readCount);
|
||||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
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) {
|
if (readCount == 2) {
|
||||||
uint8_t auth_method = buffer->bytes()[1];
|
uint8_t auth_method = buffer->bytes()[1];
|
||||||
if (auth_method == 0xff) {
|
if (auth_method == 0xff) {
|
||||||
|
@ -281,7 +588,65 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
||||||
if (ConnectionsManager::getInstance(instanceNum).delegate != nullptr) {
|
if (ConnectionsManager::getInstance(instanceNum).delegate != nullptr) {
|
||||||
ConnectionsManager::getInstance(instanceNum).delegate->onBytesReceived((int32_t) readCount, currentNetworkType, instanceNum);
|
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) {
|
if (readCount != READ_BUFFER_SIZE) {
|
||||||
|
@ -297,58 +662,90 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (proxyAuthState != 0) {
|
if (proxyAuthState != 0) {
|
||||||
if (proxyAuthState == 1) {
|
if (proxyAuthState >= 10) {
|
||||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
if (proxyAuthState == 10) {
|
||||||
proxyAuthState = 2;
|
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||||
buffer[0] = 0x05;
|
tlsHashMismatch = false;
|
||||||
buffer[1] = 0x02;
|
proxyAuthState = 11;
|
||||||
buffer[2] = 0x00;
|
TlsHello hello = TlsHello::getDefault();
|
||||||
buffer[3] = 0x02;
|
hello.setDomain(currentSecretDomain);
|
||||||
if (send(socketFd, buffer, 4, 0) < 0) {
|
uint32_t size = hello.writeToBuffer(tempBuffer->bytes);
|
||||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
if (!(size = hello.writePadding(tempBuffer->bytes, size))) {
|
||||||
closeSocket(1, -1);
|
if (LOGS_ENABLED) DEBUG_E("connection(%p) too much data for padding", this);
|
||||||
return;
|
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 {
|
||||||
} else if (proxyAuthState == 3) {
|
if (proxyAuthState == 1) {
|
||||||
buffer[0] = 0x01;
|
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||||
std::string *proxyUser;
|
proxyAuthState = 2;
|
||||||
std::string *proxyPassword;
|
tempBuffer->bytes[0] = 0x05;
|
||||||
if (!overrideProxyAddress.empty()) {
|
tempBuffer->bytes[1] = 0x02;
|
||||||
proxyUser = &overrideProxyUser;
|
tempBuffer->bytes[2] = 0x00;
|
||||||
proxyPassword = &overrideProxyPassword;
|
tempBuffer->bytes[3] = 0x02;
|
||||||
} else {
|
if (send(socketFd, tempBuffer->bytes, 4, 0) < 0) {
|
||||||
proxyUser = &ConnectionsManager::getInstance(instanceNum).proxyUser;
|
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
||||||
proxyPassword = &ConnectionsManager::getInstance(instanceNum).proxyPassword;
|
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 {
|
} else {
|
||||||
if (!onConnectedSent) {
|
if (!onConnectedSent) {
|
||||||
|
@ -365,16 +762,50 @@ void ConnectionSocket::onEvent(uint32_t events) {
|
||||||
uint32_t remaining = buffer->remaining();
|
uint32_t remaining = buffer->remaining();
|
||||||
if (remaining) {
|
if (remaining) {
|
||||||
ssize_t sentLength;
|
ssize_t sentLength;
|
||||||
if ((sentLength = send(socketFd, buffer->bytes(), remaining, 0)) < 0) {
|
if (tlsState != 0) {
|
||||||
if (LOGS_ENABLED) DEBUG_E("connection(%p) send failed", this);
|
if (remaining > 2878) {
|
||||||
closeSocket(1, -1);
|
remaining = 2878;
|
||||||
return;
|
}
|
||||||
} else {
|
size_t headersSize = 0;
|
||||||
if (ConnectionsManager::getInstance(instanceNum).delegate != nullptr) {
|
if (tlsState == 1) {
|
||||||
ConnectionsManager::getInstance(instanceNum).delegate->onBytesSent((int32_t) sentLength, currentNetworkType, instanceNum);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
eventMask.events = EPOLLIN | EPOLLRDHUP | EPOLLERR | EPOLLET;
|
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.events |= EPOLLOUT;
|
||||||
}
|
}
|
||||||
eventMask.data.ptr = eventObject;
|
eventMask.data.ptr = eventObject;
|
||||||
|
@ -444,6 +875,10 @@ void ConnectionSocket::checkTimeout(int64_t now) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConnectionSocket::hasTlsHashMismatch() {
|
||||||
|
return tlsHashMismatch;
|
||||||
|
}
|
||||||
|
|
||||||
void ConnectionSocket::resetLastEventTime() {
|
void ConnectionSocket::resetLastEventTime() {
|
||||||
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
lastEventTime = ConnectionsManager::getInstance(instanceNum).getCurrentTimeMonotonicMillis();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ class NativeByteBuffer;
|
||||||
class ConnectionsManager;
|
class ConnectionsManager;
|
||||||
class ByteStream;
|
class ByteStream;
|
||||||
class EventObject;
|
class EventObject;
|
||||||
|
class ByteArray;
|
||||||
|
|
||||||
class ConnectionSocket {
|
class ConnectionSocket {
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ public:
|
||||||
|
|
||||||
void writeBuffer(uint8_t *data, uint32_t size);
|
void writeBuffer(uint8_t *data, uint32_t size);
|
||||||
void writeBuffer(NativeByteBuffer *buffer);
|
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);
|
void setTimeout(time_t timeout);
|
||||||
time_t getTimeout();
|
time_t getTimeout();
|
||||||
bool isDisconnected();
|
bool isDisconnected();
|
||||||
|
@ -39,6 +40,7 @@ protected:
|
||||||
void onEvent(uint32_t events);
|
void onEvent(uint32_t events);
|
||||||
void checkTimeout(int64_t now);
|
void checkTimeout(int64_t now);
|
||||||
void resetLastEventTime();
|
void resetLastEventTime();
|
||||||
|
bool hasTlsHashMismatch();
|
||||||
virtual void onReceivedData(NativeByteBuffer *buffer) = 0;
|
virtual void onReceivedData(NativeByteBuffer *buffer) = 0;
|
||||||
virtual void onDisconnected(int32_t reason, int32_t error) = 0;
|
virtual void onDisconnected(int32_t reason, int32_t error) = 0;
|
||||||
virtual void onConnected() = 0;
|
virtual void onConnected() = 0;
|
||||||
|
@ -68,7 +70,14 @@ private:
|
||||||
std::string waitingForHostResolve;
|
std::string waitingForHostResolve;
|
||||||
bool adjustWriteOpAfterResolve;
|
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;
|
uint8_t proxyAuthState;
|
||||||
|
|
||||||
|
|
|
@ -625,7 +625,7 @@ void ConnectionsManager::onConnectionClosed(Connection *connection, int reason)
|
||||||
if (connection->getConnectionType() == ConnectionTypeGeneric) {
|
if (connection->getConnectionType() == ConnectionTypeGeneric) {
|
||||||
if (datacenter->getDatacenterId() == currentDatacenterId) {
|
if (datacenter->getDatacenterId() == currentDatacenterId) {
|
||||||
sendingPing = false;
|
sendingPing = false;
|
||||||
if (!connection->isSuspended() && proxyAddress.empty()) {
|
if (!connection->isSuspended() && (proxyAddress.empty() || connection->hasTlsHashMismatch())) {
|
||||||
if (reason == 2) {
|
if (reason == 2) {
|
||||||
disconnectTimeoutAmount += connection->getTimeout();
|
disconnectTimeoutAmount += connection->getTimeout();
|
||||||
} else {
|
} else {
|
||||||
|
@ -641,6 +641,7 @@ void ConnectionsManager::onConnectionClosed(Connection *connection, int reason)
|
||||||
if (disconnectTimeoutAmount >= maxTimeout) {
|
if (disconnectTimeoutAmount >= maxTimeout) {
|
||||||
if (!connection->hasUsefullData()) {
|
if (!connection->hasUsefullData()) {
|
||||||
if (LOGS_ENABLED) DEBUG_D("start requesting new address and port due to timeout reach");
|
if (LOGS_ENABLED) DEBUG_D("start requesting new address and port due to timeout reach");
|
||||||
|
requestingSecondAddressByTlsHashMismatch = connection->hasTlsHashMismatch();
|
||||||
requestingSecondAddress = 0;
|
requestingSecondAddress = 0;
|
||||||
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
||||||
} else {
|
} else {
|
||||||
|
@ -976,7 +977,7 @@ TLObject *ConnectionsManager::TLdeserialize(TLObject *request, uint32_t bytes, N
|
||||||
if (request != nullptr) {
|
if (request != nullptr) {
|
||||||
TL_api_request *apiRequest = dynamic_cast<TL_api_request *>(request);
|
TL_api_request *apiRequest = dynamic_cast<TL_api_request *>(request);
|
||||||
if (apiRequest != nullptr) {
|
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);
|
if (LOGS_ENABLED) DEBUG_D("api request constructor 0x%x, don't parse", constructor);
|
||||||
} else {
|
} else {
|
||||||
object = request->deserializeResponse(data, constructor, instanceNum, error);
|
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) {
|
} else if (error->error_code == 420) {
|
||||||
int32_t waitTime = 2;
|
int32_t waitTime = 2;
|
||||||
static std::string floodWait = "FLOOD_WAIT_";
|
static std::string floodWait = "FLOOD_WAIT_";
|
||||||
|
static std::string slowmodeWait = "SLOWMODE_WAIT_";
|
||||||
|
discardResponse = true;
|
||||||
if (error->error_message.find(floodWait) != std::string::npos) {
|
if (error->error_message.find(floodWait) != std::string::npos) {
|
||||||
std::string num = error->error_message.substr(floodWait.size(), error->error_message.size() - floodWait.size());
|
std::string num = error->error_message.substr(floodWait.size(), error->error_message.size() - floodWait.size());
|
||||||
waitTime = atoi(num.c_str());
|
waitTime = atoi(num.c_str());
|
||||||
if (waitTime <= 0) {
|
if (waitTime <= 0) {
|
||||||
waitTime = 2;
|
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->failedByFloodWait = waitTime;
|
||||||
request->startTime = 0;
|
request->startTime = 0;
|
||||||
request->startTimeMillis = 0;
|
request->startTimeMillis = 0;
|
||||||
|
@ -1431,7 +1439,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag
|
||||||
datacenter->addServerSalt(salt);
|
datacenter->addServerSalt(salt);
|
||||||
saveConfig();
|
saveConfig();
|
||||||
|
|
||||||
requestSaltsForDatacenter(datacenter);
|
requestSaltsForDatacenter(datacenter, connection->getConnectionType() == ConnectionTypeTemp);
|
||||||
if (datacenter->hasAuthKey(ConnectionTypeGeneric, 1)) {
|
if (datacenter->hasAuthKey(ConnectionTypeGeneric, 1)) {
|
||||||
processRequestQueue(AllConnectionTypes, datacenter->getDatacenterId());
|
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) {
|
void ConnectionsManager::onDatacenterHandshakeComplete(Datacenter *datacenter, HandshakeType type, int32_t timeDiff) {
|
||||||
saveConfig();
|
saveConfig();
|
||||||
uint32_t datacenterId = datacenter->getDatacenterId();
|
uint32_t datacenterId = datacenter->getDatacenterId();
|
||||||
if (datacenterId == currentDatacenterId || datacenterId == movingToDatacenterId) {
|
if (datacenterId == currentDatacenterId || datacenterId == movingToDatacenterId || updatingDcSettingsWorkaround || updatingDcSettings) {
|
||||||
timeDifference = timeDiff;
|
timeDifference = timeDiff;
|
||||||
datacenter->recreateSessions(type);
|
datacenter->recreateSessions(type);
|
||||||
clearRequestsForDatacenter(datacenter, type);
|
clearRequestsForDatacenter(datacenter, type);
|
||||||
|
@ -1953,15 +1961,19 @@ void ConnectionsManager::sendMessagesToConnectionWithConfirmation(std::vector<st
|
||||||
sendMessagesToConnection(messages, connection, reportAck);
|
sendMessagesToConnection(messages, connection, reportAck);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionsManager::requestSaltsForDatacenter(Datacenter *datacenter) {
|
void ConnectionsManager::requestSaltsForDatacenter(Datacenter *datacenter, bool useTempConnection) {
|
||||||
if (std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), datacenter->getDatacenterId()) != requestingSaltsForDc.end()) {
|
uint32_t id = datacenter->getDatacenterId();
|
||||||
|
if (useTempConnection) {
|
||||||
|
id |= 0x80000000;
|
||||||
|
}
|
||||||
|
if (std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), id) != requestingSaltsForDc.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
requestingSaltsForDc.push_back(datacenter->getDatacenterId());
|
requestingSaltsForDc.push_back(datacenter->getDatacenterId());
|
||||||
TL_get_future_salts *request = new TL_get_future_salts();
|
TL_get_future_salts *request = new TL_get_future_salts();
|
||||||
request->num = 32;
|
request->num = 32;
|
||||||
sendRequest(request, [&, datacenter](TLObject *response, TL_error *error, int32_t networkType) {
|
sendRequest(request, [&, datacenter, id](TLObject *response, TL_error *error, int32_t networkType) {
|
||||||
std::vector<uint32_t>::iterator iter = std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), datacenter->getDatacenterId());
|
std::vector<uint32_t>::iterator iter = std::find(requestingSaltsForDc.begin(), requestingSaltsForDc.end(), id);
|
||||||
if (iter != requestingSaltsForDc.end()) {
|
if (iter != requestingSaltsForDc.end()) {
|
||||||
requestingSaltsForDc.erase(iter);
|
requestingSaltsForDc.erase(iter);
|
||||||
}
|
}
|
||||||
|
@ -1970,7 +1982,7 @@ void ConnectionsManager::requestSaltsForDatacenter(Datacenter *datacenter) {
|
||||||
datacenter->mergeServerSalts(res->salts);
|
datacenter->mergeServerSalts(res->salts);
|
||||||
saveConfig();
|
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) {
|
void ConnectionsManager::clearRequestsForDatacenter(Datacenter *datacenter, HandshakeType type) {
|
||||||
|
@ -2374,7 +2386,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
|
||||||
} else {
|
} else {
|
||||||
currentCount = 0;
|
currentCount = 0;
|
||||||
}
|
}
|
||||||
if (!networkAvailable || currentCount >= 10) {
|
if (!networkAvailable || currentCount >= 12) {
|
||||||
iter++;
|
iter++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2691,14 +2703,85 @@ std::unique_ptr<TLObject> ConnectionsManager::wrapInLayer(TLObject *object, Data
|
||||||
return std::unique_ptr<TLObject>(object);
|
return std::unique_ptr<TLObject>(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string hexStr(unsigned char *data, uint32_t len) {
|
static const char *const url_symbols64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||||
constexpr char hexmap[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
static unsigned char url_char_to_value[256];
|
||||||
std::string s(len * 2, ' ');
|
static void init_base64url_table() {
|
||||||
for (uint32_t i = 0; i < len; ++i) {
|
static bool is_inited = []() {
|
||||||
s[2 * i] = hexmap[(data[i] & 0xF0) >> 4];
|
std::fill(std::begin(url_char_to_value), std::end(url_char_to_value), static_cast<unsigned char>(64));
|
||||||
s[2 * i + 1] = hexmap[data[i] & 0x0F];
|
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) {
|
void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) {
|
||||||
|
@ -2764,7 +2847,7 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) {
|
||||||
}
|
}
|
||||||
std::string secret;
|
std::string secret;
|
||||||
if (dcOption->secret != nullptr) {
|
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);
|
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));
|
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;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionsManager::applyDnsConfig(NativeByteBuffer *buffer, std::string phone) {
|
void ConnectionsManager::applyDnsConfig(NativeByteBuffer *buffer, std::string phone, int32_t date) {
|
||||||
scheduleTask([&, buffer, phone] {
|
scheduleTask([&, buffer, phone, date] {
|
||||||
|
int32_t realDate = date;
|
||||||
if (LOGS_ENABLED) DEBUG_D("trying to decrypt config %d", requestingSecondAddress);
|
if (LOGS_ENABLED) DEBUG_D("trying to decrypt config %d", requestingSecondAddress);
|
||||||
TL_help_configSimple *config = Datacenter::decodeSimpleConfig(buffer);
|
TL_help_configSimple *config = Datacenter::decodeSimpleConfig(buffer);
|
||||||
|
if (config != nullptr && realDate == 0) {
|
||||||
|
realDate = config->date;
|
||||||
|
}
|
||||||
int currentDate = getCurrentTime();
|
int currentDate = getCurrentTime();
|
||||||
if (config != nullptr && config->date <= currentDate && currentDate <= config->expires) {
|
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++) {
|
for (std::vector<std::unique_ptr<TL_accessPointRule>>::iterator iter = config->rules.begin(); iter != config->rules.end(); iter++) {
|
||||||
TL_accessPointRule *rule = iter->get();
|
TL_accessPointRule *rule = iter->get();
|
||||||
if (!checkPhoneByPrefixesRules(phone, rule->phone_prefix_rules)) {
|
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);
|
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)) {
|
} else if (typeInfo == typeid(TL_ipPortSecret)) {
|
||||||
TL_ipPortSecret *ipPort = (TL_ipPortSecret *) port;
|
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);
|
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) {
|
if (requestingSecondAddress == 0) {
|
||||||
requestingSecondAddress = 1;
|
requestingSecondAddress = 1;
|
||||||
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
||||||
} else if (requestingSecondAddress == 1) {
|
|
||||||
requestingSecondAddress = 2;
|
|
||||||
delegate->onRequestNewServerIpAndPort(requestingSecondAddress, instanceNum);
|
|
||||||
} else {
|
} else {
|
||||||
requestingSecondAddress = 0;
|
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) {
|
void ConnectionsManager::setProxySettings(std::string address, uint16_t port, std::string username, std::string password, std::string secret) {
|
||||||
scheduleTask([&, address, port, username, password, 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;
|
bool reconnect = proxyAddress != address || proxyPort != port || username != proxyUser || proxyPassword != password || secretChanged;
|
||||||
proxyAddress = address;
|
proxyAddress = address;
|
||||||
proxyPort = port;
|
proxyPort = port;
|
||||||
proxyUser = username;
|
proxyUser = username;
|
||||||
proxyPassword = password;
|
proxyPassword = password;
|
||||||
proxySecret = secret;
|
proxySecret = std::move(newSecret);
|
||||||
if (!proxyAddress.empty() && connectionState == ConnectionStateConnecting) {
|
if (!proxyAddress.empty() && connectionState == ConnectionStateConnecting) {
|
||||||
connectionState = ConnectionStateConnectingViaProxy;
|
connectionState = ConnectionStateConnectingViaProxy;
|
||||||
if (delegate != nullptr) {
|
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++) {
|
for (std::map<uint32_t, Datacenter *>::iterator iter = datacenters.begin(); iter != datacenters.end(); iter++) {
|
||||||
iter->second->resetInitVersion();
|
iter->second->resetInitVersion();
|
||||||
}
|
}
|
||||||
|
updateDcSettings(0, false);
|
||||||
saveConfig();
|
saveConfig();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3206,7 +3296,7 @@ int64_t ConnectionsManager::checkProxy(std::string address, uint16_t port, std::
|
||||||
proxyCheckInfo->port = port;
|
proxyCheckInfo->port = port;
|
||||||
proxyCheckInfo->username = username;
|
proxyCheckInfo->username = username;
|
||||||
proxyCheckInfo->password = password;
|
proxyCheckInfo->password = password;
|
||||||
proxyCheckInfo->secret = secret;
|
proxyCheckInfo->secret = decodeSecret(secret);
|
||||||
proxyCheckInfo->onRequestTime = requestTimeFunc;
|
proxyCheckInfo->onRequestTime = requestTimeFunc;
|
||||||
proxyCheckInfo->pingId = ++lastPingProxyId;
|
proxyCheckInfo->pingId = ++lastPingProxyId;
|
||||||
proxyCheckInfo->instanceNum = instanceNum;
|
proxyCheckInfo->instanceNum = instanceNum;
|
||||||
|
|
|
@ -69,7 +69,7 @@ public:
|
||||||
void setSystemLangCode(std::string langCode);
|
void setSystemLangCode(std::string langCode);
|
||||||
void updateDcSettings(uint32_t datacenterId, bool workaround);
|
void updateDcSettings(uint32_t datacenterId, bool workaround);
|
||||||
void setPushConnectionEnabled(bool value);
|
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);
|
void setMtProtoVersion(int version);
|
||||||
int32_t getMtProtoVersion();
|
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);
|
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 sendPing(Datacenter *datacenter, bool usePushConnection);
|
||||||
void sendMessagesToConnection(std::vector<std::unique_ptr<NetworkMessage>> &messages, Connection *connection, bool reportAck);
|
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 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 clearRequestsForDatacenter(Datacenter *datacenter, HandshakeType type);
|
||||||
void registerForInternalPushUpdates();
|
void registerForInternalPushUpdates();
|
||||||
void processRequestQueue(uint32_t connectionType, uint32_t datacenterId);
|
void processRequestQueue(uint32_t connectionType, uint32_t datacenterId);
|
||||||
|
@ -153,6 +153,7 @@ private:
|
||||||
bool updatingDcSettings = false;
|
bool updatingDcSettings = false;
|
||||||
bool updatingDcSettingsWorkaround = false;
|
bool updatingDcSettingsWorkaround = false;
|
||||||
int32_t disconnectTimeoutAmount = 0;
|
int32_t disconnectTimeoutAmount = 0;
|
||||||
|
bool requestingSecondAddressByTlsHashMismatch = false;
|
||||||
int32_t requestingSecondAddress = 0;
|
int32_t requestingSecondAddress = 0;
|
||||||
int32_t updatingDcStartTime = 0;
|
int32_t updatingDcStartTime = 0;
|
||||||
int32_t lastDcUpdateTime = 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) {
|
Datacenter::Datacenter(int32_t instance, NativeByteBuffer *data) {
|
||||||
instanceNum = instance;
|
instanceNum = instance;
|
||||||
for (uint32_t a = 0; a < UPLOAD_CONNECTIONS_COUNT; a++) {
|
for (uint32_t a = 0; a < UPLOAD_CONNECTIONS_COUNT; a++) {
|
||||||
|
@ -108,8 +97,19 @@ Datacenter::Datacenter(int32_t instance, NativeByteBuffer *data) {
|
||||||
} else {
|
} else {
|
||||||
flags = 0;
|
flags = 0;
|
||||||
}
|
}
|
||||||
if (currentVersion >= 9) {
|
if (currentVersion >= 11) {
|
||||||
secret = data->readString(nullptr);
|
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));
|
(*array).push_back(TcpAddress(address, port, flags, secret));
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ private:
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Handshake>> handshakes;
|
std::vector<std::unique_ptr<Handshake>> handshakes;
|
||||||
|
|
||||||
const uint32_t configVersion = 10;
|
const uint32_t configVersion = 11;
|
||||||
const uint32_t paramsConfigVersion = 1;
|
const uint32_t paramsConfigVersion = 1;
|
||||||
|
|
||||||
Connection *createProxyConnection(uint8_t num);
|
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);
|
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
|
#endif
|
||||||
|
|
|
@ -92,7 +92,7 @@ bool TL_api_request::isNeedLayer() {
|
||||||
return true;
|
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();
|
TL_api_response *result = new TL_api_response();
|
||||||
result->readParamsEx(stream, bytes, error);
|
result->readParamsEx(stream, bytes, error);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -21,7 +21,6 @@ class TLClassStore {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TLObject *TLdeserialize(NativeByteBuffer *stream, uint32_t bytes, uint32_t constructor, int32_t instanceNum, bool &error);
|
static TLObject *TLdeserialize(NativeByteBuffer *stream, uint32_t bytes, uint32_t constructor, int32_t instanceNum, bool &error);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TL_api_request : public TLObject {
|
class TL_api_request : public TLObject {
|
||||||
|
@ -31,7 +30,7 @@ public:
|
||||||
|
|
||||||
~TL_api_request();
|
~TL_api_request();
|
||||||
bool isNeedLayer();
|
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);
|
void serializeToStream(NativeByteBuffer *stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -229,14 +229,6 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</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">
|
<receiver android:name=".CallReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.PHONE_STATE"/>
|
<action android:name="android.intent.action.PHONE_STATE"/>
|
||||||
|
@ -276,7 +268,6 @@
|
||||||
<service android:name=".BringAppForegroundService" android:enabled="true"/>
|
<service android:name=".BringAppForegroundService" android:enabled="true"/>
|
||||||
<service android:name=".NotificationsService" android:enabled="true"/>
|
<service android:name=".NotificationsService" android:enabled="true"/>
|
||||||
<service android:name=".NotificationRepeat" android:exported="false"/>
|
<service android:name=".NotificationRepeat" android:exported="false"/>
|
||||||
<service android:name=".ClearCacheService" android:exported="false"/>
|
|
||||||
<service android:name=".VideoEncodingService" android:enabled="true"/>
|
<service android:name=".VideoEncodingService" android:enabled="true"/>
|
||||||
<service android:name=".LocationSharingService" android:enabled="true"/>
|
<service android:name=".LocationSharingService" android:enabled="true"/>
|
||||||
<service android:name=".voip.VoIPService" android:enabled="true"/>
|
<service android:name=".voip.VoIPService" android:enabled="true"/>
|
||||||
|
|
|
@ -22,7 +22,7 @@ key_chat_messagePanelVoiceLock=-1
|
||||||
chat_secretChatStatusText=-9997953
|
chat_secretChatStatusText=-9997953
|
||||||
switchTrack=-11314335
|
switchTrack=-11314335
|
||||||
chat_inPreviewInstantSelectedText=-11099429
|
chat_inPreviewInstantSelectedText=-11099429
|
||||||
chat_attachAudioBackground=-1267376
|
chat_attachAudioBackground=-1282464
|
||||||
actionBarDefaultSubmenuBackground=-13749706
|
actionBarDefaultSubmenuBackground=-13749706
|
||||||
switchTrackBlueThumb=-14473945
|
switchTrackBlueThumb=-14473945
|
||||||
avatar_nameInMessageViolet=-5925398
|
avatar_nameInMessageViolet=-5925398
|
||||||
|
@ -49,7 +49,7 @@ switch2Track=-2135965
|
||||||
chats_menuPhoneCats=-8287602
|
chats_menuPhoneCats=-8287602
|
||||||
chat_outPreviewLine=-5515009
|
chat_outPreviewLine=-5515009
|
||||||
dialogScrollGlow=-1708041
|
dialogScrollGlow=-1708041
|
||||||
chat_messagePanelHint=-10459539
|
chat_messagePanelHint=-10064780
|
||||||
windowBackgroundGray=-15197927
|
windowBackgroundGray=-15197927
|
||||||
chat_inViaBotNameText=-9456666
|
chat_inViaBotNameText=-9456666
|
||||||
chat_outVoiceSeekbar=-1300913456
|
chat_outVoiceSeekbar=-1300913456
|
||||||
|
@ -95,7 +95,7 @@ chat_topPanelLine=-9456666
|
||||||
chat_inReplyMessageText=-251658241
|
chat_inReplyMessageText=-251658241
|
||||||
windowBackgroundWhiteInputFieldActivated=-10636041
|
windowBackgroundWhiteInputFieldActivated=-10636041
|
||||||
dialogInputField=-11248027
|
dialogInputField=-11248027
|
||||||
chat_attachGalleryBackground=-6192928
|
chat_attachGalleryBackground=-11037210
|
||||||
chat_outInstantSelected=-1
|
chat_outInstantSelected=-1
|
||||||
chat_outSentCheck=-7156228
|
chat_outSentCheck=-7156228
|
||||||
key_graySectionText=-9075309
|
key_graySectionText=-9075309
|
||||||
|
@ -158,6 +158,7 @@ dialogTextRed2=-892058
|
||||||
chats_nameMessageArchived=-9011322
|
chats_nameMessageArchived=-9011322
|
||||||
avatar_nameInMessageOrange=-1265812
|
avatar_nameInMessageOrange=-1265812
|
||||||
chats_pinnedIcon=-10524305
|
chats_pinnedIcon=-10524305
|
||||||
|
chat_attachActiveTab=-12341003
|
||||||
chat_replyPanelLine=1907997
|
chat_replyPanelLine=1907997
|
||||||
avatar_subtitleInProfileOrange=-7697782
|
avatar_subtitleInProfileOrange=-7697782
|
||||||
chat_outSentCheckSelected=-7156228
|
chat_outSentCheckSelected=-7156228
|
||||||
|
@ -220,6 +221,7 @@ dialogRoundCheckBox=-9912583
|
||||||
chat_emojiPanelTrendingTitle=-2167820
|
chat_emojiPanelTrendingTitle=-2167820
|
||||||
actionBarTabLine=-10510610
|
actionBarTabLine=-10510610
|
||||||
switchThumbChecked=-13600600
|
switchThumbChecked=-13600600
|
||||||
|
chat_stickersHintPanel=-13748673
|
||||||
chats_nameMessageArchived_threeLines=-1644826
|
chats_nameMessageArchived_threeLines=-1644826
|
||||||
chat_outSiteNameText=-5515009
|
chat_outSiteNameText=-5515009
|
||||||
windowBackgroundWhite=-14737118
|
windowBackgroundWhite=-14737118
|
||||||
|
@ -283,12 +285,13 @@ avatar_nameInMessagePink=-1215324
|
||||||
windowBackgroundWhiteGrayText=-9603715
|
windowBackgroundWhiteGrayText=-9603715
|
||||||
musicPicker_buttonBackground=-11035162
|
musicPicker_buttonBackground=-11035162
|
||||||
avatar_actionBarSelectorViolet=-11972268
|
avatar_actionBarSelectorViolet=-11972268
|
||||||
|
chat_attachPollBackground=-1263011
|
||||||
avatar_nameInMessageBlue=-9456666
|
avatar_nameInMessageBlue=-9456666
|
||||||
dialogTextBlack=-328966
|
dialogTextBlack=-328966
|
||||||
actionBarDefault=-14276309
|
actionBarDefault=-14276309
|
||||||
profile_actionIcon=-1
|
profile_actionIcon=-1
|
||||||
windowBackgroundUnchecked=-14473945
|
windowBackgroundUnchecked=-14473945
|
||||||
actionBarDefaultSelector=-196521644
|
actionBarDefaultSelector=-1102491308
|
||||||
chats_menuTopShadow=-1558504677
|
chats_menuTopShadow=-1558504677
|
||||||
chat_outAudioPerfomerText=-6965025
|
chat_outAudioPerfomerText=-6965025
|
||||||
sharedMedia_startStopLoadIcon=-11164432
|
sharedMedia_startStopLoadIcon=-11164432
|
||||||
|
@ -307,6 +310,7 @@ dialogBadgeBackground=-10371847
|
||||||
chat_outBubbleSelected=-12487769
|
chat_outBubbleSelected=-12487769
|
||||||
avatar_backgroundInProfileBlue=-11232035
|
avatar_backgroundInProfileBlue=-11232035
|
||||||
chat_inFileNameText=-1
|
chat_inFileNameText=-1
|
||||||
|
chat_attachEmptyImage=-11840420
|
||||||
inappPlayerPerformer=-1
|
inappPlayerPerformer=-1
|
||||||
chat_inInstantSelected=-9456666
|
chat_inInstantSelected=-9456666
|
||||||
chat_outFileInfoText=-6965025
|
chat_outFileInfoText=-6965025
|
||||||
|
@ -341,7 +345,7 @@ key_player_progressCachedBackground=-12433330
|
||||||
chat_outTimeText=-6965025
|
chat_outTimeText=-6965025
|
||||||
chat_outBubble=-12687992
|
chat_outBubble=-12687992
|
||||||
avatar_backgroundActionBarCyan=-14605274
|
avatar_backgroundActionBarCyan=-14605274
|
||||||
chat_attachFileBackground=-10706196
|
chat_attachFileBackground=-11291668
|
||||||
chat_attachHideBackground=-14078156
|
chat_attachHideBackground=-14078156
|
||||||
chats_menuItemText=-986896
|
chats_menuItemText=-986896
|
||||||
chats_message=-9011322
|
chats_message=-9011322
|
||||||
|
@ -371,7 +375,7 @@ player_background=-14407896
|
||||||
inappPlayerClose=-10525075
|
inappPlayerClose=-10525075
|
||||||
chat_outMediaIcon=-1
|
chat_outMediaIcon=-1
|
||||||
player_actionBarSubtitle=-9339518
|
player_actionBarSubtitle=-9339518
|
||||||
chat_attachContactBackground=-10438416
|
chat_attachContactBackground=-1265579
|
||||||
chat_outAudioCacheSeekbar=-1218212423
|
chat_outAudioCacheSeekbar=-1218212423
|
||||||
chats_sentClock=-8740661
|
chats_sentClock=-8740661
|
||||||
chat_inAudioSeekbar=-581869200
|
chat_inAudioSeekbar=-581869200
|
||||||
|
@ -382,7 +386,7 @@ chat_inPreviewInstantText=-9456666
|
||||||
chats_archiveBackground=-10642482
|
chats_archiveBackground=-10642482
|
||||||
chat_inViews=-8812137
|
chat_inViews=-8812137
|
||||||
chat_outLoaderSelected=-9194520
|
chat_outLoaderSelected=-9194520
|
||||||
dialogButtonSelector=352321535
|
dialogButtonSelector=1229541716
|
||||||
chats_archivePinBackground=-13749706
|
chats_archivePinBackground=-13749706
|
||||||
player_actionBarItems=-1
|
player_actionBarItems=-1
|
||||||
chat_sentError=-1551526
|
chat_sentError=-1551526
|
||||||
|
|
|
@ -20,7 +20,7 @@ key_chat_messagePanelVoiceLock=-1
|
||||||
chat_secretChatStatusText=-8812137
|
chat_secretChatStatusText=-8812137
|
||||||
switchTrack=-10984850
|
switchTrack=-10984850
|
||||||
chat_inPreviewInstantSelectedText=-5648402
|
chat_inPreviewInstantSelectedText=-5648402
|
||||||
chat_attachAudioBackground=-619421
|
chat_attachAudioBackground=-626837
|
||||||
location_sendLocationBackground=-9919529
|
location_sendLocationBackground=-9919529
|
||||||
actionBarDefaultSubmenuBackground=-14075831
|
actionBarDefaultSubmenuBackground=-14075831
|
||||||
switchTrackBlueThumb=-14866637
|
switchTrackBlueThumb=-14866637
|
||||||
|
@ -47,7 +47,7 @@ key_sheet_other=1140850687
|
||||||
chat_inContactNameText=-8796932
|
chat_inContactNameText=-8796932
|
||||||
chats_menuPhoneCats=-11049613
|
chats_menuPhoneCats=-11049613
|
||||||
chat_outPreviewLine=-6631937
|
chat_outPreviewLine=-6631937
|
||||||
chat_messagePanelHint=-11180684
|
chat_messagePanelHint=-9798256
|
||||||
windowBackgroundGray=-15393241
|
windowBackgroundGray=-15393241
|
||||||
chat_inViaBotNameText=-8796932
|
chat_inViaBotNameText=-8796932
|
||||||
chat_outVoiceSeekbar=-429551165
|
chat_outVoiceSeekbar=-429551165
|
||||||
|
@ -62,6 +62,7 @@ chat_emojiPanelBackspace=-9996665
|
||||||
chat_replyPanelClose=-10062202
|
chat_replyPanelClose=-10062202
|
||||||
chat_inContactPhoneSelectedText=-7490861
|
chat_inContactPhoneSelectedText=-7490861
|
||||||
dialogSearchText=-1
|
dialogSearchText=-1
|
||||||
|
actionBarTabUnactiveText=-7628894
|
||||||
chat_outAudioTitleText=-1
|
chat_outAudioTitleText=-1
|
||||||
chat_emojiPanelBackground=-14866637
|
chat_emojiPanelBackground=-14866637
|
||||||
chats_unreadCounter=-10177041
|
chats_unreadCounter=-10177041
|
||||||
|
@ -84,6 +85,7 @@ files_folderIconBackground=-13286315
|
||||||
passport_authorizeBackgroundSelected=-11627561
|
passport_authorizeBackgroundSelected=-11627561
|
||||||
switchTrackBlueChecked=-8333825
|
switchTrackBlueChecked=-8333825
|
||||||
player_seekBarBackground=1196577362
|
player_seekBarBackground=1196577362
|
||||||
|
dialogShadowLine=335544320
|
||||||
groupcreate_onlineText=-10177041
|
groupcreate_onlineText=-10177041
|
||||||
profile_status=-9192457
|
profile_status=-9192457
|
||||||
divider=-1795162112
|
divider=-1795162112
|
||||||
|
@ -91,6 +93,7 @@ chat_topPanelLine=-11108183
|
||||||
chat_inReplyMessageText=-1
|
chat_inReplyMessageText=-1
|
||||||
dialogInputField=-8549479
|
dialogInputField=-8549479
|
||||||
windowBackgroundWhiteInputFieldActivated=-9522449
|
windowBackgroundWhiteInputFieldActivated=-9522449
|
||||||
|
chat_attachGalleryBackground=-11692299
|
||||||
chat_outInstantSelected=-4268038
|
chat_outInstantSelected=-4268038
|
||||||
chat_outSentCheck=-7878657
|
chat_outSentCheck=-7878657
|
||||||
key_graySectionText=-8549479
|
key_graySectionText=-8549479
|
||||||
|
@ -153,6 +156,7 @@ dialogTextRed2=-1152913
|
||||||
chats_nameMessageArchived=-8549479
|
chats_nameMessageArchived=-8549479
|
||||||
avatar_nameInMessageOrange=-13984
|
avatar_nameInMessageOrange=-13984
|
||||||
chats_pinnedIcon=-10982016
|
chats_pinnedIcon=-10982016
|
||||||
|
chat_attachActiveTab=-9781249
|
||||||
chat_replyPanelLine=1779898909
|
chat_replyPanelLine=1779898909
|
||||||
avatar_subtitleInProfileOrange=-7628894
|
avatar_subtitleInProfileOrange=-7628894
|
||||||
chat_outSentCheckSelected=-4268038
|
chat_outSentCheckSelected=-4268038
|
||||||
|
@ -163,6 +167,7 @@ avatar_backgroundGroupCreateSpanBlue=-13803892
|
||||||
dialogTextBlue3=-10177041
|
dialogTextBlue3=-10177041
|
||||||
switchTrackBlueThumbChecked=-11632213
|
switchTrackBlueThumbChecked=-11632213
|
||||||
dialogTextBlue4=-10177041
|
dialogTextBlue4=-10177041
|
||||||
|
chat_attachUnactiveTab=-9596506
|
||||||
windowBackgroundWhiteGreenText=-10371737
|
windowBackgroundWhiteGreenText=-10371737
|
||||||
actionBarTabActiveText=-9781249
|
actionBarTabActiveText=-9781249
|
||||||
chat_emojiPanelIcon=-9996665
|
chat_emojiPanelIcon=-9996665
|
||||||
|
@ -221,6 +226,7 @@ chat_inVoiceSeekbarSelected=-9203285
|
||||||
dialogTextGray=-8549479
|
dialogTextGray=-8549479
|
||||||
chat_messageLinkOut=-6631937
|
chat_messageLinkOut=-6631937
|
||||||
avatar_backgroundArchived=-13087910
|
avatar_backgroundArchived=-13087910
|
||||||
|
picker_badge=-11097097
|
||||||
chat_outFileInfoSelectedText=-4268038
|
chat_outFileInfoSelectedText=-4268038
|
||||||
chats_tabletSelectedOverlay=268435455
|
chats_tabletSelectedOverlay=268435455
|
||||||
chat_outAudioDurationSelectedText=-4268038
|
chat_outAudioDurationSelectedText=-4268038
|
||||||
|
@ -269,10 +275,12 @@ profile_verifiedCheck=-1
|
||||||
listSelectorSDK21=301989887
|
listSelectorSDK21=301989887
|
||||||
key_chat_messagePanelVoiceLockBackground=-13548712
|
key_chat_messagePanelVoiceLockBackground=-13548712
|
||||||
chat_outFileNameText=-1
|
chat_outFileNameText=-1
|
||||||
|
picker_enabledButton=-9781249
|
||||||
inappPlayerBackground=-14602949
|
inappPlayerBackground=-14602949
|
||||||
avatar_nameInMessagePink=-624741
|
avatar_nameInMessagePink=-624741
|
||||||
windowBackgroundWhiteGrayText=-8549479
|
windowBackgroundWhiteGrayText=-8549479
|
||||||
avatar_actionBarSelectorViolet=-12758164
|
avatar_actionBarSelectorViolet=-12758164
|
||||||
|
chat_attachPollBackground=-2183099
|
||||||
avatar_nameInMessageBlue=-8796932
|
avatar_nameInMessageBlue=-8796932
|
||||||
dialogTextBlack=-592138
|
dialogTextBlack=-592138
|
||||||
actionBarDefault=-14602949
|
actionBarDefault=-14602949
|
||||||
|
@ -334,7 +342,7 @@ key_player_progressCachedBackground=-11245182
|
||||||
chat_outTimeText=-7357217
|
chat_outTimeText=-7357217
|
||||||
chat_outBubble=-12689014
|
chat_outBubble=-12689014
|
||||||
avatar_backgroundActionBarCyan=-14602949
|
avatar_backgroundActionBarCyan=-14602949
|
||||||
chat_attachFileBackground=-11359756
|
chat_attachFileBackground=-10830604
|
||||||
chat_attachHideBackground=-14074026
|
chat_attachHideBackground=-14074026
|
||||||
chats_menuItemText=-369098753
|
chats_menuItemText=-369098753
|
||||||
chats_message=-8549479
|
chats_message=-8549479
|
||||||
|
@ -365,6 +373,7 @@ chat_outMediaIcon=-1
|
||||||
chats_message_threeLines=-8549479
|
chats_message_threeLines=-8549479
|
||||||
player_actionBarSubtitle=-8549479
|
player_actionBarSubtitle=-8549479
|
||||||
chat_outAudioCacheSeekbar=-10120765
|
chat_outAudioCacheSeekbar=-10120765
|
||||||
|
chat_attachContactBackground=-2183099
|
||||||
chats_sentClock=-11772054
|
chats_sentClock=-11772054
|
||||||
chat_inAudioSeekbar=-11443856
|
chat_inAudioSeekbar=-11443856
|
||||||
avatar_subtitleInProfileRed=-7628894
|
avatar_subtitleInProfileRed=-7628894
|
||||||
|
@ -375,7 +384,7 @@ chats_archiveBackground=-11036980
|
||||||
dialog_liveLocationProgress=-9919529
|
dialog_liveLocationProgress=-9919529
|
||||||
chat_inViews=-8812137
|
chat_inViews=-8812137
|
||||||
chat_outLoaderSelected=-9919529
|
chat_outLoaderSelected=-9919529
|
||||||
dialogButtonSelector=352321535
|
dialogButtonSelector=-13483690
|
||||||
chats_archivePinBackground=-13746613
|
chats_archivePinBackground=-13746613
|
||||||
player_actionBarItems=-1
|
player_actionBarItems=-1
|
||||||
chat_sentError=-633010
|
chat_sentError=-633010
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.AssetFileDescriptor;
|
import android.content.res.AssetFileDescriptor;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
|
import android.database.ContentObserver;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
@ -40,6 +41,7 @@ import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
import android.provider.CallLog;
|
||||||
import android.provider.DocumentsContract;
|
import android.provider.DocumentsContract;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.provider.Settings;
|
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;
|
private static boolean hasCallPermissions = Build.VERSION.SDK_INT >= 23;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -1333,9 +1337,38 @@ public class AndroidUtilities {
|
||||||
telephonyService = (ITelephony) m.invoke(tm);
|
telephonyService = (ITelephony) m.invoke(tm);
|
||||||
telephonyService.silenceRinger();
|
telephonyService.silenceRinger();
|
||||||
telephonyService.endCall();
|
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) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean checkPhonePattern(String pattern, String phone) {
|
public static boolean checkPhonePattern(String pattern, String phone) {
|
||||||
|
|
|
@ -15,12 +15,14 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
||||||
private final Object sync = new Object();
|
private final Object sync = new Object();
|
||||||
private int lastOffset;
|
private int lastOffset;
|
||||||
private boolean waitingForLoad;
|
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;
|
document = d;
|
||||||
parentObject = p;
|
parentObject = p;
|
||||||
currentAccount = a;
|
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) {
|
public int read(int offset, int readLength) {
|
||||||
|
@ -37,8 +39,8 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
||||||
while (availableLength == 0) {
|
while (availableLength == 0) {
|
||||||
availableLength = loadOperation.getDownloadedLengthFromOffset(offset, readLength);
|
availableLength = loadOperation.getDownloadedLengthFromOffset(offset, readLength);
|
||||||
if (availableLength == 0) {
|
if (availableLength == 0) {
|
||||||
if (loadOperation.isPaused() || lastOffset != offset) {
|
if (loadOperation.isPaused() || lastOffset != offset || preview) {
|
||||||
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, offset);
|
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, offset, preview);
|
||||||
}
|
}
|
||||||
synchronized (sync) {
|
synchronized (sync) {
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
|
@ -46,7 +48,9 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
||||||
}
|
}
|
||||||
countDownLatch = new CountDownLatch(1);
|
countDownLatch = new CountDownLatch(1);
|
||||||
}
|
}
|
||||||
FileLoader.getInstance(currentAccount).setLoadingVideo(document, false, true);
|
if (!preview) {
|
||||||
|
FileLoader.getInstance(currentAccount).setLoadingVideo(document, false, true);
|
||||||
|
}
|
||||||
waitingForLoad = true;
|
waitingForLoad = true;
|
||||||
countDownLatch.await();
|
countDownLatch.await();
|
||||||
waitingForLoad = false;
|
waitingForLoad = false;
|
||||||
|
@ -68,7 +72,7 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
||||||
synchronized (sync) {
|
synchronized (sync) {
|
||||||
if (countDownLatch != null) {
|
if (countDownLatch != null) {
|
||||||
countDownLatch.countDown();
|
countDownLatch.countDown();
|
||||||
if (removeLoading && !canceled) {
|
if (removeLoading && !canceled && !preview) {
|
||||||
FileLoader.getInstance(currentAccount).removeLoadingVideo(document, false, true);
|
FileLoader.getInstance(currentAccount).removeLoadingVideo(document, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,6 +94,10 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPreview() {
|
||||||
|
return preview;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCurrentAccount() {
|
public int getCurrentAccount() {
|
||||||
return currentAccount;
|
return currentAccount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,8 @@ public class ApplicationLoader extends Application {
|
||||||
public static volatile boolean mainInterfacePausedStageQueue = true;
|
public static volatile boolean mainInterfacePausedStageQueue = true;
|
||||||
public static volatile long mainInterfacePausedStageQueueTime;
|
public static volatile long mainInterfacePausedStageQueueTime;
|
||||||
|
|
||||||
|
public static boolean hasPlayServices;
|
||||||
|
|
||||||
public static File getFilesDirFixed() {
|
public static File getFilesDirFixed() {
|
||||||
for (int a = 0; a < 10; a++) {
|
for (int a = 0; a < 10; a++) {
|
||||||
File path = ApplicationLoader.applicationContext.getFilesDir();
|
File path = ApplicationLoader.applicationContext.getFilesDir();
|
||||||
|
@ -140,7 +142,6 @@ public class ApplicationLoader extends Application {
|
||||||
TLRPC.User user = UserConfig.getInstance(a).getCurrentUser();
|
TLRPC.User user = UserConfig.getInstance(a).getCurrentUser();
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
MessagesController.getInstance(a).putUser(user, true);
|
MessagesController.getInstance(a).putUser(user, true);
|
||||||
MessagesController.getInstance(a).getBlockedUsers(true);
|
|
||||||
SendMessagesHelper.getInstance(a).checkUnsentMessages();
|
SendMessagesHelper.getInstance(a).checkUnsentMessages();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,7 +222,7 @@ public class ApplicationLoader extends Application {
|
||||||
|
|
||||||
private void initPlayServices() {
|
private void initPlayServices() {
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
if (checkPlayServices()) {
|
if (hasPlayServices = checkPlayServices()) {
|
||||||
final String currentPushString = SharedConfig.pushString;
|
final String currentPushString = SharedConfig.pushString;
|
||||||
if (!TextUtils.isEmpty(currentPushString)) {
|
if (!TextUtils.isEmpty(currentPushString)) {
|
||||||
if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) {
|
if (BuildVars.DEBUG_PRIVATE_VERSION && BuildVars.LOGS_ENABLED) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class BringAppForegroundService extends IntentService {
|
||||||
protected void onHandleIntent(Intent intent) {
|
protected void onHandleIntent(Intent intent) {
|
||||||
Intent intent2 = new Intent(this, LaunchActivity.class);
|
Intent intent2 = new Intent(this, LaunchActivity.class);
|
||||||
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
intent2.setAction(Intent.ACTION_MAIN);
|
||||||
startActivity(intent2);
|
startActivity(intent2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ public class BuildVars {
|
||||||
public static boolean LOGS_ENABLED = false;
|
public static boolean LOGS_ENABLED = false;
|
||||||
public static boolean USE_CLOUD_STRINGS = true;
|
public static boolean USE_CLOUD_STRINGS = true;
|
||||||
public static boolean CHECK_UPDATES = false;
|
public static boolean CHECK_UPDATES = false;
|
||||||
public static int BUILD_VERSION = 1648;
|
public static int BUILD_VERSION = 1684;
|
||||||
public static String BUILD_VERSION_STRING = "5.9.0";
|
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 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 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";
|
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"));
|
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"));
|
highPreset = new Preset(preferences.getString("preset2", "13_13_13_13_1048576_15728640_3145728_524288_1_1_1_0"));
|
||||||
boolean newConfig;
|
boolean newConfig;
|
||||||
if (newConfig = preferences.contains("newConfig") || !getUserConfig().isClientActivated()) {
|
if ((newConfig = preferences.contains("newConfig")) || !getUserConfig().isClientActivated()) {
|
||||||
mobilePreset = new Preset(preferences.getString("mobilePreset", mediumPreset.toString()));
|
mobilePreset = new Preset(preferences.getString("mobilePreset", mediumPreset.toString()));
|
||||||
wifiPreset = new Preset(preferences.getString("wifiPreset", highPreset.toString()));
|
wifiPreset = new Preset(preferences.getString("wifiPreset", highPreset.toString()));
|
||||||
roamingPreset = new Preset(preferences.getString("roamingPreset", lowPreset.toString()));
|
roamingPreset = new Preset(preferences.getString("roamingPreset", lowPreset.toString()));
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.io.File;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
@ -114,6 +115,8 @@ public class FileLoadOperation {
|
||||||
private int totalBytesCount;
|
private int totalBytesCount;
|
||||||
private int bytesCountPadding;
|
private int bytesCountPadding;
|
||||||
private int streamStartOffset;
|
private int streamStartOffset;
|
||||||
|
private int streamPriorityStartOffset;
|
||||||
|
private RequestInfo priorityRequestInfo;
|
||||||
private FileLoadOperationDelegate delegate;
|
private FileLoadOperationDelegate delegate;
|
||||||
private byte[] key;
|
private byte[] key;
|
||||||
private byte[] iv;
|
private byte[] iv;
|
||||||
|
@ -386,6 +389,23 @@ public class FileLoadOperation {
|
||||||
break;
|
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) {
|
if (!modified) {
|
||||||
ranges.add(new Range(start, end));
|
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(() -> {
|
Utilities.stageQueue.postRunnable(() -> {
|
||||||
if (streamListeners == null) {
|
if (streamListeners == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -557,10 +577,10 @@ public class FileLoadOperation {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean start() {
|
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) {
|
if (currentDownloadChunkSize == 0) {
|
||||||
currentDownloadChunkSize = totalBytesCount >= bigFileSizeFrom ? downloadChunkSizeBig : downloadChunkSize;
|
currentDownloadChunkSize = totalBytesCount >= bigFileSizeFrom ? downloadChunkSizeBig : downloadChunkSize;
|
||||||
currentMaxDownloadRequests = totalBytesCount >= bigFileSizeFrom ? maxDownloadRequestsBig : maxDownloadRequests;
|
currentMaxDownloadRequests = totalBytesCount >= bigFileSizeFrom ? maxDownloadRequestsBig : maxDownloadRequests;
|
||||||
|
@ -573,7 +593,27 @@ public class FileLoadOperation {
|
||||||
if (streamListeners == null) {
|
if (streamListeners == null) {
|
||||||
streamListeners = new ArrayList<>();
|
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);
|
streamListeners.add(stream);
|
||||||
if (alreadyStarted) {
|
if (alreadyStarted) {
|
||||||
if (preloadedBytesRanges != null && getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, streamStartOffset, 1) == 0) {
|
if (preloadedBytesRanges != null && getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, streamStartOffset, 1) == 0) {
|
||||||
|
@ -1549,12 +1589,13 @@ public class FileLoadOperation {
|
||||||
protected void startDownloadRequest() {
|
protected void startDownloadRequest() {
|
||||||
if (paused ||
|
if (paused ||
|
||||||
state != stateDownloading ||
|
state != stateDownloading ||
|
||||||
!nextPartWasPreloaded && (requestInfos.size() + delayedRequestInfos.size() >= currentMaxDownloadRequests) ||
|
streamPriorityStartOffset == 0 && (
|
||||||
isPreloadVideoOperation && (requestedBytesCount > preloadMaxBytes || moovFound != 0 && requestInfos.size() > 0)) {
|
!nextPartWasPreloaded && (requestInfos.size() + delayedRequestInfos.size() >= currentMaxDownloadRequests) ||
|
||||||
|
isPreloadVideoOperation && (requestedBytesCount > preloadMaxBytes || moovFound != 0 && requestInfos.size() > 0))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int count = 1;
|
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());
|
count = Math.max(0, currentMaxDownloadRequests - requestInfos.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1598,18 +1639,19 @@ public class FileLoadOperation {
|
||||||
preloadNotRequestedBytesCount -= currentDownloadChunkSize;
|
preloadNotRequestedBytesCount -= currentDownloadChunkSize;
|
||||||
} else {
|
} else {
|
||||||
if (notRequestedBytesRanges != null) {
|
if (notRequestedBytesRanges != null) {
|
||||||
|
int sreamOffset = streamPriorityStartOffset != 0 ? streamPriorityStartOffset : streamStartOffset;
|
||||||
int size = notRequestedBytesRanges.size();
|
int size = notRequestedBytesRanges.size();
|
||||||
int minStart = Integer.MAX_VALUE;
|
int minStart = Integer.MAX_VALUE;
|
||||||
int minStreamStart = Integer.MAX_VALUE;
|
int minStreamStart = Integer.MAX_VALUE;
|
||||||
for (int b = 0; b < size; b++) {
|
for (int b = 0; b < size; b++) {
|
||||||
Range range = notRequestedBytesRanges.get(b);
|
Range range = notRequestedBytesRanges.get(b);
|
||||||
if (streamStartOffset != 0) {
|
if (sreamOffset != 0) {
|
||||||
if (range.start <= streamStartOffset && range.end > streamStartOffset) {
|
if (range.start <= sreamOffset && range.end > sreamOffset) {
|
||||||
minStreamStart = streamStartOffset;
|
minStreamStart = sreamOffset;
|
||||||
minStart = Integer.MAX_VALUE;
|
minStart = Integer.MAX_VALUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (streamStartOffset < range.start && range.start < minStreamStart) {
|
if (sreamOffset < range.start && range.start < minStreamStart) {
|
||||||
minStreamStart = range.start;
|
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) -> {
|
requestInfo.requestToken = ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> {
|
||||||
if (!requestInfos.contains(requestInfo)) {
|
if (!requestInfos.contains(requestInfo)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (requestInfo == priorityRequestInfo) {
|
||||||
|
if (BuildVars.DEBUG_VERSION) {
|
||||||
|
FileLog.d("frame get request completed " + priorityRequestInfo.offset);
|
||||||
|
}
|
||||||
|
priorityRequestInfo = null;
|
||||||
|
}
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
if (FileRefController.isFileRefError(error.text)) {
|
if (FileRefController.isFileRefError(error.text)) {
|
||||||
requestReference(requestInfo);
|
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;
|
String fileName = null;
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
fileName = getAttachFileName(location, locationExt);
|
fileName = getAttachFileName(location, locationExt);
|
||||||
|
@ -553,15 +553,15 @@ public class FileLoader extends BaseController {
|
||||||
downloadQueue.remove(index);
|
downloadQueue.remove(index);
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
if (downloadQueue == audioLoadOperationQueue) {
|
if (downloadQueue == audioLoadOperationQueue) {
|
||||||
if (operation.start(stream, streamOffset)) {
|
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||||
currentAudioLoadOperationsCount.put(datacenterId, currentAudioLoadOperationsCount.get(datacenterId) + 1);
|
currentAudioLoadOperationsCount.put(datacenterId, currentAudioLoadOperationsCount.get(datacenterId) + 1);
|
||||||
}
|
}
|
||||||
} else if (downloadQueue == photoLoadOperationQueue) {
|
} else if (downloadQueue == photoLoadOperationQueue) {
|
||||||
if (operation.start(stream, streamOffset)) {
|
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||||
currentPhotoLoadOperationsCount.put(datacenterId, currentPhotoLoadOperationsCount.get(datacenterId) + 1);
|
currentPhotoLoadOperationsCount.put(datacenterId, currentPhotoLoadOperationsCount.get(datacenterId) + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (operation.start(stream, streamOffset)) {
|
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||||
currentLoadOperationsCount.put(datacenterId, currentLoadOperationsCount.get(datacenterId) + 1);
|
currentLoadOperationsCount.put(datacenterId, currentLoadOperationsCount.get(datacenterId) + 1);
|
||||||
}
|
}
|
||||||
if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) {
|
if (operation.wasStarted() && !activeFileLoadOperation.contains(operation)) {
|
||||||
|
@ -578,7 +578,7 @@ public class FileLoader extends BaseController {
|
||||||
if (stream != null) {
|
if (stream != null) {
|
||||||
pauseCurrentFileLoadOperations(operation);
|
pauseCurrentFileLoadOperations(operation);
|
||||||
}
|
}
|
||||||
operation.start(stream, streamOffset);
|
operation.start(stream, streamOffset, streamPriority);
|
||||||
if (downloadQueue == loadOperationQueue && !activeFileLoadOperation.contains(operation)) {
|
if (downloadQueue == loadOperationQueue && !activeFileLoadOperation.contains(operation)) {
|
||||||
activeFileLoadOperation.add(operation);
|
activeFileLoadOperation.add(operation);
|
||||||
}
|
}
|
||||||
|
@ -676,7 +676,7 @@ public class FileLoader extends BaseController {
|
||||||
int maxCount = priority > 0 ? 3 : 1;
|
int maxCount = priority > 0 ? 3 : 1;
|
||||||
int count = currentAudioLoadOperationsCount.get(datacenterId);
|
int count = currentAudioLoadOperationsCount.get(datacenterId);
|
||||||
if (stream != null || count < maxCount) {
|
if (stream != null || count < maxCount) {
|
||||||
if (operation.start(stream, streamOffset)) {
|
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||||
currentAudioLoadOperationsCount.put(datacenterId, count + 1);
|
currentAudioLoadOperationsCount.put(datacenterId, count + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -686,7 +686,7 @@ public class FileLoader extends BaseController {
|
||||||
int maxCount = priority > 0 ? 6 : 2;
|
int maxCount = priority > 0 ? 6 : 2;
|
||||||
int count = currentPhotoLoadOperationsCount.get(datacenterId);
|
int count = currentPhotoLoadOperationsCount.get(datacenterId);
|
||||||
if (stream != null || count < maxCount) {
|
if (stream != null || count < maxCount) {
|
||||||
if (operation.start(stream, streamOffset)) {
|
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||||
currentPhotoLoadOperationsCount.put(datacenterId, count + 1);
|
currentPhotoLoadOperationsCount.put(datacenterId, count + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -696,7 +696,7 @@ public class FileLoader extends BaseController {
|
||||||
int maxCount = priority > 0 ? 4 : 1;
|
int maxCount = priority > 0 ? 4 : 1;
|
||||||
int count = currentLoadOperationsCount.get(datacenterId);
|
int count = currentLoadOperationsCount.get(datacenterId);
|
||||||
if (stream != null || count < maxCount) {
|
if (stream != null || count < maxCount) {
|
||||||
if (operation.start(stream, streamOffset)) {
|
if (operation.start(stream, streamOffset, streamPriority)) {
|
||||||
currentLoadOperationsCount.put(datacenterId, count + 1);
|
currentLoadOperationsCount.put(datacenterId, count + 1);
|
||||||
activeFileLoadOperation.add(operation);
|
activeFileLoadOperation.add(operation);
|
||||||
}
|
}
|
||||||
|
@ -741,14 +741,14 @@ public class FileLoader extends BaseController {
|
||||||
if (cacheType != 10 && !TextUtils.isEmpty(fileName) && !fileName.contains("" + Integer.MIN_VALUE)) {
|
if (cacheType != 10 && !TextUtils.isEmpty(fileName) && !fileName.contains("" + Integer.MIN_VALUE)) {
|
||||||
loadOperationPathsUI.put(fileName, true);
|
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 CountDownLatch semaphore = new CountDownLatch(1);
|
||||||
final FileLoadOperation[] result = new FileLoadOperation[1];
|
final FileLoadOperation[] result = new FileLoadOperation[1];
|
||||||
fileLoaderQueue.postRunnable(() -> {
|
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();
|
semaphore.countDown();
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
|
@ -1049,7 +1049,7 @@ public class FileLoader extends BaseController {
|
||||||
|
|
||||||
public static String fixFileName(String fileName) {
|
public static String fixFileName(String fileName) {
|
||||||
if (fileName != null) {
|
if (fileName != null) {
|
||||||
fileName = fileName.replaceAll("[\u0001-\u001f<>:\"/\\\\|?*\u007f]+", "").trim();
|
fileName = fileName.replaceAll("[\u0001-\u001f<>\u202E:\"/\\\\|?*\u007f]+", "").trim();
|
||||||
}
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -420,7 +420,7 @@ public class FileRefController extends BaseController {
|
||||||
}
|
}
|
||||||
if (done) {
|
if (done) {
|
||||||
multiMediaCache.remove(multiMedia);
|
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) {
|
} else if (requester.args[0] instanceof TLRPC.TL_messages_sendMedia) {
|
||||||
TLRPC.TL_messages_sendMedia req = (TLRPC.TL_messages_sendMedia) requester.args[0];
|
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;
|
TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media;
|
||||||
mediaPhoto.id.file_reference = file_reference;
|
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) {
|
} else if (requester.args[0] instanceof TLRPC.TL_messages_editMessage) {
|
||||||
TLRPC.TL_messages_editMessage req = (TLRPC.TL_messages_editMessage) requester.args[0];
|
TLRPC.TL_messages_editMessage req = (TLRPC.TL_messages_editMessage) requester.args[0];
|
||||||
if (req.media instanceof TLRPC.TL_inputMediaDocument) {
|
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;
|
TLRPC.TL_inputMediaPhoto mediaPhoto = (TLRPC.TL_inputMediaPhoto) req.media;
|
||||||
mediaPhoto.id.file_reference = file_reference;
|
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) {
|
} else if (requester.args[0] instanceof TLRPC.TL_messages_saveGif) {
|
||||||
TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) requester.args[0];
|
TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) requester.args[0];
|
||||||
req.id.file_reference = file_reference;
|
req.id.file_reference = file_reference;
|
||||||
|
@ -489,10 +489,10 @@ public class FileRefController extends BaseController {
|
||||||
Object[] objects = multiMediaCache.get(req);
|
Object[] objects = multiMediaCache.get(req);
|
||||||
if (objects != null) {
|
if (objects != null) {
|
||||||
multiMediaCache.remove(req);
|
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) {
|
} 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) {
|
} else if (args[0] instanceof TLRPC.TL_messages_saveGif) {
|
||||||
TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) args[0];
|
TLRPC.TL_messages_saveGif req = (TLRPC.TL_messages_saveGif) args[0];
|
||||||
//do nothing
|
//do nothing
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
||||||
} else if (document.mime_type.startsWith("audio")) {
|
} else if (document.mime_type.startsWith("audio")) {
|
||||||
document.attributes.add(new TLRPC.TL_documentAttributeAudio());
|
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;
|
bytesRemaining = dataSpec.length == C.LENGTH_UNSET ? document.size - dataSpec.position : dataSpec.length;
|
||||||
if (bytesRemaining < 0) {
|
if (bytesRemaining < 0) {
|
||||||
throw new EOFException();
|
throw new EOFException();
|
||||||
|
@ -95,15 +95,17 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
||||||
if (bytesRemaining < readLength) {
|
if (bytesRemaining < readLength) {
|
||||||
readLength = (int) bytesRemaining;
|
readLength = (int) bytesRemaining;
|
||||||
}
|
}
|
||||||
while (availableLength == 0) {
|
while (availableLength == 0 && opened) {
|
||||||
availableLength = loadOperation.getDownloadedLengthFromOffset(currentOffset, readLength);
|
availableLength = loadOperation.getDownloadedLengthFromOffset(currentOffset, readLength);
|
||||||
if (availableLength == 0) {
|
if (availableLength == 0) {
|
||||||
FileLog.d("not found bytes " + offset);
|
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, currentOffset, false);
|
||||||
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, currentOffset);
|
|
||||||
countDownLatch = new CountDownLatch(1);
|
countDownLatch = new CountDownLatch(1);
|
||||||
countDownLatch.await();
|
countDownLatch.await();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!opened) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
file.readFully(buffer, offset, availableLength);
|
file.readFully(buffer, offset, availableLength);
|
||||||
currentOffset += availableLength;
|
currentOffset += availableLength;
|
||||||
bytesRemaining -= availableLength;
|
bytesRemaining -= availableLength;
|
||||||
|
@ -125,9 +127,6 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
||||||
if (loadOperation != null) {
|
if (loadOperation != null) {
|
||||||
loadOperation.removeStreamListener(this);
|
loadOperation.removeStreamListener(this);
|
||||||
}
|
}
|
||||||
if (countDownLatch != null) {
|
|
||||||
countDownLatch.countDown();
|
|
||||||
}
|
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
try {
|
try {
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -141,6 +140,9 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
|
||||||
opened = false;
|
opened = false;
|
||||||
transferEnded();
|
transferEnded();
|
||||||
}
|
}
|
||||||
|
if (countDownLatch != null) {
|
||||||
|
countDownLatch.countDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -777,6 +777,8 @@ public class ImageLoader {
|
||||||
int h = Math.min(512, AndroidUtilities.dp(170.6f));
|
int h = Math.min(512, AndroidUtilities.dp(170.6f));
|
||||||
boolean precache = false;
|
boolean precache = false;
|
||||||
boolean limitFps = false;
|
boolean limitFps = false;
|
||||||
|
int autoRepeat = 1;
|
||||||
|
int[] colors = null;
|
||||||
if (cacheImage.filter != null) {
|
if (cacheImage.filter != null) {
|
||||||
String[] args = cacheImage.filter.split("_");
|
String[] args = cacheImage.filter.split("_");
|
||||||
if (args.length >= 2) {
|
if (args.length >= 2) {
|
||||||
|
@ -791,8 +793,29 @@ public class ImageLoader {
|
||||||
precache = SharedConfig.getDevicePerfomanceClass() != SharedConfig.PERFORMANCE_CLASS_HIGH;
|
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);
|
onPostExecute(lottieDrawable);
|
||||||
} else if (cacheImage.animatedFile) {
|
} else if (cacheImage.animatedFile) {
|
||||||
synchronized (sync) {
|
synchronized (sync) {
|
||||||
|
@ -802,9 +825,9 @@ public class ImageLoader {
|
||||||
}
|
}
|
||||||
AnimatedFileDrawable fileDrawable;
|
AnimatedFileDrawable fileDrawable;
|
||||||
if (AUTOPLAY_FILTER.equals(cacheImage.filter) && !(cacheImage.imageLocation.document instanceof TLRPC.TL_documentEncrypted)) {
|
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 {
|
} 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();
|
Thread.interrupted();
|
||||||
onPostExecute(fileDrawable);
|
onPostExecute(fileDrawable);
|
||||||
|
|
|
@ -31,6 +31,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
|
|
||||||
public interface ImageReceiverDelegate {
|
public interface ImageReceiverDelegate {
|
||||||
void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb);
|
void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb);
|
||||||
|
default void onAnimationReady(ImageReceiver imageReceiver) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BitmapHolder {
|
public static class BitmapHolder {
|
||||||
|
@ -152,6 +154,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
private boolean allowStartAnimation = true;
|
private boolean allowStartAnimation = true;
|
||||||
private boolean useSharedAnimationQueue;
|
private boolean useSharedAnimationQueue;
|
||||||
private boolean allowDecodeSingleFrame;
|
private boolean allowDecodeSingleFrame;
|
||||||
|
private int autoRepeat = 1;
|
||||||
|
private boolean animationReadySent;
|
||||||
|
|
||||||
private boolean crossfadeWithOldImage;
|
private boolean crossfadeWithOldImage;
|
||||||
private boolean crossfadingWithThumb;
|
private boolean crossfadingWithThumb;
|
||||||
|
@ -936,6 +940,12 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
if (lottieDrawable != null) {
|
if (lottieDrawable != null) {
|
||||||
lottieDrawable.setCurrentParentView(parentView);
|
lottieDrawable.setCurrentParentView(parentView);
|
||||||
}
|
}
|
||||||
|
if ((animation != null || lottieDrawable != null) && !animationNotReady && !animationReadySent) {
|
||||||
|
animationReadySent = true;
|
||||||
|
if (delegate != null) {
|
||||||
|
delegate.onAnimationReady(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
int orientation = 0;
|
int orientation = 0;
|
||||||
BitmapShader shaderToUse = null;
|
BitmapShader shaderToUse = null;
|
||||||
if (!forcePreview && currentMediaDrawable != null && !animationNotReady) {
|
if (!forcePreview && currentMediaDrawable != null && !animationNotReady) {
|
||||||
|
@ -1399,6 +1409,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
allowDecodeSingleFrame = value;
|
allowDecodeSingleFrame = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAutoRepeat(int value) {
|
||||||
|
autoRepeat = value;
|
||||||
|
RLottieDrawable drawable = getLottieAnimation();
|
||||||
|
if (drawable != null) {
|
||||||
|
drawable.setAutoRepeat(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setUseSharedAnimationQueue(boolean value) {
|
public void setUseSharedAnimationQueue(boolean value) {
|
||||||
useSharedAnimationQueue = value;
|
useSharedAnimationQueue = value;
|
||||||
}
|
}
|
||||||
|
@ -1618,6 +1636,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
fileDrawable.start();
|
fileDrawable.start();
|
||||||
}
|
}
|
||||||
fileDrawable.setAllowDecodeSingleFrame(allowDecodeSingleFrame);
|
fileDrawable.setAllowDecodeSingleFrame(allowDecodeSingleFrame);
|
||||||
|
animationReadySent = false;
|
||||||
} else if (drawable instanceof RLottieDrawable) {
|
} else if (drawable instanceof RLottieDrawable) {
|
||||||
RLottieDrawable fileDrawable = (RLottieDrawable) drawable;
|
RLottieDrawable fileDrawable = (RLottieDrawable) drawable;
|
||||||
fileDrawable.addParentView(parentView);
|
fileDrawable.addParentView(parentView);
|
||||||
|
@ -1625,6 +1644,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
|
||||||
fileDrawable.start();
|
fileDrawable.start();
|
||||||
}
|
}
|
||||||
fileDrawable.setAllowDecodeSingleFrame(true);
|
fileDrawable.setAllowDecodeSingleFrame(true);
|
||||||
|
fileDrawable.setAutoRepeat(autoRepeat);
|
||||||
|
animationReadySent = false;
|
||||||
}
|
}
|
||||||
if (parentView != null) {
|
if (parentView != null) {
|
||||||
if (invalidateAll) {
|
if (invalidateAll) {
|
||||||
|
|
|
@ -139,6 +139,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
|
|
||||||
public static class AlbumEntry {
|
public static class AlbumEntry {
|
||||||
public int bucketId;
|
public int bucketId;
|
||||||
|
public boolean videoOnly;
|
||||||
public String bucketName;
|
public String bucketName;
|
||||||
public PhotoEntry coverPhoto;
|
public PhotoEntry coverPhoto;
|
||||||
public ArrayList<PhotoEntry> photos = new ArrayList<>();
|
public ArrayList<PhotoEntry> photos = new ArrayList<>();
|
||||||
|
@ -358,6 +359,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
public static AlbumEntry allMediaAlbumEntry;
|
public static AlbumEntry allMediaAlbumEntry;
|
||||||
public static AlbumEntry allPhotosAlbumEntry;
|
public static AlbumEntry allPhotosAlbumEntry;
|
||||||
public static AlbumEntry allVideosAlbumEntry;
|
public static AlbumEntry allVideosAlbumEntry;
|
||||||
|
public static ArrayList<AlbumEntry> allMediaAlbums = new ArrayList<>();
|
||||||
|
public static ArrayList<AlbumEntry> allPhotoAlbums = new ArrayList<>();
|
||||||
private static Runnable broadcastPhotosRunnable;
|
private static Runnable broadcastPhotosRunnable;
|
||||||
|
|
||||||
private boolean isPaused = false;
|
private boolean isPaused = false;
|
||||||
|
@ -1763,7 +1766,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
private void playNextMessageWithoutOrder(boolean byStop) {
|
private void playNextMessageWithoutOrder(boolean byStop) {
|
||||||
ArrayList<MessageObject> currentPlayList = SharedConfig.shuffleMusic ? shuffledPlaylist : playlist;
|
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);
|
cleanupPlayer(false, false);
|
||||||
MessageObject messageObject = currentPlayList.get(currentPlaylistNum);
|
MessageObject messageObject = currentPlayList.get(currentPlaylistNum);
|
||||||
messageObject.audioProgress = 0;
|
messageObject.audioProgress = 0;
|
||||||
|
@ -2081,7 +2084,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
return currentPlaybackSpeed;
|
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) {
|
if (videoPlayer == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2495,7 +2498,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
@Override
|
@Override
|
||||||
public void onStateChanged(boolean playWhenReady, int playbackState) {
|
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 (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);
|
playNextMessageWithoutOrder(true);
|
||||||
} else {
|
} else {
|
||||||
cleanupPlayer(true, true, messageObject != null && messageObject.isVoice(), false);
|
cleanupPlayer(true, true, messageObject != null && messageObject.isVoice(), false);
|
||||||
|
@ -3017,13 +3020,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
if (!destFile.exists()) {
|
if (!destFile.exists()) {
|
||||||
destFile.createNewFile();
|
destFile.createNewFile();
|
||||||
}
|
}
|
||||||
FileChannel source = null;
|
|
||||||
FileChannel destination = null;
|
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
long lastProgress = System.currentTimeMillis() - 500;
|
long lastProgress = System.currentTimeMillis() - 500;
|
||||||
try {
|
try (FileChannel source = new FileInputStream(sourceFile).getChannel(); FileChannel destination = new FileOutputStream(destFile).getChannel()) {
|
||||||
source = new FileInputStream(sourceFile).getChannel();
|
|
||||||
destination = new FileOutputStream(destFile).getChannel();
|
|
||||||
long size = source.size();
|
long size = source.size();
|
||||||
for (long a = 0; a < size; a += 4096) {
|
for (long a = 0; a < size; a += 4096) {
|
||||||
if (cancelled[0]) {
|
if (cancelled[0]) {
|
||||||
|
@ -3047,21 +3046,6 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
result = false;
|
result = false;
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (source != null) {
|
|
||||||
source.close();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (destination != null) {
|
|
||||||
destination.close();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (cancelled[0]) {
|
if (cancelled[0]) {
|
||||||
destFile.delete();
|
destFile.delete();
|
||||||
|
@ -3148,18 +3132,12 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
public static String getFileName(Uri uri) {
|
public static String getFileName(Uri uri) {
|
||||||
String result = null;
|
String result = null;
|
||||||
if (uri.getScheme().equals("content")) {
|
if (uri.getScheme().equals("content")) {
|
||||||
Cursor cursor = null;
|
try (Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null)) {
|
||||||
try {
|
|
||||||
cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, new String[]{OpenableColumns.DISPLAY_NAME}, null, null, null);
|
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
} finally {
|
|
||||||
if (cursor != null) {
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
@ -3340,6 +3318,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
|
|
||||||
if (allVideosAlbum == null) {
|
if (allVideosAlbum == null) {
|
||||||
allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideos", R.string.AllVideos), photoEntry);
|
allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideos", R.string.AllVideos), photoEntry);
|
||||||
|
allVideosAlbum.videoOnly = true;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
if (allMediaAlbum != null) {
|
if (allMediaAlbum != null) {
|
||||||
index++;
|
index++;
|
||||||
|
@ -3408,6 +3387,8 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
|
||||||
broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, cameraAlbumIdFinal, allMediaAlbumFinal, allPhotosAlbumFinal, allVideosAlbumFinal, 1000);
|
broadcastNewPhotos(guid, mediaAlbumsSorted, photoAlbumsSorted, cameraAlbumIdFinal, allMediaAlbumFinal, allPhotosAlbumFinal, allVideosAlbumFinal, 1000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
allMediaAlbums = mediaAlbumsSorted;
|
||||||
|
allPhotoAlbums = photoAlbumsSorted;
|
||||||
broadcastPhotosRunnable = null;
|
broadcastPhotosRunnable = null;
|
||||||
allPhotosAlbumEntry = allPhotosAlbumFinal;
|
allPhotosAlbumEntry = allPhotosAlbumFinal;
|
||||||
allMediaAlbumEntry = allMediaAlbumFinal;
|
allMediaAlbumEntry = allMediaAlbumFinal;
|
||||||
|
|
|
@ -120,16 +120,18 @@ public class MediaDataController extends BaseController {
|
||||||
public static final int TYPE_MASK = 1;
|
public static final int TYPE_MASK = 1;
|
||||||
public static final int TYPE_FAVE = 2;
|
public static final int TYPE_FAVE = 2;
|
||||||
public static final int TYPE_FEATURED = 3;
|
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> stickerSetsById = new LongSparseArray<>();
|
||||||
private LongSparseArray<TLRPC.TL_messages_stickerSet> installedStickerSetsById = new LongSparseArray<>();
|
private LongSparseArray<TLRPC.TL_messages_stickerSet> installedStickerSetsById = new LongSparseArray<>();
|
||||||
private LongSparseArray<TLRPC.TL_messages_stickerSet> groupStickerSets = new LongSparseArray<>();
|
private LongSparseArray<TLRPC.TL_messages_stickerSet> groupStickerSets = new LongSparseArray<>();
|
||||||
private HashMap<String, TLRPC.TL_messages_stickerSet> stickerSetsByName = new HashMap<>();
|
private HashMap<String, TLRPC.TL_messages_stickerSet> stickerSetsByName = new HashMap<>();
|
||||||
private boolean[] loadingStickers = new boolean[4];
|
private boolean[] loadingStickers = new boolean[5];
|
||||||
private boolean[] stickersLoaded = new boolean[4];
|
private boolean[] stickersLoaded = new boolean[5];
|
||||||
private int[] loadHash = new int[4];
|
private int[] loadHash = new int[5];
|
||||||
private int[] loadDate = new int[4];
|
private int[] loadDate = new int[5];
|
||||||
|
|
||||||
private int[] archivedStickersCount = new int[2];
|
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) {
|
public void addRecentSticker(final int type, Object parentObject, TLRPC.Document document, int date, boolean remove) {
|
||||||
|
if (document == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (int a = 0; a < recentStickers[type].size(); a++) {
|
for (int a = 0; a < recentStickers[type].size(); a++) {
|
||||||
TLRPC.Document image = recentStickers[type].get(a);
|
TLRPC.Document image = recentStickers[type].get(a);
|
||||||
|
@ -392,26 +397,44 @@ public class MediaDataController extends BaseController {
|
||||||
if (existingSet == null) {
|
if (existingSet == null) {
|
||||||
return;
|
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;
|
boolean changed = false;
|
||||||
for (int a = 0, size = existingSet.documents.size(); a < size; a++) {
|
if ("AnimatedEmojies".equals(set.set.short_name)) {
|
||||||
TLRPC.Document document = set.documents.get(a);
|
changed = true;
|
||||||
TLRPC.Document newDocument = documents.get(document.id);
|
existingSet.documents = set.documents;
|
||||||
if (newDocument != null) {
|
existingSet.packs = set.packs;
|
||||||
existingSet.documents.set(a, newDocument);
|
existingSet.set = set.set;
|
||||||
changed = true;
|
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 (changed) {
|
||||||
if (isGroupSet) {
|
if (isGroupSet) {
|
||||||
putSetToCache(existingSet);
|
putSetToCache(existingSet);
|
||||||
} else {
|
} 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]);
|
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;
|
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() {
|
public boolean canAddStickerToFavorites() {
|
||||||
return !stickersLoaded[0] || stickerSets[0].size() >= 5 || !recentStickers[TYPE_FAVE].isEmpty();
|
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() {
|
public ArrayList<TLRPC.StickerSetCovered> getFeaturedStickerSets() {
|
||||||
return featuredStickerSets;
|
return featuredStickerSets;
|
||||||
}
|
}
|
||||||
|
@ -1185,7 +1228,7 @@ public class MediaDataController extends BaseController {
|
||||||
if (featuredStickerSets.isEmpty() || !getMessagesController().preloadFeaturedStickers) {
|
if (featuredStickerSets.isEmpty() || !getMessagesController().preloadFeaturedStickers) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (type != TYPE_EMOJI) {
|
||||||
loadArchivedStickersCount(type, cache);
|
loadArchivedStickersCount(type, cache);
|
||||||
}
|
}
|
||||||
loadingStickers[type] = true;
|
loadingStickers[type] = true;
|
||||||
|
@ -1228,24 +1271,36 @@ public class MediaDataController extends BaseController {
|
||||||
response.sets.add(featuredStickerSets.get(a).set);
|
response.sets.add(featuredStickerSets.get(a).set);
|
||||||
}
|
}
|
||||||
processLoadStickersResponse(type, response);
|
processLoadStickersResponse(type, response);
|
||||||
return;
|
} else if (type == TYPE_EMOJI) {
|
||||||
}
|
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
|
||||||
TLObject req;
|
req.stickerset = new TLRPC.TL_inputStickerSetAnimatedEmoji();
|
||||||
final int hash;
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||||
if (type == TYPE_IMAGE) {
|
if (response instanceof TLRPC.TL_messages_stickerSet) {
|
||||||
req = new TLRPC.TL_messages_getAllStickers();
|
final ArrayList<TLRPC.TL_messages_stickerSet> newStickerArray = new ArrayList<>();
|
||||||
hash = ((TLRPC.TL_messages_getAllStickers) req).hash = force ? 0 : loadHash[type];
|
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 {
|
} else {
|
||||||
req = new TLRPC.TL_messages_getMaskStickers();
|
TLObject req;
|
||||||
hash = ((TLRPC.TL_messages_getMaskStickers) req).hash = force ? 0 : loadHash[type];
|
final int hash;
|
||||||
}
|
if (type == TYPE_IMAGE) {
|
||||||
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
req = new TLRPC.TL_messages_getAllStickers();
|
||||||
if (response instanceof TLRPC.TL_messages_allStickers) {
|
hash = ((TLRPC.TL_messages_getAllStickers) req).hash = force ? 0 : loadHash[type];
|
||||||
processLoadStickersResponse(type, (TLRPC.TL_messages_allStickers) response);
|
|
||||||
} else {
|
} 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++) {
|
for (int a = 0; a < stickerSets[type].size(); a++) {
|
||||||
TLRPC.StickerSet set = stickerSets[type].get(a).set;
|
TLRPC.StickerSet set = stickerSets[type].get(a).set;
|
||||||
stickerSetsById.remove(set.id);
|
stickerSetsById.remove(set.id);
|
||||||
installedStickerSetsById.remove(set.id);
|
|
||||||
stickerSetsByName.remove(set.short_name);
|
stickerSetsByName.remove(set.short_name);
|
||||||
|
if (type != TYPE_FEATURED && type != TYPE_EMOJI) {
|
||||||
|
installedStickerSetsById.remove(set.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int a = 0; a < stickerSetsByIdNew.size(); a++) {
|
for (int a = 0; a < stickerSetsByIdNew.size(); a++) {
|
||||||
stickerSetsById.put(stickerSetsByIdNew.keyAt(a), stickerSetsByIdNew.valueAt(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));
|
installedStickerSetsById.put(stickerSetsByIdNew.keyAt(a), stickerSetsByIdNew.valueAt(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1424,6 +1481,7 @@ public class MediaDataController extends BaseController {
|
||||||
stickerSets[type] = stickerSetsNew;
|
stickerSets[type] = stickerSetsNew;
|
||||||
loadHash[type] = hash;
|
loadHash[type] = hash;
|
||||||
loadDate[type] = date;
|
loadDate[type] = date;
|
||||||
|
stickersByIds[type] = stickersByIdNew;
|
||||||
if (type == TYPE_IMAGE) {
|
if (type == TYPE_IMAGE) {
|
||||||
allStickers = allStickersNew;
|
allStickers = allStickersNew;
|
||||||
stickersByEmoji = stickersByEmojiNew;
|
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) {
|
public static void addStyleToText(TextStyleSpan span, int start, int end, Spannable editable, boolean allowIntersection) {
|
||||||
try {
|
try {
|
||||||
allowIntersection = true;
|
|
||||||
CharacterStyle[] spans = editable.getSpans(start, end, CharacterStyle.class);
|
CharacterStyle[] spans = editable.getSpans(start, end, CharacterStyle.class);
|
||||||
if (spans != null && spans.length > 0) {
|
if (spans != null && spans.length > 0) {
|
||||||
for (int a = 0; a < spans.length; a++) {
|
for (int a = 0; a < spans.length; a++) {
|
||||||
|
|
|
@ -75,6 +75,8 @@ public class MessageObject {
|
||||||
public boolean localChannel;
|
public boolean localChannel;
|
||||||
public boolean localEdit;
|
public boolean localEdit;
|
||||||
public TLRPC.Message messageOwner;
|
public TLRPC.Message messageOwner;
|
||||||
|
public TLRPC.Document emojiAnimatedSticker;
|
||||||
|
public String emojiAnimatedStickerColor;
|
||||||
public CharSequence messageText;
|
public CharSequence messageText;
|
||||||
public CharSequence linkDescription;
|
public CharSequence linkDescription;
|
||||||
public CharSequence caption;
|
public CharSequence caption;
|
||||||
|
@ -87,6 +89,7 @@ public class MessageObject {
|
||||||
public String monthKey;
|
public String monthKey;
|
||||||
public boolean deleted;
|
public boolean deleted;
|
||||||
public float audioProgress;
|
public float audioProgress;
|
||||||
|
public float forceSeekTo = -1;
|
||||||
public int audioProgressMs;
|
public int audioProgressMs;
|
||||||
public float bufferedProgress;
|
public float bufferedProgress;
|
||||||
public float gifState;
|
public float gifState;
|
||||||
|
@ -141,6 +144,7 @@ public class MessageObject {
|
||||||
|
|
||||||
public static Pattern urlPattern;
|
public static Pattern urlPattern;
|
||||||
public static Pattern instagramUrlPattern;
|
public static Pattern instagramUrlPattern;
|
||||||
|
public static Pattern videoTimeUrlPattern;
|
||||||
|
|
||||||
public CharSequence vCardData;
|
public CharSequence vCardData;
|
||||||
|
|
||||||
|
@ -745,7 +749,11 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageObject(int accountNum, TLRPC.Message message, boolean generateLayout) {
|
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) {
|
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) {
|
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) {
|
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);
|
Theme.createChatResources(null, true);
|
||||||
|
|
||||||
currentAccount = accountNum;
|
currentAccount = accountNum;
|
||||||
messageOwner = message;
|
messageOwner = message;
|
||||||
|
replyMessageObject = replyToMessage;
|
||||||
eventId = eid;
|
eventId = eid;
|
||||||
|
|
||||||
if (message.replyMessage != null) {
|
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;
|
TLRPC.User fromUser = null;
|
||||||
|
@ -807,7 +816,40 @@ public class MessageObject {
|
||||||
int[] emojiOnly = SharedConfig.allowBigEmoji ? new int[1] : null;
|
int[] emojiOnly = SharedConfig.allowBigEmoji ? new int[1] : null;
|
||||||
messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly);
|
messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly);
|
||||||
checkEmojiOnly(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;
|
layoutCreated = generateLayout;
|
||||||
generateThumbs(false);
|
generateThumbs(false);
|
||||||
|
@ -966,6 +1008,15 @@ public class MessageObject {
|
||||||
if (n == null) {
|
if (n == null) {
|
||||||
n = new TLRPC.TL_chatAdminRights();
|
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) {
|
if (o.change_info != n.change_info) {
|
||||||
rights.append('\n').append(n.change_info ? '+' : '-').append(' ');
|
rights.append('\n').append(n.change_info ? '+' : '-').append(' ');
|
||||||
rights.append(chat.megagroup ? LocaleController.getString("EventLogPromotedChangeGroupInfo", R.string.EventLogPromotedChangeGroupInfo) : LocaleController.getString("EventLogPromotedChangeChannelInfo", R.string.EventLogPromotedChangeChannelInfo));
|
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;
|
TLRPC.TL_channelLocation channelLocation = (TLRPC.TL_channelLocation) location.new_value;
|
||||||
messageText = replaceWithLink(LocaleController.formatString("EventLogChangedLocation", R.string.EventLogChangedLocation, channelLocation.address), "un1", fromUser);
|
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 {
|
} else {
|
||||||
messageText = "unsupported " + event.action;
|
messageText = "unsupported " + event.action;
|
||||||
}
|
}
|
||||||
|
@ -2224,7 +2290,7 @@ public class MessageObject {
|
||||||
} else {
|
} else {
|
||||||
messageText = LocaleController.getString("AttachPhoto", R.string.AttachPhoto);
|
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)) {
|
if (messageOwner.media.ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) {
|
||||||
messageText = LocaleController.getString("AttachDestructingVideo", R.string.AttachDestructingVideo);
|
messageText = LocaleController.getString("AttachDestructingVideo", R.string.AttachDestructingVideo);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2262,7 +2328,7 @@ public class MessageObject {
|
||||||
} else if (isGif()) {
|
} else if (isGif()) {
|
||||||
messageText = LocaleController.getString("AttachGif", R.string.AttachGif);
|
messageText = LocaleController.getString("AttachGif", R.string.AttachGif);
|
||||||
} else {
|
} else {
|
||||||
String name = FileLoader.getDocumentFileName(messageOwner.media.document);
|
String name = FileLoader.getDocumentFileName(getDocument());
|
||||||
if (name != null && name.length() > 0) {
|
if (name != null && name.length() > 0) {
|
||||||
messageText = name;
|
messageText = name;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2283,12 +2349,18 @@ public class MessageObject {
|
||||||
int oldType = type;
|
int oldType = type;
|
||||||
isRoundVideoCached = 0;
|
isRoundVideoCached = 0;
|
||||||
if (messageOwner instanceof TLRPC.TL_message || messageOwner instanceof TLRPC.TL_messageForwarded_old2) {
|
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;
|
type = 0;
|
||||||
if (TextUtils.isEmpty(messageText) && eventId == 0) {
|
if (TextUtils.isEmpty(messageText) && eventId == 0) {
|
||||||
messageText = "Empty message";
|
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;
|
contentType = 1;
|
||||||
type = 10;
|
type = 10;
|
||||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||||
|
@ -2310,8 +2382,9 @@ public class MessageObject {
|
||||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) {
|
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) {
|
||||||
type = 0;
|
type = 0;
|
||||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||||
if (messageOwner.media.document != null && messageOwner.media.document.mime_type != null) {
|
TLRPC.Document document = getDocument();
|
||||||
if (isGifDocument(messageOwner.media.document)) {
|
if (document != null && document.mime_type != null) {
|
||||||
|
if (isGifDocument(document)) {
|
||||||
type = 8;
|
type = 8;
|
||||||
} else if (isSticker()) {
|
} else if (isSticker()) {
|
||||||
type = TYPE_STICKER;
|
type = TYPE_STICKER;
|
||||||
|
@ -2394,8 +2467,9 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMimeType() {
|
public String getMimeType() {
|
||||||
if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
TLRPC.Document document = getDocument();
|
||||||
return messageOwner.media.document.mime_type;
|
if (document != null) {
|
||||||
|
return document.mime_type;
|
||||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) {
|
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) {
|
||||||
TLRPC.WebDocument photo = ((TLRPC.TL_messageMediaInvoice) messageOwner.media).photo;
|
TLRPC.WebDocument photo = ((TLRPC.TL_messageMediaInvoice) messageOwner.media).photo;
|
||||||
if (photo != null) {
|
if (photo != null) {
|
||||||
|
@ -2404,9 +2478,7 @@ public class MessageObject {
|
||||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||||
return "image/jpeg";
|
return "image/jpeg";
|
||||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
|
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) {
|
||||||
if (messageOwner.media.webpage.document != null) {
|
if (messageOwner.media.webpage.photo != null) {
|
||||||
return messageOwner.media.document.mime_type;
|
|
||||||
} else if (messageOwner.media.webpage.photo != null) {
|
|
||||||
return "image/jpeg";
|
return "image/jpeg";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2551,6 +2623,16 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
photoThumbsObject = messageOwner.action.photo;
|
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)) {
|
} else if (messageOwner.media != null && !(messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) {
|
||||||
if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||||
TLRPC.Photo photo = messageOwner.media.photo;
|
TLRPC.Photo photo = messageOwner.media.photo;
|
||||||
|
@ -2576,7 +2658,7 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
photoThumbsObject = messageOwner.media.photo;
|
photoThumbsObject = messageOwner.media.photo;
|
||||||
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
||||||
TLRPC.Document document = messageOwner.media.document;
|
TLRPC.Document document = getDocument();
|
||||||
if (isDocumentHasThumb(document)) {
|
if (isDocumentHasThumb(document)) {
|
||||||
if (!update || photoThumbs == null) {
|
if (!update || photoThumbs == null) {
|
||||||
photoThumbs = new ArrayList<>();
|
photoThumbs = new ArrayList<>();
|
||||||
|
@ -2719,7 +2801,7 @@ public class MessageObject {
|
||||||
ext = fileName.substring(idx + 1);
|
ext = fileName.substring(idx + 1);
|
||||||
}
|
}
|
||||||
if (ext == null || ext.length() == 0) {
|
if (ext == null || ext.length() == 0) {
|
||||||
ext = messageOwner.media.document.mime_type;
|
ext = getDocument().mime_type;
|
||||||
}
|
}
|
||||||
if (ext == null) {
|
if (ext == null) {
|
||||||
ext = "";
|
ext = "";
|
||||||
|
@ -2730,7 +2812,7 @@ public class MessageObject {
|
||||||
|
|
||||||
public String getFileName() {
|
public String getFileName() {
|
||||||
if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
|
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) {
|
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
|
||||||
ArrayList<TLRPC.PhotoSize> sizes = messageOwner.media.photo.sizes;
|
ArrayList<TLRPC.PhotoSize> sizes = messageOwner.media.photo.sizes;
|
||||||
if (sizes.size() > 0) {
|
if (sizes.size() > 0) {
|
||||||
|
@ -2852,7 +2934,7 @@ public class MessageObject {
|
||||||
if (!(linkDescription instanceof Spannable)) {
|
if (!(linkDescription instanceof Spannable)) {
|
||||||
linkDescription = new SpannableStringBuilder(linkDescription);
|
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);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addUsernamesAndHashtags(isOutOwner(), caption, true, 0);
|
addUrlsByPattern(isOutOwner(), caption, true, 0, 0);
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
Linkify.addLinks((Spannable) caption, Linkify.PHONE_NUMBERS);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
FileLog.e(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addEntitiesToText(caption, useManualParse);
|
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 {
|
try {
|
||||||
Matcher matcher;
|
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) {
|
if (instagramUrlPattern == null) {
|
||||||
instagramUrlPattern = Pattern.compile("(^|\\s|\\()@[a-zA-Z\\d_.]{1,32}|(^|\\s|\\()#[\\w.]+");
|
instagramUrlPattern = Pattern.compile("(^|\\s|\\()@[a-zA-Z\\d_.]{1,32}|(^|\\s|\\()#[\\w.]+");
|
||||||
}
|
}
|
||||||
|
@ -2923,47 +3007,73 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
matcher = urlPattern.matcher(charSequence);
|
matcher = urlPattern.matcher(charSequence);
|
||||||
}
|
}
|
||||||
|
Spannable spannable = (Spannable) charSequence;
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
int start = matcher.start();
|
int start = matcher.start();
|
||||||
int end = matcher.end();
|
int end = matcher.end();
|
||||||
char ch = charSequence.charAt(start);
|
URLSpanNoUnderline url = null;
|
||||||
if (hashtagsType != 0) {
|
if (patternType == 3) {
|
||||||
if (ch != '@' && ch != '#') {
|
URLSpan[] spans = spannable.getSpans(start, end, URLSpan.class);
|
||||||
start++;
|
if (spans != null && spans.length > 0) {
|
||||||
}
|
|
||||||
ch = charSequence.charAt(start);
|
|
||||||
if (ch != '@' && ch != '#') {
|
|
||||||
continue;
|
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 {
|
} else {
|
||||||
if (ch != '@' && ch != '#' && ch != '/' && ch != '$') {
|
char ch = charSequence.charAt(start);
|
||||||
start++;
|
if (patternType != 0) {
|
||||||
}
|
if (ch != '@' && ch != '#') {
|
||||||
}
|
start++;
|
||||||
URLSpanNoUnderline url = null;
|
}
|
||||||
if (hashtagsType == 1) {
|
ch = charSequence.charAt(start);
|
||||||
if (ch == '@') {
|
if (ch != '@' && ch != '#') {
|
||||||
url = new URLSpanNoUnderline("https://instagram.com/" + charSequence.subSequence(start + 1, end).toString());
|
continue;
|
||||||
} 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);
|
|
||||||
}
|
}
|
||||||
} else {
|
} 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) {
|
if (url != null) {
|
||||||
((Spannable) charSequence).setSpan(url, start, end, 0);
|
spannable.setSpan(url, start, end, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -3051,7 +3161,7 @@ public class MessageObject {
|
||||||
FileLog.e(e);
|
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_messageEntityCode ||
|
||||||
entity instanceof TLRPC.TL_messageEntityPre ||
|
entity instanceof TLRPC.TL_messageEntityPre ||
|
||||||
entity instanceof TLRPC.TL_messageEntityMentionName ||
|
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) {
|
if (spans != null && spans.length > 0) {
|
||||||
for (int b = 0; b < spans.length; b++) {
|
for (int b = 0; b < spans.length; b++) {
|
||||||
if (spans[b] == null) {
|
if (spans[b] == null) {
|
||||||
|
@ -3161,7 +3272,7 @@ public class MessageObject {
|
||||||
newRun.flags = TextStyleSpan.FLAG_STYLE_MENTION;
|
newRun.flags = TextStyleSpan.FLAG_STYLE_MENTION;
|
||||||
newRun.urlEntity = entity;
|
newRun.urlEntity = entity;
|
||||||
} else {
|
} else {
|
||||||
if (useManualParse) {
|
if (useManualParse && !(entity instanceof TLRPC.TL_messageEntityTextUrl)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((entity instanceof TLRPC.TL_messageEntityUrl || entity instanceof TLRPC.TL_messageEntityTextUrl) && Browser.isPassportUrl(entity.url)) {
|
if ((entity instanceof TLRPC.TL_messageEntityUrl || entity instanceof TLRPC.TL_messageEntityTextUrl) && Browser.isPassportUrl(entity.url)) {
|
||||||
|
@ -3313,6 +3424,10 @@ public class MessageObject {
|
||||||
return false;
|
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() {
|
public int getMaxMessageTextWidth() {
|
||||||
int maxWidth = 0;
|
int maxWidth = 0;
|
||||||
if (AndroidUtilities.isTablet() && eventId != 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);
|
boolean hasUrls = addEntitiesToText(messageText, useManualParse);
|
||||||
|
|
||||||
|
@ -3894,13 +4014,7 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDocumentName() {
|
public String getDocumentName() {
|
||||||
TLRPC.Document document;
|
return FileLoader.getDocumentFileName(getDocument());
|
||||||
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 "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isStickerDocument(TLRPC.Document document) {
|
public static boolean isStickerDocument(TLRPC.Document document) {
|
||||||
|
@ -4010,6 +4124,9 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TLRPC.Document getDocument() {
|
public TLRPC.Document getDocument() {
|
||||||
|
if (emojiAnimatedSticker != null) {
|
||||||
|
return emojiAnimatedSticker;
|
||||||
|
}
|
||||||
return getDocument(messageOwner);
|
return getDocument(messageOwner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4108,13 +4225,22 @@ public class MessageObject {
|
||||||
|
|
||||||
public static TLRPC.InputStickerSet getInputStickerSet(TLRPC.Message message) {
|
public static TLRPC.InputStickerSet getInputStickerSet(TLRPC.Message message) {
|
||||||
if (message.media != null && message.media.document != null) {
|
if (message.media != null && message.media.document != null) {
|
||||||
for (TLRPC.DocumentAttribute attribute : message.media.document.attributes) {
|
return getInputStickerSet(message.media.document);
|
||||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
}
|
||||||
if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetEmpty) {
|
return null;
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
return attribute.stickerset;
|
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;
|
return null;
|
||||||
|
@ -4137,8 +4263,9 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStrickerChar() {
|
public String getStrickerChar() {
|
||||||
if (messageOwner.media != null && messageOwner.media.document != null) {
|
TLRPC.Document document = getDocument();
|
||||||
for (TLRPC.DocumentAttribute attribute : messageOwner.media.document.attributes) {
|
if (document != null) {
|
||||||
|
for (TLRPC.DocumentAttribute attribute : document.attributes) {
|
||||||
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
||||||
return attribute.alt;
|
return attribute.alt;
|
||||||
}
|
}
|
||||||
|
@ -4180,7 +4307,9 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
int photoHeight = 0;
|
int photoHeight = 0;
|
||||||
int photoWidth = 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) {
|
if (attribute instanceof TLRPC.TL_documentAttributeImageSize) {
|
||||||
photoWidth = attribute.w;
|
photoWidth = attribute.w;
|
||||||
photoHeight = attribute.h;
|
photoHeight = attribute.h;
|
||||||
|
@ -4242,8 +4371,12 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStickerEmoji() {
|
public String getStickerEmoji() {
|
||||||
for (int a = 0; a < messageOwner.media.document.attributes.size(); a++) {
|
TLRPC.Document document = getDocument();
|
||||||
TLRPC.DocumentAttribute attribute = messageOwner.media.document.attributes.get(a);
|
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) {
|
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
|
||||||
return attribute.alt != null && attribute.alt.length() > 0 ? attribute.alt : null;
|
return attribute.alt != null && attribute.alt.length() > 0 ? attribute.alt : null;
|
||||||
}
|
}
|
||||||
|
@ -4251,18 +4384,22 @@ public class MessageObject {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAnimatedEmoji() {
|
||||||
|
return emojiAnimatedSticker != null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSticker() {
|
public boolean isSticker() {
|
||||||
if (type != 1000) {
|
if (type != 1000) {
|
||||||
return type == TYPE_STICKER;
|
return type == TYPE_STICKER;
|
||||||
}
|
}
|
||||||
return isStickerMessage(messageOwner);
|
return isStickerDocument(getDocument());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAnimatedSticker() {
|
public boolean isAnimatedSticker() {
|
||||||
if (type != 1000) {
|
if (type != 1000) {
|
||||||
return type == TYPE_ANIMATED_STICKER;
|
return type == TYPE_ANIMATED_STICKER;
|
||||||
}
|
}
|
||||||
return isAnimatedStickerMessage(messageOwner);
|
return isAnimatedStickerDocument(getDocument());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAnyKindOfSticker() {
|
public boolean isAnyKindOfSticker() {
|
||||||
|
|
|
@ -104,6 +104,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
|
|
||||||
public boolean loadingBlockedUsers = false;
|
public boolean loadingBlockedUsers = false;
|
||||||
public SparseIntArray blockedUsers = new SparseIntArray();
|
public SparseIntArray blockedUsers = new SparseIntArray();
|
||||||
|
public int totalBlockedCount = -1;
|
||||||
|
public boolean blockedEndReached;
|
||||||
|
|
||||||
private SparseArray<ArrayList<Integer>> channelViewsToSend = new SparseArray<>();
|
private SparseArray<ArrayList<Integer>> channelViewsToSend = new SparseArray<>();
|
||||||
private LongSparseArray<SparseArray<MessageObject>> pollsToCheck = new LongSparseArray<>();
|
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> loadingFullParticipants = new ArrayList<>();
|
||||||
private ArrayList<Integer> loadedFullParticipants = new ArrayList<>();
|
private ArrayList<Integer> loadedFullParticipants = new ArrayList<>();
|
||||||
private ArrayList<Integer> loadedFullChats = 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 loadingChannelAdmins = new SparseIntArray();
|
||||||
|
|
||||||
private SparseIntArray migratedChats = new SparseIntArray();
|
private SparseIntArray migratedChats = new SparseIntArray();
|
||||||
|
@ -205,6 +207,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
private boolean uploadingWallpaperBlurred;
|
private boolean uploadingWallpaperBlurred;
|
||||||
private boolean uploadingWallpaperMotion;
|
private boolean uploadingWallpaperMotion;
|
||||||
|
|
||||||
|
private boolean loadingAppConfig;
|
||||||
|
|
||||||
public boolean enableJoined;
|
public boolean enableJoined;
|
||||||
public String linkPrefix;
|
public String linkPrefix;
|
||||||
public int maxGroupCount;
|
public int maxGroupCount;
|
||||||
|
@ -233,6 +237,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
public boolean blockedCountry;
|
public boolean blockedCountry;
|
||||||
public boolean defaultP2pContacts;
|
public boolean defaultP2pContacts;
|
||||||
public boolean preloadFeaturedStickers;
|
public boolean preloadFeaturedStickers;
|
||||||
|
public float animatedEmojisZoom;
|
||||||
public String venueSearchBot;
|
public String venueSearchBot;
|
||||||
public String gifSearchBot;
|
public String gifSearchBot;
|
||||||
public String imageSearchBot;
|
public String imageSearchBot;
|
||||||
|
@ -435,14 +440,46 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
gifSearchBot = mainPreferences.getString("gifSearchBot", "gif");
|
gifSearchBot = mainPreferences.getString("gifSearchBot", "gif");
|
||||||
imageSearchBot = mainPreferences.getString("imageSearchBot", "pic");
|
imageSearchBot = mainPreferences.getString("imageSearchBot", "pic");
|
||||||
blockedCountry = mainPreferences.getBoolean("blockedCountry", false);
|
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);
|
webFileDatacenterId = mainPreferences.getInt("webFileDatacenterId", ConnectionsManager.native_isTestBackend(currentAccount) != 0 ? 2 : 4);
|
||||||
suggestedLangCode = mainPreferences.getString("suggestedLangCode", "en");
|
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) {
|
public void updateConfig(final TLRPC.TL_config config) {
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
getDownloadController().loadAutoDownloadConfig(false);
|
getDownloadController().loadAutoDownloadConfig(false);
|
||||||
|
loadAppConfig();
|
||||||
maxMegagroupCount = config.megagroup_size_max;
|
maxMegagroupCount = config.megagroup_size_max;
|
||||||
maxGroupCount = config.chat_size_max;
|
maxGroupCount = config.chat_size_max;
|
||||||
maxEditTime = config.edit_time_limit;
|
maxEditTime = config.edit_time_limit;
|
||||||
|
@ -563,7 +600,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
editor.putString("venueSearchBot", venueSearchBot);
|
editor.putString("venueSearchBot", venueSearchBot);
|
||||||
editor.putString("gifSearchBot", gifSearchBot);
|
editor.putString("gifSearchBot", gifSearchBot);
|
||||||
editor.putString("imageSearchBot", imageSearchBot);
|
editor.putString("imageSearchBot", imageSearchBot);
|
||||||
editor.putString("dcDomainName", dcDomainName);
|
editor.putString("dcDomainName2", dcDomainName);
|
||||||
editor.putInt("webFileDatacenterId", webFileDatacenterId);
|
editor.putInt("webFileDatacenterId", webFileDatacenterId);
|
||||||
editor.putString("suggestedLangCode", suggestedLangCode);
|
editor.putString("suggestedLangCode", suggestedLangCode);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
|
@ -783,6 +820,16 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
dialogMessagesByIds.put(newMsgId, obj);
|
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) {
|
} else if (id == NotificationCenter.updateMessageMedia) {
|
||||||
TLRPC.Message message = (TLRPC.Message) args[0];
|
TLRPC.Message message = (TLRPC.Message) args[0];
|
||||||
MessageObject existMessageObject = dialogMessagesByIds.get(message.id);
|
MessageObject existMessageObject = dialogMessagesByIds.get(message.id);
|
||||||
|
@ -812,7 +859,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
editor = emojiPreferences.edit();
|
editor = emojiPreferences.edit();
|
||||||
editor.putLong("lastGifLoadTime", 0).putLong("lastStickersLoadTime", 0).putLong("lastStickersLoadTimeMask", 0).putLong("lastStickersLoadTimeFavs", 0).commit();
|
editor.putLong("lastGifLoadTime", 0).putLong("lastStickersLoadTime", 0).putLong("lastStickersLoadTimeMask", 0).putLong("lastStickersLoadTimeFavs", 0).commit();
|
||||||
editor = mainPreferences.edit();
|
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();
|
reloadingWebpages.clear();
|
||||||
reloadingWebpagesPending.clear();
|
reloadingWebpagesPending.clear();
|
||||||
|
@ -889,6 +936,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
dialogsEndReached.clear();
|
dialogsEndReached.clear();
|
||||||
serverDialogsEndReached.clear();
|
serverDialogsEndReached.clear();
|
||||||
|
|
||||||
|
loadingAppConfig = false;
|
||||||
|
|
||||||
checkingTosUpdate = false;
|
checkingTosUpdate = false;
|
||||||
nextTosCheckTime = 0;
|
nextTosCheckTime = 0;
|
||||||
nextProxyInfoCheckTime = 0;
|
nextProxyInfoCheckTime = 0;
|
||||||
|
@ -900,6 +949,8 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
currentDeletingTaskChannelId = 0;
|
currentDeletingTaskChannelId = 0;
|
||||||
gettingNewDeleteTask = false;
|
gettingNewDeleteTask = false;
|
||||||
loadingBlockedUsers = false;
|
loadingBlockedUsers = false;
|
||||||
|
totalBlockedCount = -1;
|
||||||
|
blockedEndReached = false;
|
||||||
firstGettingTask = false;
|
firstGettingTask = false;
|
||||||
updatingState = false;
|
updatingState = false;
|
||||||
resetingDialogs = false;
|
resetingDialogs = false;
|
||||||
|
@ -1395,53 +1446,69 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isChannelAdmin(int chatId, int uid) {
|
public String getAdminRank(int chatId, int uid) {
|
||||||
ArrayList<Integer> array = channelAdmins.get(chatId);
|
SparseArray<String> array = channelAdmins.get(chatId);
|
||||||
return array != null && array.indexOf(uid) >= 0;
|
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) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
loadingChannelAdmins.put(chatId, 0);
|
loadingChannelAdmins.put(chatId, (int) (SystemClock.uptimeMillis() / 1000));
|
||||||
if (cache) {
|
if (cache) {
|
||||||
getMessagesStorage().loadChannelAdmins(chatId);
|
getMessagesStorage().loadChannelAdmins(chatId);
|
||||||
} else {
|
} else {
|
||||||
TLRPC.TL_channels_getParticipants req = new TLRPC.TL_channels_getParticipants();
|
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) {
|
if (array != null) {
|
||||||
long acc = 0;
|
ArrayList<Integer> values = new ArrayList<>();
|
||||||
for (int a = 0; a < array.size(); a++) {
|
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.hash = (int) acc;
|
||||||
}
|
}*/
|
||||||
req.channel = getInputChannel(chatId);
|
req.channel = getInputChannel(chatId);
|
||||||
req.limit = 100;
|
req.limit = 100;
|
||||||
req.filter = new TLRPC.TL_channelParticipantsAdmins();
|
req.filter = new TLRPC.TL_channelParticipantsAdmins();
|
||||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||||
if (response instanceof TLRPC.TL_channels_channelParticipants) {
|
if (response instanceof TLRPC.TL_channels_channelParticipants) {
|
||||||
TLRPC.TL_channels_channelParticipants participants = (TLRPC.TL_channels_channelParticipants) response;
|
processLoadedAdminsResponse(chatId, (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);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processLoadedChannelAdmins(final ArrayList<Integer> array, final int chatId, final boolean cache) {
|
public void processLoadedAdminsResponse(int chatId, TLRPC.TL_channels_channelParticipants participants) {
|
||||||
Collections.sort(array);
|
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) {
|
if (!cache) {
|
||||||
getMessagesStorage().putChannelAdmins(chatId, array);
|
getMessagesStorage().putChannelAdmins(chatId, array);
|
||||||
}
|
}
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
loadingChannelAdmins.delete(chatId);
|
|
||||||
channelAdmins.put(chatId, array);
|
channelAdmins.put(chatId, array);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
|
loadingChannelAdmins.delete(chatId);
|
||||||
loadChannelAdmins(chatId, false);
|
loadChannelAdmins(chatId, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1564,17 +1631,11 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
int index = blockedUsers.indexOfKey(user.id);
|
int index = blockedUsers.indexOfKey(user.id);
|
||||||
if (userFull.blocked) {
|
if (userFull.blocked) {
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
SparseIntArray ids = new SparseIntArray();
|
|
||||||
ids.put(user.id, 1);
|
|
||||||
getMessagesStorage().putBlockedUsers(ids, false);
|
|
||||||
|
|
||||||
blockedUsers.put(user.id, 1);
|
blockedUsers.put(user.id, 1);
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
getMessagesStorage().deleteBlockedUser(user.id);
|
|
||||||
|
|
||||||
blockedUsers.removeAt(index);
|
blockedUsers.removeAt(index);
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
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();
|
TLRPC.TL_contacts_block req = new TLRPC.TL_contacts_block();
|
||||||
req.id = getInputUser(user);
|
req.id = getInputUser(user);
|
||||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
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) {
|
public void setDefaultBannedRole(final int chatId, TLRPC.TL_chatBannedRights rights, final boolean isChannel, final BaseFragment parentFragment) {
|
||||||
if (rights == null) {
|
if (rights == null) {
|
||||||
return;
|
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) {
|
if (user == null || rights == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2106,6 +2175,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
req.channel = getInputChannel(chat);
|
req.channel = getInputChannel(chat);
|
||||||
req.user_id = getInputUser(user);
|
req.user_id = getInputUser(user);
|
||||||
req.admin_rights = rights;
|
req.admin_rights = rights;
|
||||||
|
req.rank = rank;
|
||||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
||||||
if (error == null) {
|
if (error == null) {
|
||||||
processUpdates((TLRPC.Updates) response, false);
|
processUpdates((TLRPC.Updates) response, false);
|
||||||
|
@ -2143,53 +2213,37 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
blockedUsers.delete(user.id);
|
blockedUsers.delete(user.id);
|
||||||
req.id = getInputUser(user);
|
req.id = getInputUser(user);
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
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) {
|
if (!getUserConfig().isClientActivated() || loadingBlockedUsers) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loadingBlockedUsers = true;
|
loadingBlockedUsers = true;
|
||||||
if (cache) {
|
TLRPC.TL_contacts_getBlocked req = new TLRPC.TL_contacts_getBlocked();
|
||||||
getMessagesStorage().getBlockedUsers();
|
req.offset = reset ? 0 : blockedUsers.size();
|
||||||
} else {
|
req.limit = reset ? 20 : 100;
|
||||||
TLRPC.TL_contacts_getBlocked req = new TLRPC.TL_contacts_getBlocked();
|
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
||||||
req.offset = 0;
|
if (response != null) {
|
||||||
req.limit = 200;
|
TLRPC.contacts_Blocked res = (TLRPC.contacts_Blocked) response;
|
||||||
getConnectionsManager().sendRequest(req, (response, error) -> {
|
putUsers(res.users, false);
|
||||||
SparseIntArray blocked = new SparseIntArray();
|
getMessagesStorage().putUsersAndChats(res.users, null, true, true);
|
||||||
ArrayList<TLRPC.User> users = null;
|
if (reset) {
|
||||||
if (error == null) {
|
blockedUsers.clear();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
processLoadedBlockedUsers(blocked, users, false);
|
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);
|
||||||
public void processLoadedBlockedUsers(final SparseIntArray ids, final ArrayList<TLRPC.User> users, final boolean cache) {
|
}
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
loadingBlockedUsers = false;
|
||||||
if (users != null) {
|
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
|
||||||
putUsers(users, cache);
|
|
||||||
}
|
}
|
||||||
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) {
|
public void deleteUserPhoto(TLRPC.InputPhoto photo) {
|
||||||
|
@ -2380,7 +2434,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
toSend.add(mid);
|
toSend.add(mid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getMessagesStorage().markMessagesAsDeleted(messages, true, channelId);
|
getMessagesStorage().markMessagesAsDeleted(messages, true, channelId, forAll);
|
||||||
getMessagesStorage().updateDialogsWithDeletedMessages(messages, null, true, channelId);
|
getMessagesStorage().updateDialogsWithDeletedMessages(messages, null, true, channelId);
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, messages, 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) {
|
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) {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
loadFullChat(chat_id, 0, force);
|
if (fromCache && chat_id > 0 && !byChannelUsers) {
|
||||||
}
|
loadFullChat(chat_id, 0, force);
|
||||||
if (info != null) {
|
}
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
if (info != null) {
|
||||||
|
if (fullChats.get(chat_id) == null) {
|
||||||
|
fullChats.put(chat_id, info);
|
||||||
|
}
|
||||||
putUsers(usersArr, fromCache);
|
putUsers(usersArr, fromCache);
|
||||||
if (info.stickerset != null) {
|
if (info.stickerset != null) {
|
||||||
getMediaDataController().getGroupStickerSetById(info.stickerset);
|
getMediaDataController().getGroupStickerSetById(info.stickerset);
|
||||||
}
|
}
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, byChannelUsers, pinnedMessageObject);
|
getNotificationCenter().postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, byChannelUsers, pinnedMessageObject);
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadUserInfo(TLRPC.User user, boolean force, int classGuid) {
|
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) {
|
public void processUserInfo(TLRPC.User user, final TLRPC.UserFull info, final boolean fromCache, boolean force, final MessageObject pinnedMessageObject, int classGuid) {
|
||||||
if (fromCache) {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
loadFullUser(user, classGuid, force);
|
if (fromCache) {
|
||||||
}
|
loadFullUser(user, classGuid, force);
|
||||||
if (info != null) {
|
|
||||||
if (fullUsers.get(user.id) == null) {
|
|
||||||
fullUsers.put(user.id, info);
|
|
||||||
}
|
}
|
||||||
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() {
|
public void updateTimerProc() {
|
||||||
|
@ -3196,6 +3256,9 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
nextProxyInfoCheckTime = res.expires;
|
nextProxyInfoCheckTime = res.expires;
|
||||||
if (!noDialog) {
|
if (!noDialog) {
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
|
if (proxyDialog != null && did != proxyDialog.id) {
|
||||||
|
removeProxyDialog();
|
||||||
|
}
|
||||||
proxyDialog = dialogs_dict.get(did);
|
proxyDialog = dialogs_dict.get(did);
|
||||||
|
|
||||||
if (proxyDialog != null) {
|
if (proxyDialog != null) {
|
||||||
|
@ -3341,22 +3404,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
getGlobalMainSettings().edit().putLong("proxy_dialog", proxyDialogId).remove("proxyDialogAddress").commit();
|
getGlobalMainSettings().edit().putLong("proxy_dialog", proxyDialogId).remove("proxyDialogAddress").commit();
|
||||||
checkingProxyInfoRequestId = 0;
|
checkingProxyInfoRequestId = 0;
|
||||||
checkingProxyInfo = false;
|
checkingProxyInfo = false;
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(this::removeProxyDialog);
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -3374,25 +3422,28 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
checkingProxyInfoRequestId = 0;
|
checkingProxyInfoRequestId = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(this::removeProxyDialog);
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
public boolean isProxyDialog(long did, boolean checkLeft) {
|
||||||
return proxyDialog != null && proxyDialog.id == did && (!checkLeft || isLeftProxyChannel);
|
return proxyDialog != null && proxyDialog.id == did && (!checkLeft || isLeftProxyChannel);
|
||||||
}
|
}
|
||||||
|
@ -6192,7 +6243,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
return 0;
|
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();
|
TLRPC.TL_messages_migrateChat req = new TLRPC.TL_messages_migrateChat();
|
||||||
req.chat_id = chat_id;
|
req.chat_id = chat_id;
|
||||||
final AlertDialog progressDialog = new AlertDialog(context, 3);
|
final AlertDialog progressDialog = new AlertDialog(context, 3);
|
||||||
|
@ -6228,11 +6279,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
AlertsCreator.processError(currentAccount, error, fragment, req, false);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -7993,7 +8040,7 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
getMessagesStorage().deletePushMessages(dialogId, ids);
|
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);
|
getMessagesStorage().updateDialogsWithDeletedMessages(ids, dialogIds, false, channelId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -9172,13 +9219,6 @@ public class MessagesController extends BaseController implements NotificationCe
|
||||||
getSecretChatHelper().processUpdateEncryption((TLRPC.TL_updateEncryption) baseUpdate, usersDict);
|
getSecretChatHelper().processUpdateEncryption((TLRPC.TL_updateEncryption) baseUpdate, usersDict);
|
||||||
} else if (baseUpdate instanceof TLRPC.TL_updateUserBlocked) {
|
} else if (baseUpdate instanceof TLRPC.TL_updateUserBlocked) {
|
||||||
final TLRPC.TL_updateUserBlocked finalUpdate = (TLRPC.TL_updateUserBlocked) baseUpdate;
|
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(() -> {
|
getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> {
|
||||||
if (finalUpdate.blocked) {
|
if (finalUpdate.blocked) {
|
||||||
if (blockedUsers.indexOfKey(finalUpdate.user_id) < 0) {
|
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 int key = deletedMessages.keyAt(a);
|
||||||
final ArrayList<Integer> arrayList = deletedMessages.valueAt(a);
|
final ArrayList<Integer> arrayList = deletedMessages.valueAt(a);
|
||||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
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);
|
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 key = clearHistoryMessages.keyAt(a);
|
||||||
final int id = clearHistoryMessages.valueAt(a);
|
final int id = clearHistoryMessages.valueAt(a);
|
||||||
getMessagesStorage().getStorageQueue().postRunnable(() -> {
|
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);
|
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.isOut() && !message.isSending() && !message.isForwarded()) {
|
||||||
if (message.isNewGif()) {
|
if (message.isNewGif()) {
|
||||||
getMediaDataController().addRecentGif(message.messageOwner.media.document, message.messageOwner.date);
|
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);
|
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 CountDownLatch openSync = new CountDownLatch(1);
|
||||||
|
|
||||||
private static volatile MessagesStorage[] Instance = new MessagesStorage[UserConfig.MAX_ACCOUNT_COUNT];
|
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) {
|
public static MessagesStorage getInstance(int num) {
|
||||||
MessagesStorage localInstance = Instance[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 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 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 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 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();
|
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 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 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_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 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 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 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 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();
|
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 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 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 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 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("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();
|
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;
|
version = 43;
|
||||||
}
|
}
|
||||||
if (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();
|
database.executeFast("PRAGMA user_version = 44").stepThis().dispose();
|
||||||
version = 44;
|
version = 44;
|
||||||
}
|
}
|
||||||
|
@ -785,6 +779,19 @@ public class MessagesStorage extends BaseController {
|
||||||
version = 60;
|
version = 60;
|
||||||
}
|
}
|
||||||
if (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) {
|
} catch (Exception e) {
|
||||||
|
@ -1487,16 +1494,16 @@ public class MessagesStorage extends BaseController {
|
||||||
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
|
||||||
for (int a = 0; a < chats.size(); a++) {
|
for (int a = 0; a < chats.size(); a++) {
|
||||||
TLRPC.Chat chat = chats.get(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;
|
long did = -chat.id;
|
||||||
database.executeFast("UPDATE dialogs SET unread_count = 0 WHERE did = " + did).stepThis().dispose();
|
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();
|
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);
|
chats.remove(a);
|
||||||
a--;
|
a--;
|
||||||
pushDialogs.remove((long) -chat.id);
|
pushDialogs.remove(did);
|
||||||
for (int b = 0; b < messages.size(); b++) {
|
for (int b = 0; b < messages.size(); b++) {
|
||||||
TLRPC.Message message = messages.get(b);
|
TLRPC.Message message = messages.get(b);
|
||||||
if (message.dialog_id == -chat.id) {
|
if (message.dialog_id == did) {
|
||||||
messages.remove(b);
|
messages.remove(b);
|
||||||
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) {
|
public void deleteUserChannelHistory(final int channelId, final int uid) {
|
||||||
storageQueue.postRunnable(() -> {
|
storageQueue.postRunnable(() -> {
|
||||||
try {
|
try {
|
||||||
|
@ -1793,27 +1738,7 @@ public class MessagesStorage extends BaseController {
|
||||||
data.reuse();
|
data.reuse();
|
||||||
if (message != null && message.from_id == uid && message.id != 1) {
|
if (message != null && message.from_id == uid && message.id != 1) {
|
||||||
mids.add(message.id);
|
mids.add(message.id);
|
||||||
if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
|
addFilesToDelete(message, filesToDelete, false);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1822,7 +1747,7 @@ public class MessagesStorage extends BaseController {
|
||||||
}
|
}
|
||||||
cursor.dispose();
|
cursor.dispose();
|
||||||
AndroidUtilities.runOnUIThread(() -> getMessagesController().markChannelDialogMessageAsDeleted(mids, channelId));
|
AndroidUtilities.runOnUIThread(() -> getMessagesController().markChannelDialogMessageAsDeleted(mids, channelId));
|
||||||
markMessagesAsDeletedInternal(mids, channelId);
|
markMessagesAsDeletedInternal(mids, channelId, false);
|
||||||
updateDialogsWithDeletedMessagesInternal(mids, null, channelId);
|
updateDialogsWithDeletedMessagesInternal(mids, null, channelId);
|
||||||
getFileLoader().deleteFiles(filesToDelete, 0);
|
getFileLoader().deleteFiles(filesToDelete, 0);
|
||||||
if (!mids.isEmpty()) {
|
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) {
|
public void deleteDialog(final long did, final int messagesOnly) {
|
||||||
storageQueue.postRunnable(() -> {
|
storageQueue.postRunnable(() -> {
|
||||||
try {
|
try {
|
||||||
|
@ -1858,29 +1813,7 @@ public class MessagesStorage extends BaseController {
|
||||||
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||||
message.readAttachPath(data, getUserConfig().clientUserId);
|
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||||
data.reuse();
|
data.reuse();
|
||||||
if (message != null && message.media != null) {
|
addFilesToDelete(message, filesToDelete, false);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -2219,29 +2152,7 @@ public class MessagesStorage extends BaseController {
|
||||||
message.readAttachPath(data, getUserConfig().clientUserId);
|
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||||
data.reuse();
|
data.reuse();
|
||||||
if (message.media != null) {
|
if (message.media != null) {
|
||||||
if (message.media.document != null) {
|
if (!addFilesToDelete(message, filesToDelete, true)) {
|
||||||
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 {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
message.media.flags = message.media.flags &~ 1;
|
message.media.flags = message.media.flags &~ 1;
|
||||||
|
@ -2747,10 +2658,10 @@ public class MessagesStorage extends BaseController {
|
||||||
public void loadChannelAdmins(final int chatId) {
|
public void loadChannelAdmins(final int chatId) {
|
||||||
storageQueue.postRunnable(() -> {
|
storageQueue.postRunnable(() -> {
|
||||||
try {
|
try {
|
||||||
SQLiteCursor cursor = database.queryFinalized("SELECT uid FROM channel_admins WHERE did = " + chatId);
|
SQLiteCursor cursor = database.queryFinalized("SELECT uid, rank FROM channel_admins_v2 WHERE did = " + chatId);
|
||||||
ArrayList<Integer> ids = new ArrayList<>();
|
SparseArray<String> ids = new SparseArray<>();
|
||||||
while (cursor.next()) {
|
while (cursor.next()) {
|
||||||
ids.add(cursor.intValue(0));
|
ids.put(cursor.intValue(0), cursor.stringValue(1));
|
||||||
}
|
}
|
||||||
cursor.dispose();
|
cursor.dispose();
|
||||||
getMessagesController().processLoadedChannelAdmins(ids, chatId, true);
|
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(() -> {
|
storageQueue.postRunnable(() -> {
|
||||||
try {
|
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();
|
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);
|
int date = (int) (System.currentTimeMillis() / 1000);
|
||||||
for (int a = 0; a < ids.size(); a++) {
|
for (int a = 0; a < ids.size(); a++) {
|
||||||
state.requery();
|
state.requery();
|
||||||
state.bindInteger(1, chatId);
|
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.step();
|
||||||
}
|
}
|
||||||
state.dispose();
|
state.dispose();
|
||||||
|
@ -3192,7 +3104,8 @@ public class MessagesStorage extends BaseController {
|
||||||
return result[0];
|
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(() -> {
|
storageQueue.postRunnable(() -> {
|
||||||
MessageObject pinnedMessageObject = null;
|
MessageObject pinnedMessageObject = null;
|
||||||
TLRPC.ChatFull info = null;
|
TLRPC.ChatFull info = null;
|
||||||
|
@ -3269,21 +3182,27 @@ public class MessagesStorage extends BaseController {
|
||||||
getUsersInternal(usersToLoad.toString(), loadedUsers);
|
getUsersInternal(usersToLoad.toString(), loadedUsers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (countDownLatch != null) {
|
|
||||||
countDownLatch.countDown();
|
|
||||||
}
|
|
||||||
if (info != null && info.pinned_msg_id != 0) {
|
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);
|
pinnedMessageObject = getMediaDataController().loadPinnedMessage(-chat_id, info instanceof TLRPC.TL_channelFull ? chat_id : 0, info.pinned_msg_id, false);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
result[0] = info;
|
||||||
getMessagesController().processChatInfo(chat_id, info, loadedUsers, true, force, byChannelUsers, pinnedMessageObject);
|
getMessagesController().processChatInfo(chat_id, info, loadedUsers, true, force, byChannelUsers, pinnedMessageObject);
|
||||||
if (countDownLatch != null) {
|
if (countDownLatch != null) {
|
||||||
countDownLatch.countDown();
|
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) {
|
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> chatsToLoad = new ArrayList<>();
|
||||||
ArrayList<Integer> broadcastIds = new ArrayList<>();
|
ArrayList<Integer> broadcastIds = new ArrayList<>();
|
||||||
ArrayList<Integer> encryptedChatIds = 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);
|
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()) {
|
while (cursor.next()) {
|
||||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
NativeByteBuffer data = cursor.byteBufferValue(1);
|
||||||
|
@ -6291,7 +6211,7 @@ public class MessagesStorage extends BaseController {
|
||||||
if (!mids.isEmpty()) {
|
if (!mids.isEmpty()) {
|
||||||
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0));
|
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDeleted, mids, 0));
|
||||||
updateDialogsWithReadMessagesInternal(mids, null, null, null);
|
updateDialogsWithReadMessagesInternal(mids, null, null, null);
|
||||||
markMessagesAsDeletedInternal(mids, 0);
|
markMessagesAsDeletedInternal(mids, 0, true);
|
||||||
updateDialogsWithDeletedMessagesInternal(mids, null, 0);
|
updateDialogsWithDeletedMessagesInternal(mids, null, 0);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} 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 {
|
try {
|
||||||
String ids;
|
String ids;
|
||||||
final ArrayList<Integer> temp = new ArrayList<>(messages);
|
final ArrayList<Integer> temp = new ArrayList<>(messages);
|
||||||
|
@ -6354,7 +6274,7 @@ public class MessagesStorage extends BaseController {
|
||||||
unread_count[0]++;
|
unread_count[0]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((int) did != 0) {
|
if ((int) did != 0 && !deleteFiles) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
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);
|
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||||
message.readAttachPath(data, getUserConfig().clientUserId);
|
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||||
data.reuse();
|
data.reuse();
|
||||||
if (message != null) {
|
addFilesToDelete(message, filesToDelete, false);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} 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()) {
|
if (messages.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (useQueue) {
|
if (useQueue) {
|
||||||
storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(messages, channelId));
|
storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(messages, channelId, deleteFiles));
|
||||||
} else {
|
} else {
|
||||||
return markMessagesAsDeletedInternal(messages, channelId);
|
return markMessagesAsDeletedInternal(messages, channelId, deleteFiles);
|
||||||
}
|
}
|
||||||
return null;
|
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 {
|
try {
|
||||||
String ids;
|
String ids;
|
||||||
ArrayList<Long> dialogsIds = new ArrayList<>();
|
ArrayList<Long> dialogsIds = new ArrayList<>();
|
||||||
|
@ -6695,7 +6593,7 @@ public class MessagesStorage extends BaseController {
|
||||||
unread_count[0]++;
|
unread_count[0]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((int) did != 0) {
|
if ((int) did != 0 && !deleteFiles) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NativeByteBuffer data = cursor.byteBufferValue(1);
|
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);
|
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
||||||
message.readAttachPath(data, getUserConfig().clientUserId);
|
message.readAttachPath(data, getUserConfig().clientUserId);
|
||||||
data.reuse();
|
data.reuse();
|
||||||
if (message != null) {
|
addFilesToDelete(message, filesToDelete, false);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -6768,11 +6644,11 @@ public class MessagesStorage extends BaseController {
|
||||||
return null;
|
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) {
|
if (useQueue) {
|
||||||
storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(channelId, mid));
|
storageQueue.postRunnable(() -> markMessagesAsDeletedInternal(channelId, mid, deleteFiles));
|
||||||
} else {
|
} else {
|
||||||
return markMessagesAsDeletedInternal(channelId, mid);
|
return markMessagesAsDeletedInternal(channelId, mid, deleteFiles);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -7129,6 +7005,7 @@ public class MessagesStorage extends BaseController {
|
||||||
int minChannelMessageId = Integer.MAX_VALUE;
|
int minChannelMessageId = Integer.MAX_VALUE;
|
||||||
int maxChannelMessageId = 0;
|
int maxChannelMessageId = 0;
|
||||||
int channelId = 0;
|
int channelId = 0;
|
||||||
|
ArrayList<File> filesToDelete = new ArrayList<>();
|
||||||
for (int a = 0; a < count; a++) {
|
for (int a = 0; a < count; a++) {
|
||||||
TLRPC.Message message = messages.messages.get(a);
|
TLRPC.Message message = messages.messages.get(a);
|
||||||
|
|
||||||
|
@ -7154,6 +7031,15 @@ public class MessagesStorage extends BaseController {
|
||||||
message.attachPath = oldMessage.attachPath;
|
message.attachPath = oldMessage.attachPath;
|
||||||
message.ttl = cursor.intValue(2);
|
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;
|
boolean oldMention = cursor.intValue(3) != 0;
|
||||||
int readState = cursor.intValue(4);
|
int readState = cursor.intValue(4);
|
||||||
|
@ -7294,6 +7180,7 @@ public class MessagesStorage extends BaseController {
|
||||||
if (botKeyboard != null) {
|
if (botKeyboard != null) {
|
||||||
getMediaDataController().putBotKeyboard(dialog_id, botKeyboard);
|
getMediaDataController().putBotKeyboard(dialog_id, botKeyboard);
|
||||||
}
|
}
|
||||||
|
getFileLoader().deleteFiles(filesToDelete, 0);
|
||||||
|
|
||||||
putUsersInternal(messages.users);
|
putUsersInternal(messages.users);
|
||||||
putChatsInternal(messages.chats);
|
putChatsInternal(messages.chats);
|
||||||
|
|
|
@ -93,6 +93,7 @@ public class NotificationCenter {
|
||||||
public static final int newPeopleNearbyAvailable = totalEvents++;
|
public static final int newPeopleNearbyAvailable = totalEvents++;
|
||||||
public static final int stopAllHeavyOperations = totalEvents++;
|
public static final int stopAllHeavyOperations = totalEvents++;
|
||||||
public static final int startAllHeavyOperations = totalEvents++;
|
public static final int startAllHeavyOperations = totalEvents++;
|
||||||
|
public static final int sendingMessagesChanged = totalEvents++;
|
||||||
|
|
||||||
public static final int httpFileDidLoad = totalEvents++;
|
public static final int httpFileDidLoad = totalEvents++;
|
||||||
public static final int httpFileDidFailedLoad = totalEvents++;
|
public static final int httpFileDidFailedLoad = totalEvents++;
|
||||||
|
|
|
@ -16,121 +16,130 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
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);
|
private static final UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
|
||||||
static{
|
|
||||||
|
static {
|
||||||
matcher.addURI(AUTHORITY, "msg_media_raw/#/*", 1); // content://org.telegram..../msg_media_raw/account/filename.ext
|
matcher.addURI(AUTHORITY, "msg_media_raw/#/*", 1); // content://org.telegram..../msg_media_raw/account/filename.ext
|
||||||
}
|
}
|
||||||
|
|
||||||
private HashSet<String> waitingForFiles=new HashSet<>();
|
private HashSet<String> waitingForFiles = new HashSet<>();
|
||||||
private final Object sync=new Object();
|
private final Object sync = new Object();
|
||||||
private HashMap<String, Long> fileStartTimes=new HashMap<>();
|
private HashMap<String, Long> fileStartTimes = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreate(){
|
public boolean onCreate() {
|
||||||
for(int i=0;i<UserConfig.getActivatedAccountsCount();i++){
|
for (int i = 0; i < UserConfig.getActivatedAccountsCount(); i++) {
|
||||||
NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.fileDidLoad);
|
NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.fileDidLoad);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown(){
|
public void shutdown() {
|
||||||
for(int i=0;i<UserConfig.getActivatedAccountsCount();i++){
|
for (int i = 0; i < UserConfig.getActivatedAccountsCount(); i++) {
|
||||||
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.fileDidLoad);
|
NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.fileDidLoad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public String getType(@NonNull Uri uri){
|
public String getType(@NonNull Uri uri) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values){
|
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter){
|
public String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter) {
|
||||||
if(mimeTypeFilter.startsWith("*/") || mimeTypeFilter.startsWith("image/"))
|
if (mimeTypeFilter.startsWith("*/") || mimeTypeFilter.startsWith("image/")) {
|
||||||
return new String[]{"image/jpeg", "image/png", "image/webp"};
|
return new String[]{"image/jpeg", "image/png", "image/webp"};
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException{
|
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
||||||
if(!"r".equals(mode))
|
if (!"r".equals(mode)) {
|
||||||
throw new SecurityException("Can only open files for read");
|
throw new SecurityException("Can only open files for read");
|
||||||
switch(matcher.match(uri)){
|
}
|
||||||
case 1:
|
if (matcher.match(uri) == 1) {
|
||||||
{
|
List<String> path = uri.getPathSegments();
|
||||||
List<String> path=uri.getPathSegments();
|
int account = Integer.parseInt(path.get(1));
|
||||||
int account=Integer.parseInt(path.get(1));
|
String name = path.get(2);
|
||||||
String name=path.get(2);
|
String finalPath = uri.getQueryParameter("final_path");
|
||||||
String finalPath=uri.getQueryParameter("final_path");
|
String fallbackPath = uri.getQueryParameter("fallback");
|
||||||
String fallbackPath=uri.getQueryParameter("fallback");
|
File finalFile = new File(finalPath);
|
||||||
File finalFile=new File(finalPath);
|
if (AndroidUtilities.isInternalUri(Uri.fromFile(finalFile))) {
|
||||||
if(finalFile.exists()){
|
throw new SecurityException("trying to read internal file");
|
||||||
FileLog.d(finalFile+" already exists");
|
}
|
||||||
return ParcelFileDescriptor.open(finalFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
if (finalFile.exists()) {
|
||||||
}else{
|
return ParcelFileDescriptor.open(finalFile, ParcelFileDescriptor.MODE_READ_ONLY);
|
||||||
Long _startTime=fileStartTimes.get(name);
|
} else {
|
||||||
long startTime=_startTime!=null ? _startTime : System.currentTimeMillis();
|
Long _startTime = fileStartTimes.get(name);
|
||||||
if(_startTime==null)
|
long startTime = _startTime != null ? _startTime : System.currentTimeMillis();
|
||||||
fileStartTimes.put(name, startTime);
|
if (_startTime == null) {
|
||||||
while(!finalFile.exists()){
|
fileStartTimes.put(name, startTime);
|
||||||
if(System.currentTimeMillis()-startTime>=3000){
|
}
|
||||||
if(BuildVars.LOGS_ENABLED)
|
while (!finalFile.exists()) {
|
||||||
FileLog.w("Waiting for "+name+" to download timed out");
|
if (System.currentTimeMillis() - startTime >= 3000) {
|
||||||
if(TextUtils.isEmpty(fallbackPath))
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
throw new FileNotFoundException("Download timed out");
|
FileLog.w("Waiting for " + name + " to download timed out");
|
||||||
return ParcelFileDescriptor.open(new File(fallbackPath), ParcelFileDescriptor.MODE_READ_ONLY);
|
|
||||||
}
|
}
|
||||||
synchronized(sync){
|
if (TextUtils.isEmpty(fallbackPath)) {
|
||||||
waitingForFiles.add(name);
|
throw new FileNotFoundException("Download timed out");
|
||||||
try{
|
}
|
||||||
sync.wait(1000);
|
File file = new File(fallbackPath);
|
||||||
}catch(InterruptedException ignore){
|
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");
|
throw new FileNotFoundException("Invalid URI");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void didReceivedNotification(int id, int account, Object... args){
|
public void didReceivedNotification(int id, int account, Object... args) {
|
||||||
if(id==NotificationCenter.fileDidLoad){
|
if (id == NotificationCenter.fileDidLoad) {
|
||||||
synchronized(sync){
|
synchronized (sync) {
|
||||||
String name=(String)args[0];
|
String name = (String) args[0];
|
||||||
if(waitingForFiles.remove(name)){
|
if (waitingForFiles.remove(name)) {
|
||||||
fileStartTimes.remove(name);
|
fileStartTimes.remove(name);
|
||||||
sync.notifyAll();
|
sync.notifyAll();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1045,6 +1045,9 @@ public class SecretChatHelper extends BaseController {
|
||||||
newMessage.media.ttl_seconds = newMessage.ttl;
|
newMessage.media.ttl_seconds = newMessage.ttl;
|
||||||
newMessage.media.flags |= 4;
|
newMessage.media.flags |= 4;
|
||||||
}
|
}
|
||||||
|
if (newMessage.message != null) {
|
||||||
|
newMessage.message = newMessage.message.replace('\u202E', ' ');
|
||||||
|
}
|
||||||
return newMessage;
|
return newMessage;
|
||||||
} else if (object instanceof TLRPC.TL_decryptedMessageService) {
|
} else if (object instanceof TLRPC.TL_decryptedMessageService) {
|
||||||
final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService) object;
|
final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService) object;
|
||||||
|
|
|
@ -31,6 +31,7 @@ import android.text.TextUtils;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.LongSparseArray;
|
import android.util.LongSparseArray;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
import android.util.SparseIntArray;
|
||||||
import android.webkit.MimeTypeMap;
|
import android.webkit.MimeTypeMap;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -68,6 +69,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
private HashMap<String, ArrayList<DelayedMessage>> delayedMessages = new HashMap<>();
|
private HashMap<String, ArrayList<DelayedMessage>> delayedMessages = new HashMap<>();
|
||||||
private SparseArray<MessageObject> unsentMessages = new SparseArray<>();
|
private SparseArray<MessageObject> unsentMessages = new SparseArray<>();
|
||||||
private SparseArray<TLRPC.Message> sendingMessages = 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, MessageObject> waitingForLocation = new HashMap<>();
|
||||||
private HashMap<String, Boolean> waitingForCallback = new HashMap<>();
|
private HashMap<String, Boolean> waitingForCallback = new HashMap<>();
|
||||||
private HashMap<String, byte[]> waitingForVote = 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;
|
obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, obj.getId());
|
getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, obj.getId());
|
||||||
processSentMessage(obj.getId());
|
processSentMessage(obj.getId());
|
||||||
|
removeFromUploadingMessages(obj.getId());
|
||||||
}
|
}
|
||||||
delayedMessages.remove( "group_" + groupId);
|
delayedMessages.remove( "group_" + groupId);
|
||||||
} else {
|
} else {
|
||||||
|
@ -368,6 +374,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
|
obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR;
|
||||||
getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, obj.getId());
|
getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, obj.getId());
|
||||||
processSentMessage(obj.getId());
|
processSentMessage(obj.getId());
|
||||||
|
removeFromUploadingMessages(obj.getId());
|
||||||
}
|
}
|
||||||
sendDelayedRequests();
|
sendDelayedRequests();
|
||||||
}
|
}
|
||||||
|
@ -407,6 +414,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
delayedMessages.clear();
|
delayedMessages.clear();
|
||||||
unsentMessages.clear();
|
unsentMessages.clear();
|
||||||
sendingMessages.clear();
|
sendingMessages.clear();
|
||||||
|
editingMessages.clear();
|
||||||
|
sendingMessagesIdDialogs.clear();
|
||||||
|
uploadMessages.clear();
|
||||||
|
uploadingMessagesIdDialogs.clear();
|
||||||
waitingForLocation.clear();
|
waitingForLocation.clear();
|
||||||
waitingForCallback.clear();
|
waitingForCallback.clear();
|
||||||
waitingForVote.clear();
|
waitingForVote.clear();
|
||||||
|
@ -807,6 +818,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
|
|
||||||
public void cancelSendingMessage(ArrayList<MessageObject> objects) {
|
public void cancelSendingMessage(ArrayList<MessageObject> objects) {
|
||||||
ArrayList<String> keysToRemove = new ArrayList<>();
|
ArrayList<String> keysToRemove = new ArrayList<>();
|
||||||
|
ArrayList<DelayedMessage> checkReadyToSendGroups = new ArrayList<>();
|
||||||
ArrayList<Integer> messageIds = new ArrayList<>();
|
ArrayList<Integer> messageIds = new ArrayList<>();
|
||||||
boolean enc = false;
|
boolean enc = false;
|
||||||
int channelId = 0;
|
int channelId = 0;
|
||||||
|
@ -830,6 +842,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
messageObject = message.messageObjects.get(b);
|
messageObject = message.messageObjects.get(b);
|
||||||
if (messageObject.getId() == object.getId()) {
|
if (messageObject.getId() == object.getId()) {
|
||||||
index = b;
|
index = b;
|
||||||
|
removeFromUploadingMessages(object.getId());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -862,13 +875,15 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
TLRPC.TL_messages_messages messagesRes = new TLRPC.TL_messages_messages();
|
||||||
messagesRes.messages.add(prevMessage.messageOwner);
|
messagesRes.messages.add(prevMessage.messageOwner);
|
||||||
getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false);
|
getMessagesStorage().putMessages(messagesRes, message.peer, -2, 0, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
sendReadyToSendGroup(message, false, true);
|
if (!checkReadyToSendGroups.contains(message)) {
|
||||||
|
checkReadyToSendGroups.add(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (message.obj.getId() == object.getId()) {
|
} else if (message.obj.getId() == object.getId()) {
|
||||||
|
removeFromUploadingMessages(object.getId());
|
||||||
messages.remove(a);
|
messages.remove(a);
|
||||||
message.sendDelayedRequests();
|
message.sendDelayedRequests();
|
||||||
MediaController.getInstance().cancelVideoConvert(message.obj);
|
MediaController.getInstance().cancelVideoConvert(message.obj);
|
||||||
|
@ -893,6 +908,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
stopVideoService(key);
|
stopVideoService(key);
|
||||||
delayedMessages.remove(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) {
|
if (objects.size() == 1 && objects.get(0).isEditing() && objects.get(0).previousMedia != null) {
|
||||||
revertEditingMessageObject(objects.get(0));
|
revertEditingMessageObject(objects.get(0));
|
||||||
} else {
|
} else {
|
||||||
|
@ -1381,9 +1399,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
final TLRPC.TL_messages_forwardMessages req = new TLRPC.TL_messages_forwardMessages();
|
final TLRPC.TL_messages_forwardMessages req = new TLRPC.TL_messages_forwardMessages();
|
||||||
req.to_peer = inputPeer;
|
req.to_peer = inputPeer;
|
||||||
req.grouped = lastGroupedId != 0;
|
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) {
|
if (msgObj.messageOwner.to_id instanceof TLRPC.TL_peerChannel) {
|
||||||
TLRPC.Chat channel = getMessagesController().getChat(msgObj.messageOwner.to_id.channel_id);
|
TLRPC.Chat channel = getMessagesController().getChat(msgObj.messageOwner.to_id.channel_id);
|
||||||
req.from_peer = new TLRPC.TL_inputPeerChannel();
|
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();
|
TLRPC.TL_messages_sendMedia request = new TLRPC.TL_messages_sendMedia();
|
||||||
request.peer = peer;
|
request.peer = peer;
|
||||||
if (request.peer instanceof TLRPC.TL_inputPeerChannel) {
|
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.random_id = random_id != 0 ? random_id : getNextRandomId();
|
||||||
request.message = "";
|
request.message = "";
|
||||||
|
@ -2260,7 +2280,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
if (retryMessageObject.isForwarded()) {
|
if (retryMessageObject.isForwarded()) {
|
||||||
type = 4;
|
type = 4;
|
||||||
} else {
|
} else {
|
||||||
if (retryMessageObject.type == 0) {
|
if (retryMessageObject.type == 0 || retryMessageObject.isAnimatedEmoji()) {
|
||||||
if (retryMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
|
if (retryMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) {
|
||||||
//game = retryMessageObject.messageOwner.media.game;
|
//game = retryMessageObject.messageOwner.media.game;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2284,7 +2304,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
user.restriction_reason = newMsg.media.vcard;
|
user.restriction_reason = newMsg.media.vcard;
|
||||||
user.id = newMsg.media.user_id;
|
user.id = newMsg.media.user_id;
|
||||||
type = 6;
|
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;
|
document = (TLRPC.TL_document) newMsg.media.document;
|
||||||
type = 7;
|
type = 7;
|
||||||
} else if (retryMessageObject.type == 2) {
|
} else if (retryMessageObject.type == 2) {
|
||||||
|
@ -2624,8 +2644,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
|
|
||||||
newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING;
|
newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING;
|
||||||
newMsgObj = new MessageObject(currentAccount, newMsg, true);
|
newMsgObj = new MessageObject(currentAccount, newMsg, reply_to_msg, true);
|
||||||
newMsgObj.replyMessageObject = reply_to_msg;
|
|
||||||
if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == 2) && !TextUtils.isEmpty(newMsg.attachPath)) {
|
if (!newMsgObj.isForwarded() && (newMsgObj.type == 3 || videoEditedInfo != null || newMsgObj.type == 2) && !TextUtils.isEmpty(newMsg.attachPath)) {
|
||||||
newMsgObj.attachPathExists = true;
|
newMsgObj.attachPathExists = true;
|
||||||
}
|
}
|
||||||
|
@ -2698,9 +2717,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
TLRPC.TL_messages_sendMessage reqSend = new TLRPC.TL_messages_sendMessage();
|
TLRPC.TL_messages_sendMessage reqSend = new TLRPC.TL_messages_sendMessage();
|
||||||
reqSend.message = message;
|
reqSend.message = message;
|
||||||
reqSend.clear_draft = retryMessageObject == null;
|
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.peer = sendToPeer;
|
||||||
reqSend.random_id = newMsg.random_id;
|
reqSend.random_id = newMsg.random_id;
|
||||||
if (newMsg.reply_to_msg_id != 0) {
|
if (newMsg.reply_to_msg_id != 0) {
|
||||||
|
@ -2989,9 +3006,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
request = new TLRPC.TL_messages_sendMultiMedia();
|
request = new TLRPC.TL_messages_sendMultiMedia();
|
||||||
request.peer = sendToPeer;
|
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) {
|
if (newMsg.reply_to_msg_id != 0) {
|
||||||
request.flags |= 1;
|
request.flags |= 1;
|
||||||
request.reply_to_msg_id = newMsg.reply_to_msg_id;
|
request.reply_to_msg_id = newMsg.reply_to_msg_id;
|
||||||
|
@ -3019,9 +3034,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
TLRPC.TL_messages_sendMedia request = new TLRPC.TL_messages_sendMedia();
|
TLRPC.TL_messages_sendMedia request = new TLRPC.TL_messages_sendMedia();
|
||||||
request.peer = sendToPeer;
|
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) {
|
if (newMsg.reply_to_msg_id != 0) {
|
||||||
request.flags |= 1;
|
request.flags |= 1;
|
||||||
request.reply_to_msg_id = newMsg.reply_to_msg_id;
|
request.reply_to_msg_id = newMsg.reply_to_msg_id;
|
||||||
|
@ -3353,9 +3366,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
reqSend.from_peer = new TLRPC.TL_inputPeerEmpty();
|
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);
|
reqSend.random_id.add(newMsg.random_id);
|
||||||
if (retryMessageObject.getId() >= 0) {
|
if (retryMessageObject.getId() >= 0) {
|
||||||
reqSend.id.add(retryMessageObject.getId());
|
reqSend.id.add(retryMessageObject.getId());
|
||||||
|
@ -3376,9 +3387,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
reqSend.flags |= 1;
|
reqSend.flags |= 1;
|
||||||
reqSend.reply_to_msg_id = newMsg.reply_to_msg_id;
|
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.query_id = Utilities.parseLong(params.get("query_id"));
|
||||||
reqSend.id = params.get("id");
|
reqSend.id = params.get("id");
|
||||||
if (retryMessageObject == null) {
|
if (retryMessageObject == null) {
|
||||||
|
@ -3440,6 +3449,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
String location = FileLoader.getPathToAttach(message.photoSize).toString();
|
String location = FileLoader.getPathToAttach(message.photoSize).toString();
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
} else {
|
} else {
|
||||||
String location = FileLoader.getPathToAttach(message.photoSize).toString();
|
String location = FileLoader.getPathToAttach(message.photoSize).toString();
|
||||||
if (message.sendEncryptedRequest != null && message.photoSize.location.dc_id != 0) {
|
if (message.sendEncryptedRequest != null && message.photoSize.location.dc_id != 0) {
|
||||||
|
@ -3456,6 +3466,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
getFileLoader().uploadFile(location, true, true, ConnectionsManager.FileTypePhoto);
|
getFileLoader().uploadFile(location, true, true, ConnectionsManager.FileTypePhoto);
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (message.type == 1) {
|
} else if (message.type == 1) {
|
||||||
|
@ -3467,6 +3478,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
MediaController.getInstance().scheduleVideoConvert(message.obj);
|
MediaController.getInstance().scheduleVideoConvert(message.obj);
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
} else {
|
} else {
|
||||||
if (message.videoEditedInfo != null) {
|
if (message.videoEditedInfo != null) {
|
||||||
if (message.videoEditedInfo.file != null) {
|
if (message.videoEditedInfo.file != null) {
|
||||||
|
@ -3511,10 +3523,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
getFileLoader().uploadFile(location, false, false, ConnectionsManager.FileTypeVideo);
|
getFileLoader().uploadFile(location, false, false, ConnectionsManager.FileTypeVideo);
|
||||||
}
|
}
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
} else {
|
} else {
|
||||||
String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg";
|
String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg";
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String location = message.obj.messageOwner.attachPath;
|
String location = message.obj.messageOwner.attachPath;
|
||||||
|
@ -3536,6 +3550,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeVideo);
|
getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeVideo);
|
||||||
}
|
}
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (message.type == 2) {
|
} else if (message.type == 2) {
|
||||||
|
@ -3556,10 +3571,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
String location = message.obj.messageOwner.attachPath;
|
String location = message.obj.messageOwner.attachPath;
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
getFileLoader().uploadFile(location, message.sendRequest == null, false, ConnectionsManager.FileTypeFile);
|
getFileLoader().uploadFile(location, message.sendRequest == null, false, ConnectionsManager.FileTypeFile);
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
} else if (media.thumb == null && message.photoSize != null) {
|
} 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";
|
String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg";
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String location = message.obj.messageOwner.attachPath;
|
String location = message.obj.messageOwner.attachPath;
|
||||||
|
@ -3574,12 +3591,14 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeFile);
|
getFileLoader().uploadFile(location, true, false, ConnectionsManager.FileTypeFile);
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (message.type == 3) {
|
} else if (message.type == 3) {
|
||||||
String location = message.obj.messageOwner.attachPath;
|
String location = message.obj.messageOwner.attachPath;
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
getFileLoader().uploadFile(location, message.sendRequest == null, true, ConnectionsManager.FileTypeAudio);
|
getFileLoader().uploadFile(location, message.sendRequest == null, true, ConnectionsManager.FileTypeAudio);
|
||||||
|
putToUploadingMessages(message.obj);
|
||||||
} else if (message.type == 4) {
|
} else if (message.type == 4) {
|
||||||
boolean add = index < 0;
|
boolean add = index < 0;
|
||||||
if (message.performMediaUpload) {
|
if (message.performMediaUpload) {
|
||||||
|
@ -3601,6 +3620,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
message.extraHashMap.put(location + "_t", message.photoSize);
|
message.extraHashMap.put(location + "_t", message.photoSize);
|
||||||
}
|
}
|
||||||
MediaController.getInstance().scheduleVideoConvert(messageObject);
|
MediaController.getInstance().scheduleVideoConvert(messageObject);
|
||||||
|
message.obj = messageObject;
|
||||||
|
putToUploadingMessages(messageObject);
|
||||||
} else {
|
} else {
|
||||||
TLRPC.Document document = messageObject.getDocument();
|
TLRPC.Document document = messageObject.getDocument();
|
||||||
String documentLocation = messageObject.messageOwner.attachPath;
|
String documentLocation = messageObject.messageOwner.attachPath;
|
||||||
|
@ -3623,6 +3644,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
getFileLoader().uploadFile(documentLocation, false, false, ConnectionsManager.FileTypeVideo);
|
getFileLoader().uploadFile(documentLocation, false, false, ConnectionsManager.FileTypeVideo);
|
||||||
}
|
}
|
||||||
|
putToUploadingMessages(messageObject);
|
||||||
} else {
|
} else {
|
||||||
String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg";
|
String location = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE) + "/" + message.photoSize.location.volume_id + "_" + message.photoSize.location.local_id + ".jpg";
|
||||||
putToDelayedMessages(location, message);
|
putToDelayedMessages(location, message);
|
||||||
|
@ -3630,6 +3652,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
message.extraHashMap.put(messageObject, location);
|
message.extraHashMap.put(messageObject, location);
|
||||||
message.extraHashMap.put(location, media);
|
message.extraHashMap.put(location, media);
|
||||||
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto);
|
||||||
|
putToUploadingMessages(messageObject);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TLRPC.TL_messages_sendEncryptedMultiMedia request = (TLRPC.TL_messages_sendEncryptedMultiMedia) message.sendEncryptedRequest;
|
TLRPC.TL_messages_sendEncryptedMultiMedia request = (TLRPC.TL_messages_sendEncryptedMultiMedia) message.sendEncryptedRequest;
|
||||||
|
@ -3645,6 +3668,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
} else {
|
} else {
|
||||||
getFileLoader().uploadFile(documentLocation, true, false, ConnectionsManager.FileTypeVideo);
|
getFileLoader().uploadFile(documentLocation, true, false, ConnectionsManager.FileTypeVideo);
|
||||||
}
|
}
|
||||||
|
putToUploadingMessages(messageObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
message.videoEditedInfo = null;
|
message.videoEditedInfo = null;
|
||||||
|
@ -3670,12 +3694,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
message.extraHashMap.put(location, inputMedia);
|
message.extraHashMap.put(location, inputMedia);
|
||||||
message.extraHashMap.put(messageObject, location);
|
message.extraHashMap.put(messageObject, location);
|
||||||
getFileLoader().uploadFile(location, message.sendEncryptedRequest != null, true, ConnectionsManager.FileTypePhoto);
|
getFileLoader().uploadFile(location, message.sendEncryptedRequest != null, true, ConnectionsManager.FileTypePhoto);
|
||||||
|
putToUploadingMessages(messageObject);
|
||||||
message.photoSize = null;
|
message.photoSize = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
message.performMediaUpload = false;
|
message.performMediaUpload = false;
|
||||||
} else if (!message.messageObjects.isEmpty()) {
|
} 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);
|
sendReadyToSendGroup(message, add, true);
|
||||||
}
|
}
|
||||||
|
@ -3805,19 +3830,121 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void putToSendingMessages(TLRPC.Message message) {
|
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) {
|
protected TLRPC.Message removeFromSendingMessages(int mid) {
|
||||||
TLRPC.Message message = sendingMessages.get(mid);
|
TLRPC.Message message;
|
||||||
if (message != null) {
|
if (mid > 0) {
|
||||||
sendingMessages.remove(mid);
|
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;
|
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) {
|
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) {
|
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.os.SystemClock;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.telegram.tgnet.ConnectionsManager;
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
|
@ -53,6 +54,9 @@ public class SharedConfig {
|
||||||
public static boolean useFingerprint = true;
|
public static boolean useFingerprint = true;
|
||||||
public static String lastUpdateVersion;
|
public static String lastUpdateVersion;
|
||||||
public static int suggestStickers;
|
public static int suggestStickers;
|
||||||
|
public static boolean loopStickers;
|
||||||
|
public static int keepMedia = 2;
|
||||||
|
public static int lastKeepMediaCheckTime;
|
||||||
private static int lastLocalId = -210000;
|
private static int lastLocalId = -210000;
|
||||||
|
|
||||||
private static String passportConfigJson = "";
|
private static String passportConfigJson = "";
|
||||||
|
@ -72,7 +76,6 @@ public class SharedConfig {
|
||||||
public static boolean directShare = true;
|
public static boolean directShare = true;
|
||||||
public static boolean inappCamera = true;
|
public static boolean inappCamera = true;
|
||||||
public static boolean roundCamera16to9 = true;
|
public static boolean roundCamera16to9 = true;
|
||||||
public static boolean groupPhotosEnabled = true;
|
|
||||||
public static boolean noSoundHintShowed = false;
|
public static boolean noSoundHintShowed = false;
|
||||||
public static boolean streamMedia = true;
|
public static boolean streamMedia = true;
|
||||||
public static boolean streamAllVideo = false;
|
public static boolean streamAllVideo = false;
|
||||||
|
@ -231,7 +234,6 @@ public class SharedConfig {
|
||||||
inappCamera = preferences.getBoolean("inappCamera", true);
|
inappCamera = preferences.getBoolean("inappCamera", true);
|
||||||
hasCameraCache = preferences.contains("cameraCache");
|
hasCameraCache = preferences.contains("cameraCache");
|
||||||
roundCamera16to9 = true;//preferences.getBoolean("roundCamera16to9", false);
|
roundCamera16to9 = true;//preferences.getBoolean("roundCamera16to9", false);
|
||||||
groupPhotosEnabled = preferences.getBoolean("groupPhotosEnabled", true);
|
|
||||||
repeatMode = preferences.getInt("repeatMode", 0);
|
repeatMode = preferences.getInt("repeatMode", 0);
|
||||||
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
|
fontSize = preferences.getInt("fons_size", AndroidUtilities.isTablet() ? 18 : 16);
|
||||||
allowBigEmoji = preferences.getBoolean("allowBigEmoji", true);
|
allowBigEmoji = preferences.getBoolean("allowBigEmoji", true);
|
||||||
|
@ -248,6 +250,9 @@ public class SharedConfig {
|
||||||
archiveHidden = preferences.getBoolean("archiveHidden", false);
|
archiveHidden = preferences.getBoolean("archiveHidden", false);
|
||||||
distanceSystemType = preferences.getInt("distanceSystemType", 0);
|
distanceSystemType = preferences.getInt("distanceSystemType", 0);
|
||||||
devicePerformanceClass = preferences.getInt("devicePerformanceClass", -1);
|
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);
|
preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
|
||||||
showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true);
|
showNotificationsForAllAccounts = preferences.getBoolean("AllAccounts", true);
|
||||||
|
@ -374,6 +379,64 @@ public class SharedConfig {
|
||||||
editor.commit();
|
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) {
|
public static void toggleShuffleMusic(int type) {
|
||||||
if (type == 2) {
|
if (type == 2) {
|
||||||
shuffleMusic = !shuffleMusic;
|
shuffleMusic = !shuffleMusic;
|
||||||
|
@ -545,14 +608,6 @@ public class SharedConfig {
|
||||||
editor.commit();
|
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) {
|
public static void setDistanceSystemType(int type) {
|
||||||
distanceSystemType = type;
|
distanceSystemType = type;
|
||||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
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 lastBroadcastId = -1;
|
||||||
public int contactsSavedCount;
|
public int contactsSavedCount;
|
||||||
public int clientUserId;
|
public int clientUserId;
|
||||||
public boolean blockedUsersLoaded;
|
|
||||||
public int lastContactsSyncTime;
|
public int lastContactsSyncTime;
|
||||||
public int lastHintsSyncTime;
|
public int lastHintsSyncTime;
|
||||||
public boolean draftsLoaded;
|
public boolean draftsLoaded;
|
||||||
|
@ -118,7 +117,6 @@ public class UserConfig extends BaseController {
|
||||||
editor.putInt("lastSendMessageId", lastSendMessageId);
|
editor.putInt("lastSendMessageId", lastSendMessageId);
|
||||||
editor.putInt("contactsSavedCount", contactsSavedCount);
|
editor.putInt("contactsSavedCount", contactsSavedCount);
|
||||||
editor.putInt("lastBroadcastId", lastBroadcastId);
|
editor.putInt("lastBroadcastId", lastBroadcastId);
|
||||||
editor.putBoolean("blockedUsersLoaded", blockedUsersLoaded);
|
|
||||||
editor.putInt("lastContactsSyncTime", lastContactsSyncTime);
|
editor.putInt("lastContactsSyncTime", lastContactsSyncTime);
|
||||||
editor.putInt("lastHintsSyncTime", lastHintsSyncTime);
|
editor.putInt("lastHintsSyncTime", lastHintsSyncTime);
|
||||||
editor.putBoolean("draftsLoaded", draftsLoaded);
|
editor.putBoolean("draftsLoaded", draftsLoaded);
|
||||||
|
@ -255,7 +253,6 @@ public class UserConfig extends BaseController {
|
||||||
lastSendMessageId = preferences.getInt("lastSendMessageId", -210000);
|
lastSendMessageId = preferences.getInt("lastSendMessageId", -210000);
|
||||||
contactsSavedCount = preferences.getInt("contactsSavedCount", 0);
|
contactsSavedCount = preferences.getInt("contactsSavedCount", 0);
|
||||||
lastBroadcastId = preferences.getInt("lastBroadcastId", -1);
|
lastBroadcastId = preferences.getInt("lastBroadcastId", -1);
|
||||||
blockedUsersLoaded = preferences.getBoolean("blockedUsersLoaded", false);
|
|
||||||
lastContactsSyncTime = preferences.getInt("lastContactsSyncTime", (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60);
|
lastContactsSyncTime = preferences.getInt("lastContactsSyncTime", (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60);
|
||||||
lastHintsSyncTime = preferences.getInt("lastHintsSyncTime", (int) (System.currentTimeMillis() / 1000) - 25 * 60 * 60);
|
lastHintsSyncTime = preferences.getInt("lastHintsSyncTime", (int) (System.currentTimeMillis() / 1000) - 25 * 60 * 60);
|
||||||
draftsLoaded = preferences.getBoolean("draftsLoaded", false);
|
draftsLoaded = preferences.getBoolean("draftsLoaded", false);
|
||||||
|
@ -399,7 +396,6 @@ public class UserConfig extends BaseController {
|
||||||
contactsSavedCount = 0;
|
contactsSavedCount = 0;
|
||||||
lastSendMessageId = -210000;
|
lastSendMessageId = -210000;
|
||||||
lastBroadcastId = -1;
|
lastBroadcastId = -1;
|
||||||
blockedUsersLoaded = false;
|
|
||||||
notificationsSettingsLoaded = false;
|
notificationsSettingsLoaded = false;
|
||||||
notificationsSignUpSettingsLoaded = false;
|
notificationsSignUpSettingsLoaded = false;
|
||||||
migrateOffsetId = -1;
|
migrateOffsetId = -1;
|
||||||
|
|
|
@ -91,11 +91,11 @@ public class Utilities {
|
||||||
aesCbcEncryptionByteArray(buffer, key, iv.clone(), offset, length, n, encrypt);
|
aesCbcEncryptionByteArray(buffer, key, iv.clone(), offset, length, n, encrypt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Integer parseInt(String value) {
|
public static Integer parseInt(CharSequence value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
Integer val = 0;
|
int val = 0;
|
||||||
try {
|
try {
|
||||||
Matcher matcher = pattern.matcher(value);
|
Matcher matcher = pattern.matcher(value);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
|
@ -112,7 +112,7 @@ public class Utilities {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
Long val = 0L;
|
long val = 0L;
|
||||||
try {
|
try {
|
||||||
Matcher matcher = pattern.matcher(value);
|
Matcher matcher = pattern.matcher(value);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
|
|
|
@ -15,6 +15,8 @@ import java.util.Locale;
|
||||||
public class VideoEditedInfo {
|
public class VideoEditedInfo {
|
||||||
public long startTime;
|
public long startTime;
|
||||||
public long endTime;
|
public long endTime;
|
||||||
|
public float start;
|
||||||
|
public float end;
|
||||||
public int rotationValue;
|
public int rotationValue;
|
||||||
public int originalWidth;
|
public int originalWidth;
|
||||||
public int originalHeight;
|
public int originalHeight;
|
||||||
|
|
|
@ -41,7 +41,6 @@ import org.telegram.messenger.support.customtabsclient.shared.ServiceConnectionC
|
||||||
import org.telegram.tgnet.ConnectionsManager;
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.AlertDialog;
|
import org.telegram.ui.ActionBar.AlertDialog;
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
|
||||||
import org.telegram.ui.LaunchActivity;
|
import org.telegram.ui.LaunchActivity;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
@ -287,7 +286,7 @@ public class Browser {
|
||||||
|
|
||||||
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getSession());
|
CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(getSession());
|
||||||
builder.addMenuItem(LocaleController.getString("CopyLink", R.string.CopyLink), copy);
|
builder.addMenuItem(LocaleController.getString("CopyLink", R.string.CopyLink), copy);
|
||||||
builder.setToolbarColor(Theme.getColor(Theme.key_actionBarDefault));
|
builder.setToolbarColor(0xffffffff);
|
||||||
builder.setShowTitle(true);
|
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);
|
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();
|
CustomTabsIntent intent = builder.build();
|
||||||
|
|
|
@ -242,6 +242,10 @@ public class CameraController implements MediaRecorder.OnInfoListener {
|
||||||
return cameraInitied && cameraInfos != null && !cameraInfos.isEmpty();
|
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) {
|
public void close(final CameraSession session, final CountDownLatch countDownLatch, final Runnable beforeDestroyRunnable) {
|
||||||
session.destroy();
|
session.destroy();
|
||||||
threadPool.execute(() -> {
|
threadPool.execute(() -> {
|
||||||
|
|
|
@ -38,23 +38,22 @@ public class CameraSession {
|
||||||
private final Size previewSize;
|
private final Size previewSize;
|
||||||
private final int pictureFormat;
|
private final int pictureFormat;
|
||||||
private boolean initied;
|
private boolean initied;
|
||||||
|
private int maxZoom;
|
||||||
private boolean meteringAreaSupported;
|
private boolean meteringAreaSupported;
|
||||||
private int currentOrientation;
|
private int currentOrientation;
|
||||||
private int diffOrientation;
|
private int diffOrientation;
|
||||||
private int jpegOrientation;
|
private int jpegOrientation;
|
||||||
private boolean sameTakePictureOrientation;
|
private boolean sameTakePictureOrientation;
|
||||||
private boolean flipFront = true;
|
private boolean flipFront = true;
|
||||||
|
private float currentZoom;
|
||||||
|
|
||||||
public static final int ORIENTATION_HYSTERESIS = 5;
|
public static final int ORIENTATION_HYSTERESIS = 5;
|
||||||
|
|
||||||
private Camera.AutoFocusCallback autoFocusCallback = new Camera.AutoFocusCallback() {
|
private Camera.AutoFocusCallback autoFocusCallback = (success, camera) -> {
|
||||||
@Override
|
if (success) {
|
||||||
public void onAutoFocus(boolean success, Camera camera) {
|
|
||||||
if (success) {
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -335,6 +334,10 @@ public class CameraSession {
|
||||||
params.setPreviewSize(previewSize.getWidth(), previewSize.getHeight());
|
params.setPreviewSize(previewSize.getWidth(), previewSize.getHeight());
|
||||||
params.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight());
|
params.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight());
|
||||||
params.setPictureFormat(pictureFormat);
|
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;
|
String desiredMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
|
||||||
if (params.getSupportedFocusModes().contains(desiredMode)) {
|
if (params.getSupportedFocusModes().contains(desiredMode)) {
|
||||||
|
@ -380,7 +383,6 @@ public class CameraSession {
|
||||||
try {
|
try {
|
||||||
Camera camera = cameraInfo.camera;
|
Camera camera = cameraInfo.camera;
|
||||||
if (camera != null) {
|
if (camera != null) {
|
||||||
|
|
||||||
camera.cancelAutoFocus();
|
camera.cancelAutoFocus();
|
||||||
Camera.Parameters parameters = null;
|
Camera.Parameters parameters = null;
|
||||||
try {
|
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) {
|
protected void configureRecorder(int quality, MediaRecorder recorder) {
|
||||||
Camera.CameraInfo info = new Camera.CameraInfo();
|
Camera.CameraInfo info = new Camera.CameraInfo();
|
||||||
Camera.getCameraInfo(cameraInfo.cameraId, info);
|
Camera.getCameraInfo(cameraInfo.cameraId, info);
|
||||||
|
@ -509,9 +520,10 @@ public class CameraSession {
|
||||||
cameraInfo.camera.setPreviewCallback(callback);
|
cameraInfo.camera.setPreviewCallback(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOneShotPreviewCallback(Camera.PreviewCallback callback){
|
public void setOneShotPreviewCallback(Camera.PreviewCallback callback) {
|
||||||
if(cameraInfo!=null && cameraInfo.camera!=null)
|
if (cameraInfo != null && cameraInfo.camera != null) {
|
||||||
cameraInfo.camera.setOneShotPreviewCallback(callback);
|
cameraInfo.camera.setOneShotPreviewCallback(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
||||||
private boolean initied;
|
private boolean initied;
|
||||||
private CameraViewDelegate delegate;
|
private CameraViewDelegate delegate;
|
||||||
private int clipTop;
|
private int clipTop;
|
||||||
private int clipLeft;
|
private int clipBottom;
|
||||||
private boolean isFrontface;
|
private boolean isFrontface;
|
||||||
private Matrix txform = new Matrix();
|
private Matrix txform = new Matrix();
|
||||||
private Matrix matrix = new Matrix();
|
private Matrix matrix = new Matrix();
|
||||||
|
@ -90,6 +90,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
||||||
return isFrontface;
|
return isFrontface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TextureView getTextureView() {
|
||||||
|
return textureView;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasFrontFaceCamera() {
|
public boolean hasFrontFaceCamera() {
|
||||||
ArrayList<CameraInfo> cameraInfos = CameraController.getInstance().getCameras();
|
ArrayList<CameraInfo> cameraInfos = CameraController.getInstance().getCameras();
|
||||||
for (int a = 0; a < cameraInfos.size(); a++) {
|
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) {
|
if (previewSize != null && surfaceTexture != null) {
|
||||||
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
|
||||||
cameraSession = new CameraSession(info, previewSize, pictureSize, ImageFormat.JPEG);
|
cameraSession = new CameraSession(info, previewSize, pictureSize, ImageFormat.JPEG);
|
||||||
CameraController.getInstance().open(cameraSession, surfaceTexture, new Runnable() {
|
CameraController.getInstance().open(cameraSession, surfaceTexture, () -> {
|
||||||
@Override
|
if (cameraSession != null) {
|
||||||
public void run() {
|
cameraSession.setInitied();
|
||||||
if (cameraSession != null) {
|
|
||||||
cameraSession.setInitied();
|
|
||||||
}
|
|
||||||
checkPreviewMatrix();
|
|
||||||
}
|
}
|
||||||
}, new Runnable() {
|
checkPreviewMatrix();
|
||||||
@Override
|
}, () -> {
|
||||||
public void run() {
|
if (delegate != null) {
|
||||||
if (delegate != null) {
|
delegate.onCameraCreated(cameraSession.cameraInfo.camera);
|
||||||
delegate.onCameraCreated(cameraSession.cameraInfo.camera);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -223,8 +221,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
||||||
clipTop = value;
|
clipTop = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClipLeft(int value) {
|
public void setClipBottom(int value) {
|
||||||
clipLeft = value;
|
clipBottom = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPreviewMatrix() {
|
private void checkPreviewMatrix() {
|
||||||
|
@ -244,9 +242,9 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
||||||
|
|
||||||
float scale;
|
float scale;
|
||||||
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
|
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 {
|
} 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;
|
float previewWidthScaled = previewWidth * scale;
|
||||||
|
@ -268,8 +266,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
||||||
if (mirror) {
|
if (mirror) {
|
||||||
txform.postScale(-1, 1, viewCenterX, viewCenterY);
|
txform.postScale(-1, 1, viewCenterX, viewCenterY);
|
||||||
}
|
}
|
||||||
if (clipTop != 0 || clipLeft != 0) {
|
if (clipTop != 0) {
|
||||||
txform.postTranslate(-clipLeft / 2, -clipTop / 2);
|
txform.postTranslate(0, -clipTop / 2);
|
||||||
|
} else if (clipBottom != 0) {
|
||||||
|
txform.postTranslate(0, clipBottom / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
textureView.setTransform(txform);
|
textureView.setTransform(txform);
|
||||||
|
@ -320,6 +320,12 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setZoom(float value) {
|
||||||
|
if (cameraSession != null) {
|
||||||
|
cameraSession.setZoom(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setDelegate(CameraViewDelegate cameraViewDelegate) {
|
public void setDelegate(CameraViewDelegate cameraViewDelegate) {
|
||||||
delegate = cameraViewDelegate;
|
delegate = cameraViewDelegate;
|
||||||
}
|
}
|
||||||
|
@ -339,6 +345,10 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Matrix getMatrix() {
|
||||||
|
return txform;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
||||||
boolean result = super.drawChild(canvas, child, drawingTime);
|
boolean result = super.drawChild(canvas, child, drawingTime);
|
||||||
|
|
|
@ -34,6 +34,8 @@ import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.telegram.messenger.FileLog;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
@ -162,8 +164,13 @@ public abstract class JobIntentService extends Service {
|
||||||
mServiceProcessing = true;
|
mServiceProcessing = true;
|
||||||
// Keep the device awake, but only for at most 10 minutes at a time
|
// Keep the device awake, but only for at most 10 minutes at a time
|
||||||
// (Similar to JobScheduler.)
|
// (Similar to JobScheduler.)
|
||||||
mRunWakeLock.acquire(2 * 60 * 1000L);
|
try {
|
||||||
mLaunchWakeLock.release();
|
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);
|
if (DEBUG) Log.d(TAG, "Processing next work: " + work);
|
||||||
onHandleWork(work.getIntent());
|
onHandleWork(work.getIntent());
|
||||||
if (DEBUG) Log.d(TAG, "Completing work: " + work);
|
if (DEBUG) Log.d(TAG, "Completing work: " + work);
|
||||||
work.complete();
|
try {
|
||||||
|
work.complete();
|
||||||
|
} catch (Throwable ignore) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG) Log.d(TAG, "Done processing work!");
|
if (DEBUG) Log.d(TAG, "Done processing work!");
|
||||||
|
|
|
@ -502,14 +502,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastDnsRequestTime = System.currentTimeMillis();
|
lastDnsRequestTime = System.currentTimeMillis();
|
||||||
if (second == 2) {
|
if (second == 1) {
|
||||||
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 (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
FileLog.d("start dns txt task");
|
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_seSystemLangCode(int currentAccount, String langCode);
|
||||||
public static native void native_setJava(boolean useJavaByteBuffers);
|
public static native void native_setJava(boolean useJavaByteBuffers);
|
||||||
public static native void native_setPushConnectionEnabled(int currentAccount, boolean value);
|
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 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);
|
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 static class DnsTxtLoadTask extends AsyncTask<Void, Void, NativeByteBuffer> {
|
||||||
|
|
||||||
private int currentAccount;
|
private int currentAccount;
|
||||||
|
private int responseDate;
|
||||||
|
|
||||||
public DnsTxtLoadTask(int instance) {
|
public DnsTxtLoadTask(int instance) {
|
||||||
super();
|
super();
|
||||||
|
@ -851,7 +845,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
} else {
|
} else {
|
||||||
googleDomain = "google.com";
|
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;
|
int len = Utilities.random.nextInt(116) + 13;
|
||||||
final String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
final String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
|
||||||
|
@ -867,6 +861,7 @@ public class ConnectionsManager extends BaseController {
|
||||||
httpConnection.setReadTimeout(5000);
|
httpConnection.setReadTimeout(5000);
|
||||||
httpConnection.connect();
|
httpConnection.connect();
|
||||||
httpConnectionStream = httpConnection.getInputStream();
|
httpConnectionStream = httpConnection.getInputStream();
|
||||||
|
responseDate = (int) (httpConnection.getDate() / 1000);
|
||||||
|
|
||||||
outbuf = new ByteArrayOutputStream();
|
outbuf = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
@ -941,17 +936,13 @@ public class ConnectionsManager extends BaseController {
|
||||||
protected void onPostExecute(final NativeByteBuffer result) {
|
protected void onPostExecute(final NativeByteBuffer result) {
|
||||||
Utilities.stageQueue.postRunnable(() -> {
|
Utilities.stageQueue.postRunnable(() -> {
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
currentTask = null;
|
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone(), responseDate);
|
||||||
native_applyDnsConfig(currentAccount, result.address, AccountInstance.getInstance(currentAccount).getUserConfig().getClientPhone());
|
|
||||||
} else {
|
} else {
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
FileLog.d("failed to get dns txt result");
|
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();
|
firebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
|
||||||
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder().setDeveloperModeEnabled(BuildConfig.DEBUG).build();
|
FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder().setDeveloperModeEnabled(BuildConfig.DEBUG).build();
|
||||||
firebaseRemoteConfig.setConfigSettings(configSettings);
|
firebaseRemoteConfig.setConfigSettings(configSettings);
|
||||||
String currentValue = firebaseRemoteConfig.getString("ipconfigv2");
|
String currentValue = firebaseRemoteConfig.getString("ipconfigv3");
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
FileLog.d("current firebase value = " + currentValue);
|
FileLog.d("current firebase value = " + currentValue);
|
||||||
}
|
}
|
||||||
|
@ -993,7 +984,8 @@ public class ConnectionsManager extends BaseController {
|
||||||
try {
|
try {
|
||||||
NativeByteBuffer buffer = new NativeByteBuffer(bytes.length);
|
NativeByteBuffer buffer = new NativeByteBuffer(bytes.length);
|
||||||
buffer.writeBytes(bytes);
|
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) {
|
} catch (Exception e) {
|
||||||
FileLog.e(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);
|
menu.setSearchFieldText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onSearchPressed() {
|
||||||
|
menu.onSearchPressed();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
super.setEnabled(enabled);
|
super.setEnabled(enabled);
|
||||||
|
|
|
@ -1112,7 +1112,7 @@ public class ActionBarLayout extends FrameLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
previousFragment.onTransitionAnimationStart(true, true);
|
previousFragment.onTransitionAnimationStart(true, true);
|
||||||
currentFragment.onTransitionAnimationStart(false, false);
|
currentFragment.onTransitionAnimationStart(false, true);
|
||||||
previousFragment.onResume();
|
previousFragment.onResume();
|
||||||
if (themeAnimatorSet != null) {
|
if (themeAnimatorSet != null) {
|
||||||
presentingFragmentDescriptions = previousFragment.getThemeDescriptions();
|
presentingFragmentDescriptions = previousFragment.getThemeDescriptions();
|
||||||
|
@ -1140,7 +1140,7 @@ public class ActionBarLayout extends FrameLayout {
|
||||||
containerViewBack.setTranslationX(0);
|
containerViewBack.setTranslationX(0);
|
||||||
}
|
}
|
||||||
closeLastFragmentInternalRemoveOld(currentFragment);
|
closeLastFragmentInternalRemoveOld(currentFragment);
|
||||||
currentFragment.onTransitionAnimationEnd(false, false);
|
currentFragment.onTransitionAnimationEnd(false, true);
|
||||||
previousFragmentFinal.onTransitionAnimationEnd(true, true);
|
previousFragmentFinal.onTransitionAnimationEnd(true, true);
|
||||||
previousFragmentFinal.onBecomeFullyVisible();
|
previousFragmentFinal.onBecomeFullyVisible();
|
||||||
};
|
};
|
||||||
|
@ -1168,7 +1168,7 @@ public class ActionBarLayout extends FrameLayout {
|
||||||
currentAnimation = animation;
|
currentAnimation = animation;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentFragment.onTransitionAnimationEnd(false, false);
|
currentFragment.onTransitionAnimationEnd(false, true);
|
||||||
previousFragment.onTransitionAnimationEnd(true, true);
|
previousFragment.onTransitionAnimationEnd(true, true);
|
||||||
previousFragment.onBecomeFullyVisible();
|
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) {
|
public void openSearchField(boolean toggle, String text, boolean animated) {
|
||||||
int count = getChildCount();
|
int count = getChildCount();
|
||||||
for (int a = 0; a < count; a++) {
|
for (int a = 0; a < count; a++) {
|
||||||
|
|
|
@ -99,7 +99,8 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
private boolean animationEnabled = true;
|
private boolean animationEnabled = true;
|
||||||
private boolean ignoreOnTextChange;
|
private boolean ignoreOnTextChange;
|
||||||
private CloseProgressDrawable2 progressDrawable;
|
private CloseProgressDrawable2 progressDrawable;
|
||||||
private int additionalOffset;
|
private int additionalYOffset;
|
||||||
|
private int additionalXOffset;
|
||||||
private boolean longClickEnabled = true;
|
private boolean longClickEnabled = true;
|
||||||
private boolean animateClear = 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) {
|
public void addSubItem(View view, int width, int height) {
|
||||||
createPopupLayout();
|
createPopupLayout();
|
||||||
popupLayout.addView(view, new LinearLayout.LayoutParams(width, height));
|
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.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0);
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
textView.setMinWidth(AndroidUtilities.dp(196));
|
textView.setMinWidth(AndroidUtilities.dp(196));
|
||||||
|
textView.setSingleLine(true);
|
||||||
|
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
textView.setTag(id);
|
textView.setTag(id);
|
||||||
textView.setText(text);
|
textView.setText(text);
|
||||||
popupLayout.addView(textView);
|
popupLayout.addView(textView);
|
||||||
|
@ -534,6 +544,12 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onSearchPressed() {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onSearchPressed(searchField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public EditTextBoldCursor getSearchField() {
|
public EditTextBoldCursor getSearchField() {
|
||||||
return searchField;
|
return searchField;
|
||||||
}
|
}
|
||||||
|
@ -827,8 +843,12 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAdditionalOffset(int value) {
|
public void setAdditionalYOffset(int value) {
|
||||||
additionalOffset = value;
|
additionalYOffset = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAdditionalXOffset(int value) {
|
||||||
|
additionalXOffset = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOrShowPopup(boolean show, boolean update) {
|
private void updateOrShowPopup(boolean show, boolean update) {
|
||||||
|
@ -838,7 +858,7 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
offsetY = -parentMenu.parentActionBar.getMeasuredHeight() + parentMenu.getTop() + parentMenu.getPaddingTop();
|
offsetY = -parentMenu.parentActionBar.getMeasuredHeight() + parentMenu.getTop() + parentMenu.getPaddingTop();
|
||||||
} else {
|
} else {
|
||||||
float scaleY = getScaleY();
|
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;
|
offsetY += yOffset;
|
||||||
|
|
||||||
|
@ -868,25 +888,25 @@ public class ActionBarMenuItem extends FrameLayout {
|
||||||
if (getParent() != null) {
|
if (getParent() != null) {
|
||||||
View parent = (View) getParent();
|
View parent = (View) getParent();
|
||||||
if (show) {
|
if (show) {
|
||||||
popupWindow.showAsDropDown(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY);
|
popupWindow.showAsDropDown(parent, getLeft() + getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY);
|
||||||
}
|
}
|
||||||
if (update) {
|
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) {
|
} else if (subMenuOpenSide == 1) {
|
||||||
if (show) {
|
if (show) {
|
||||||
popupWindow.showAsDropDown(this, -AndroidUtilities.dp(8), offsetY);
|
popupWindow.showAsDropDown(this, -AndroidUtilities.dp(8) + additionalXOffset, offsetY);
|
||||||
}
|
}
|
||||||
if (update) {
|
if (update) {
|
||||||
popupWindow.update(this, -AndroidUtilities.dp(8), offsetY, -1, -1);
|
popupWindow.update(this, -AndroidUtilities.dp(8) + additionalXOffset, offsetY, -1, -1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (show) {
|
if (show) {
|
||||||
popupWindow.showAsDropDown(this, getMeasuredWidth() - popupLayout.getMeasuredWidth(), offsetY);
|
popupWindow.showAsDropDown(this, getMeasuredWidth() - popupLayout.getMeasuredWidth() + additionalXOffset, offsetY);
|
||||||
}
|
}
|
||||||
if (update) {
|
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.
|
* Copyright Nikolai Kudashov, 2013-2018.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//Thanks to https://github.com/JakeWharton/ActionBarSherlock/
|
|
||||||
|
|
||||||
package org.telegram.ui.ActionBar;
|
package org.telegram.ui.ActionBar;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -24,6 +23,7 @@ import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.view.animation.DecelerateInterpolator;
|
import android.view.animation.DecelerateInterpolator;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
@ -37,6 +37,7 @@ import org.telegram.ui.Components.LayoutHelper;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class ActionBarPopupWindow extends PopupWindow {
|
public class ActionBarPopupWindow extends PopupWindow {
|
||||||
|
@ -79,6 +80,7 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
private int lastStartedChild = 0;
|
private int lastStartedChild = 0;
|
||||||
private boolean showedFromBotton;
|
private boolean showedFromBotton;
|
||||||
private boolean animationEnabled = allowAnimation;
|
private boolean animationEnabled = allowAnimation;
|
||||||
|
private ArrayList<AnimatorSet> itemAnimators;
|
||||||
private HashMap<View, Integer> positions = new HashMap<>();
|
private HashMap<View, Integer> positions = new HashMap<>();
|
||||||
|
|
||||||
private ScrollView scrollView;
|
private ScrollView scrollView;
|
||||||
|
@ -141,11 +143,6 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
public void setBackScaleY(float value) {
|
public void setBackScaleY(float value) {
|
||||||
backScaleY = value;
|
backScaleY = value;
|
||||||
if (animationEnabled) {
|
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);
|
int height = getMeasuredHeight() - AndroidUtilities.dp(16);
|
||||||
if (showedFromBotton) {
|
if (showedFromBotton) {
|
||||||
for (int a = lastStartedChild; a >= 0; a--) {
|
for (int a = lastStartedChild; a >= 0; a--) {
|
||||||
|
@ -161,6 +158,7 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
startChildAnimation(child);
|
startChildAnimation(child);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
int count = getItemsCount();
|
||||||
for (int a = lastStartedChild; a < count; a++) {
|
for (int a = lastStartedChild; a < count; a++) {
|
||||||
View child = getItemAt(a);
|
View child = getItemAt(a);
|
||||||
if (child.getVisibility() != VISIBLE) {
|
if (child.getVisibility() != VISIBLE) {
|
||||||
|
@ -186,11 +184,21 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
if (animationEnabled) {
|
if (animationEnabled) {
|
||||||
AnimatorSet animatorSet = new AnimatorSet();
|
AnimatorSet animatorSet = new AnimatorSet();
|
||||||
animatorSet.playTogether(
|
animatorSet.playTogether(
|
||||||
ObjectAnimator.ofFloat(child, "alpha", 0.0f, 1.0f),
|
ObjectAnimator.ofFloat(child, View.ALPHA, 0.0f, 1.0f),
|
||||||
ObjectAnimator.ofFloat(child, "translationY", AndroidUtilities.dp(showedFromBotton ? 6 : -6), 0));
|
ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, AndroidUtilities.dp(showedFromBotton ? 6 : -6), 0));
|
||||||
animatorSet.setDuration(180);
|
animatorSet.setDuration(180);
|
||||||
|
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
itemAnimators.remove(animatorSet);
|
||||||
|
}
|
||||||
|
});
|
||||||
animatorSet.setInterpolator(decelerateInterpolator);
|
animatorSet.setInterpolator(decelerateInterpolator);
|
||||||
animatorSet.start();
|
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() {
|
public int getItemsCount() {
|
||||||
return linearLayout.getChildCount();
|
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
|
@Override
|
||||||
public void showAsDropDown(View anchor, int xoff, int yoff) {
|
public void showAsDropDown(View anchor, int xoff, int yoff) {
|
||||||
try {
|
try {
|
||||||
|
@ -362,11 +384,11 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
int visibleCount = 0;
|
int visibleCount = 0;
|
||||||
for (int a = 0; a < count; a++) {
|
for (int a = 0; a < count; a++) {
|
||||||
View child = content.getItemAt(a);
|
View child = content.getItemAt(a);
|
||||||
|
child.setAlpha(0.0f);
|
||||||
if (child.getVisibility() != View.VISIBLE) {
|
if (child.getVisibility() != View.VISIBLE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
content.positions.put(child, visibleCount);
|
content.positions.put(child, visibleCount);
|
||||||
child.setAlpha(0.0f);
|
|
||||||
visibleCount++;
|
visibleCount++;
|
||||||
}
|
}
|
||||||
if (content.showedFromBotton) {
|
if (content.showedFromBotton) {
|
||||||
|
@ -388,6 +410,12 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
windowAnimatorSet = null;
|
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
|
@Override
|
||||||
|
@ -434,10 +462,16 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
windowAnimatorSet.cancel();
|
windowAnimatorSet.cancel();
|
||||||
}
|
}
|
||||||
ActionBarPopupWindowLayout content = (ActionBarPopupWindowLayout) getContentView();
|
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 = new AnimatorSet();
|
||||||
windowAnimatorSet.playTogether(
|
windowAnimatorSet.playTogether(
|
||||||
ObjectAnimator.ofFloat(content, "translationY", AndroidUtilities.dp(content.showedFromBotton ? 5 : -5)),
|
ObjectAnimator.ofFloat(content, View.TRANSLATION_Y, AndroidUtilities.dp(content.showedFromBotton ? 5 : -5)),
|
||||||
ObjectAnimator.ofFloat(content, "alpha", 0.0f));
|
ObjectAnimator.ofFloat(content, View.ALPHA, 0.0f));
|
||||||
windowAnimatorSet.setDuration(dismissAnimationDuration);
|
windowAnimatorSet.setDuration(dismissAnimationDuration);
|
||||||
windowAnimatorSet.addListener(new Animator.AnimatorListener() {
|
windowAnimatorSet.addListener(new Animator.AnimatorListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -451,8 +485,8 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
setFocusable(false);
|
setFocusable(false);
|
||||||
try {
|
try {
|
||||||
ActionBarPopupWindow.super.dismiss();
|
ActionBarPopupWindow.super.dismiss();
|
||||||
} catch (Exception e) {
|
} catch (Exception ignore) {
|
||||||
//don't promt
|
|
||||||
}
|
}
|
||||||
unregisterListener();
|
unregisterListener();
|
||||||
}
|
}
|
||||||
|
@ -471,8 +505,8 @@ public class ActionBarPopupWindow extends PopupWindow {
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
super.dismiss();
|
super.dismiss();
|
||||||
} catch (Exception e) {
|
} catch (Exception ignore) {
|
||||||
//don't promt
|
|
||||||
}
|
}
|
||||||
unregisterListener();
|
unregisterListener();
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.view.WindowInsets;
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -47,6 +48,7 @@ import org.telegram.messenger.FileLog;
|
||||||
import org.telegram.messenger.NotificationCenter;
|
import org.telegram.messenger.NotificationCenter;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.UserConfig;
|
import org.telegram.messenger.UserConfig;
|
||||||
|
import org.telegram.ui.Components.AnimationProperties;
|
||||||
import org.telegram.ui.Components.CubicBezierInterpolator;
|
import org.telegram.ui.Components.CubicBezierInterpolator;
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
|
|
||||||
|
@ -84,6 +86,7 @@ public class BottomSheet extends Dialog {
|
||||||
|
|
||||||
private int touchSlop;
|
private int touchSlop;
|
||||||
private boolean useFastDismiss;
|
private boolean useFastDismiss;
|
||||||
|
protected Interpolator openInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT;
|
||||||
|
|
||||||
private TextView titleView;
|
private TextView titleView;
|
||||||
|
|
||||||
|
@ -93,7 +96,7 @@ public class BottomSheet extends Dialog {
|
||||||
|
|
||||||
private boolean allowNestedScroll = true;
|
private boolean allowNestedScroll = true;
|
||||||
|
|
||||||
private Drawable shadowDrawable;
|
protected Drawable shadowDrawable;
|
||||||
protected int backgroundPaddingTop;
|
protected int backgroundPaddingTop;
|
||||||
protected int backgroundPaddingLeft;
|
protected int backgroundPaddingLeft;
|
||||||
|
|
||||||
|
@ -107,6 +110,7 @@ public class BottomSheet extends Dialog {
|
||||||
private BottomSheetDelegateInterface delegate;
|
private BottomSheetDelegateInterface delegate;
|
||||||
|
|
||||||
protected AnimatorSet currentSheetAnimation;
|
protected AnimatorSet currentSheetAnimation;
|
||||||
|
protected int currentSheetAnimationType;
|
||||||
|
|
||||||
protected View nestedScrollChild;
|
protected View nestedScrollChild;
|
||||||
|
|
||||||
|
@ -681,6 +685,27 @@ public class BottomSheet extends Dialog {
|
||||||
window.setAttributes(params);
|
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) {
|
public void setShowWithoutAnimation(boolean value) {
|
||||||
showWithoutAnimation = value;
|
showWithoutAnimation = value;
|
||||||
}
|
}
|
||||||
|
@ -778,6 +803,7 @@ public class BottomSheet extends Dialog {
|
||||||
if (currentSheetAnimation != null) {
|
if (currentSheetAnimation != null) {
|
||||||
currentSheetAnimation.cancel();
|
currentSheetAnimation.cancel();
|
||||||
currentSheetAnimation = null;
|
currentSheetAnimation = null;
|
||||||
|
currentSheetAnimationType = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -792,18 +818,20 @@ public class BottomSheet extends Dialog {
|
||||||
container.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
container.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||||
}
|
}
|
||||||
containerView.setTranslationY(containerView.getMeasuredHeight());
|
containerView.setTranslationY(containerView.getMeasuredHeight());
|
||||||
AnimatorSet animatorSet = new AnimatorSet();
|
currentSheetAnimationType = 1;
|
||||||
animatorSet.playTogether(
|
currentSheetAnimation = new AnimatorSet();
|
||||||
ObjectAnimator.ofFloat(containerView, "translationY", 0),
|
currentSheetAnimation.playTogether(
|
||||||
ObjectAnimator.ofInt(backDrawable, "alpha", dimBehind ? 51 : 0));
|
ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, 0),
|
||||||
animatorSet.setDuration(400);
|
ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, dimBehind ? 51 : 0));
|
||||||
animatorSet.setStartDelay(20);
|
currentSheetAnimation.setDuration(400);
|
||||||
animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
|
currentSheetAnimation.setStartDelay(20);
|
||||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
currentSheetAnimation.setInterpolator(openInterpolator);
|
||||||
|
currentSheetAnimation.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||||
currentSheetAnimation = null;
|
currentSheetAnimation = null;
|
||||||
|
currentSheetAnimationType = 0;
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
delegate.onOpenAnimationEnd();
|
delegate.onOpenAnimationEnd();
|
||||||
}
|
}
|
||||||
|
@ -824,12 +852,12 @@ public class BottomSheet extends Dialog {
|
||||||
public void onAnimationCancel(Animator animation) {
|
public void onAnimationCancel(Animator animation) {
|
||||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||||
currentSheetAnimation = null;
|
currentSheetAnimation = null;
|
||||||
|
currentSheetAnimationType = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
||||||
animatorSet.start();
|
currentSheetAnimation.start();
|
||||||
currentSheetAnimation = animatorSet;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,18 +921,20 @@ public class BottomSheet extends Dialog {
|
||||||
}
|
}
|
||||||
dismissed = true;
|
dismissed = true;
|
||||||
cancelSheetAnimation();
|
cancelSheetAnimation();
|
||||||
AnimatorSet animatorSet = new AnimatorSet();
|
currentSheetAnimationType = 2;
|
||||||
animatorSet.playTogether(
|
currentSheetAnimation = new AnimatorSet();
|
||||||
|
currentSheetAnimation.playTogether(
|
||||||
ObjectAnimator.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)),
|
ObjectAnimator.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)),
|
||||||
ObjectAnimator.ofInt(backDrawable, "alpha", 0)
|
ObjectAnimator.ofInt(backDrawable, "alpha", 0)
|
||||||
);
|
);
|
||||||
animatorSet.setDuration(180);
|
currentSheetAnimation.setDuration(180);
|
||||||
animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
currentSheetAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
||||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
currentSheetAnimation.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||||
currentSheetAnimation = null;
|
currentSheetAnimation = null;
|
||||||
|
currentSheetAnimationType = 0;
|
||||||
if (onClickListener != null) {
|
if (onClickListener != null) {
|
||||||
onClickListener.onClick(BottomSheet.this, item);
|
onClickListener.onClick(BottomSheet.this, item);
|
||||||
}
|
}
|
||||||
|
@ -923,12 +953,12 @@ public class BottomSheet extends Dialog {
|
||||||
public void onAnimationCancel(Animator animation) {
|
public void onAnimationCancel(Animator animation) {
|
||||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||||
currentSheetAnimation = null;
|
currentSheetAnimation = null;
|
||||||
|
currentSheetAnimationType = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
||||||
animatorSet.start();
|
currentSheetAnimation.start();
|
||||||
currentSheetAnimation = animatorSet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -942,24 +972,26 @@ public class BottomSheet extends Dialog {
|
||||||
dismissed = true;
|
dismissed = true;
|
||||||
cancelSheetAnimation();
|
cancelSheetAnimation();
|
||||||
if (!allowCustomAnimation || !onCustomCloseAnimation()) {
|
if (!allowCustomAnimation || !onCustomCloseAnimation()) {
|
||||||
AnimatorSet animatorSet = new AnimatorSet();
|
currentSheetAnimationType = 2;
|
||||||
animatorSet.playTogether(
|
currentSheetAnimation = new AnimatorSet();
|
||||||
|
currentSheetAnimation.playTogether(
|
||||||
ObjectAnimator.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)),
|
ObjectAnimator.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)),
|
||||||
ObjectAnimator.ofInt(backDrawable, "alpha", 0)
|
ObjectAnimator.ofInt(backDrawable, "alpha", 0)
|
||||||
);
|
);
|
||||||
if (useFastDismiss) {
|
if (useFastDismiss) {
|
||||||
int height = containerView.getMeasuredHeight();
|
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;
|
useFastDismiss = false;
|
||||||
} else {
|
} else {
|
||||||
animatorSet.setDuration(180);
|
currentSheetAnimation.setDuration(180);
|
||||||
}
|
}
|
||||||
animatorSet.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
currentSheetAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT);
|
||||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
currentSheetAnimation.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||||
currentSheetAnimation = null;
|
currentSheetAnimation = null;
|
||||||
|
currentSheetAnimationType = 0;
|
||||||
AndroidUtilities.runOnUIThread(() -> {
|
AndroidUtilities.runOnUIThread(() -> {
|
||||||
try {
|
try {
|
||||||
dismissInternal();
|
dismissInternal();
|
||||||
|
@ -975,12 +1007,12 @@ public class BottomSheet extends Dialog {
|
||||||
public void onAnimationCancel(Animator animation) {
|
public void onAnimationCancel(Animator animation) {
|
||||||
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) {
|
||||||
currentSheetAnimation = null;
|
currentSheetAnimation = null;
|
||||||
|
currentSheetAnimationType = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512);
|
||||||
animatorSet.start();
|
currentSheetAnimation.start();
|
||||||
currentSheetAnimation = animatorSet;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,12 +136,6 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
||||||
textWidth = (int) Math.ceil(layout.getLineWidth(0));
|
textWidth = (int) Math.ceil(layout.getLineWidth(0));
|
||||||
textHeight = layout.getLineBottom(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) {
|
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT) {
|
||||||
offsetX = -(int) layout.getLineLeft(0);
|
offsetX = -(int) layout.getLineLeft(0);
|
||||||
} else if (layout.getLineLeft(0) == 0) {
|
} else if (layout.getLineLeft(0) == 0) {
|
||||||
|
@ -207,6 +201,12 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
||||||
finalHeight = textHeight;
|
finalHeight = textHeight;
|
||||||
}
|
}
|
||||||
setMeasuredDimension(width, finalHeight);
|
setMeasuredDimension(width, finalHeight);
|
||||||
|
|
||||||
|
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.CENTER_VERTICAL) {
|
||||||
|
offsetY = (getMeasuredHeight() - textHeight) / 2;
|
||||||
|
} else {
|
||||||
|
offsetY = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -306,7 +306,13 @@ public class SimpleTextView extends View implements Drawable.Callback {
|
||||||
|
|
||||||
private boolean recreateLayoutMaybe() {
|
private boolean recreateLayoutMaybe() {
|
||||||
if (wasLayout && getMeasuredHeight() != 0) {
|
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 {
|
} else {
|
||||||
requestLayout();
|
requestLayout();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.ColorFilter;
|
import android.graphics.ColorFilter;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Path;
|
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
@ -207,91 +206,6 @@ public class Theme {
|
||||||
public static double autoNightLocationLatitude = 10000;
|
public static double autoNightLocationLatitude = 10000;
|
||||||
public static double autoNightLocationLongitude = 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);
|
private static Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
|
|
||||||
public static ArrayList<ThemeInfo> themes;
|
public static ArrayList<ThemeInfo> themes;
|
||||||
|
@ -505,7 +419,8 @@ public class Theme {
|
||||||
public static Drawable chat_msgCallDownGreenDrawable;
|
public static Drawable chat_msgCallDownGreenDrawable;
|
||||||
|
|
||||||
public static Drawable chat_msgAvatarLiveLocationDrawable;
|
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_locationDrawable = new Drawable[2];
|
||||||
public static Drawable[] chat_contactDrawable = new Drawable[2];
|
public static Drawable[] chat_contactDrawable = new Drawable[2];
|
||||||
public static Drawable[] chat_cornerOuter = new Drawable[4];
|
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_actionUnreadBackground = "chats_actionUnreadBackground";
|
||||||
public static final String key_chats_actionUnreadPressedBackground = "chats_actionUnreadPressedBackground";
|
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_attachMediaBanBackground = "chat_attachMediaBanBackground";
|
||||||
public static final String key_chat_attachMediaBanText = "chat_attachMediaBanText";
|
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_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_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_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_attachAudioIcon = "chat_attachAudioIcon";
|
||||||
public static final String key_chat_attachFileBackground = "chat_attachFileBackground";
|
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_attachFileIcon = "chat_attachFileIcon";
|
||||||
public static final String key_chat_attachContactBackground = "chat_attachContactBackground";
|
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_attachContactIcon = "chat_attachContactIcon";
|
||||||
public static final String key_chat_attachLocationBackground = "chat_attachLocationBackground";
|
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_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_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_attachPollIcon = "chat_attachPollIcon";
|
||||||
|
|
||||||
public static final String key_chat_status = "chat_status";
|
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_messagePanelHint = "chat_messagePanelHint";
|
||||||
public static final String key_chat_messagePanelIcons = "chat_messagePanelIcons";
|
public static final String key_chat_messagePanelIcons = "chat_messagePanelIcons";
|
||||||
public static final String key_chat_messagePanelSend = "chat_messagePanelSend";
|
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_messagePanelVoiceLock = "key_chat_messagePanelVoiceLock";
|
||||||
public static final String key_chat_messagePanelVoiceLockBackground = "key_chat_messagePanelVoiceLockBackground";
|
public static final String key_chat_messagePanelVoiceLockBackground = "key_chat_messagePanelVoiceLockBackground";
|
||||||
public static final String key_chat_messagePanelVoiceLockShadow = "key_chat_messagePanelVoiceLockShadow";
|
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_actionUnreadPressedBackground, 0xfff2f2f2);
|
||||||
defaultColors.put(key_chats_menuTopBackgroundCats, 0xff598fba);
|
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_attachMediaBanBackground, 0xff464646);
|
||||||
defaultColors.put(key_chat_attachMediaBanText, 0xffffffff);
|
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_attachGalleryBackground, 0xff459df5);
|
||||||
//defaultColors.put(key_chat_attachGalleryBackgroundPressed, 0xffa47ad9);
|
|
||||||
defaultColors.put(key_chat_attachGalleryIcon, 0xffffffff);
|
defaultColors.put(key_chat_attachGalleryIcon, 0xffffffff);
|
||||||
defaultColors.put(key_chat_attachVideoBackground, 0xffe37179);
|
defaultColors.put(key_chat_attachAudioBackground, 0xffeb6060);
|
||||||
//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_attachAudioIcon, 0xffffffff);
|
defaultColors.put(key_chat_attachAudioIcon, 0xffffffff);
|
||||||
defaultColors.put(key_chat_attachFileBackground, 0xff34a0f4);
|
defaultColors.put(key_chat_attachFileBackground, 0xff34b9f1);
|
||||||
//defaultColors.put(key_chat_attachFileBackgroundPressed, 0xff34a0f4);
|
|
||||||
defaultColors.put(key_chat_attachFileIcon, 0xffffffff);
|
defaultColors.put(key_chat_attachFileIcon, 0xffffffff);
|
||||||
defaultColors.put(key_chat_attachContactBackground, 0xff3ebffa);
|
defaultColors.put(key_chat_attachContactBackground, 0xfff2c04b);
|
||||||
//defaultColors.put(key_chat_attachContactBackgroundPressed, 0xff3ebffa);
|
|
||||||
defaultColors.put(key_chat_attachContactIcon, 0xffffffff);
|
defaultColors.put(key_chat_attachContactIcon, 0xffffffff);
|
||||||
defaultColors.put(key_chat_attachLocationBackground, 0xff3fc87a);
|
defaultColors.put(key_chat_attachLocationBackground, 0xff36c766);
|
||||||
//defaultColors.put(key_chat_attachLocationBackgroundPressed, 0xff3fc87a);
|
|
||||||
defaultColors.put(key_chat_attachLocationIcon, 0xffffffff);
|
defaultColors.put(key_chat_attachLocationIcon, 0xffffffff);
|
||||||
defaultColors.put(key_chat_attachHideBackground, 0xffaeaab8);
|
defaultColors.put(key_chat_attachPollBackground, 0xfff2c04b);
|
||||||
//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_attachPollIcon, 0xffffffff);
|
defaultColors.put(key_chat_attachPollIcon, 0xffffffff);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1446,7 +1339,6 @@ public class Theme {
|
||||||
defaultColors.put(key_chat_inGreenCall, 0xff00c853);
|
defaultColors.put(key_chat_inGreenCall, 0xff00c853);
|
||||||
defaultColors.put(key_chat_inRedCall, 0xffff4848);
|
defaultColors.put(key_chat_inRedCall, 0xffff4848);
|
||||||
defaultColors.put(key_chat_outGreenCall, 0xff00c853);
|
defaultColors.put(key_chat_outGreenCall, 0xff00c853);
|
||||||
defaultColors.put(key_chat_attachSendIcon, 0xffffffff);
|
|
||||||
defaultColors.put(key_chat_shareBackground, 0x66728fa6);
|
defaultColors.put(key_chat_shareBackground, 0x66728fa6);
|
||||||
defaultColors.put(key_chat_shareBackgroundSelected, 0x99728fa6);
|
defaultColors.put(key_chat_shareBackgroundSelected, 0x99728fa6);
|
||||||
defaultColors.put(key_chat_lockIcon, 0xffffffff);
|
defaultColors.put(key_chat_lockIcon, 0xffffffff);
|
||||||
|
@ -1652,6 +1544,7 @@ public class Theme {
|
||||||
defaultColors.put(key_chat_recordedVoiceProgressInner, 0xffffffff);
|
defaultColors.put(key_chat_recordedVoiceProgressInner, 0xffffffff);
|
||||||
defaultColors.put(key_chat_recordVoiceCancel, 0xff999999);
|
defaultColors.put(key_chat_recordVoiceCancel, 0xff999999);
|
||||||
defaultColors.put(key_chat_messagePanelSend, 0xff62b0eb);
|
defaultColors.put(key_chat_messagePanelSend, 0xff62b0eb);
|
||||||
|
defaultColors.put(key_chat_messagePanelSendPressed, 0xffffffff);
|
||||||
defaultColors.put(key_chat_messagePanelVoiceLock, 0xffa4a4a4);
|
defaultColors.put(key_chat_messagePanelVoiceLock, 0xffa4a4a4);
|
||||||
defaultColors.put(key_chat_messagePanelVoiceLockBackground, 0xffffffff);
|
defaultColors.put(key_chat_messagePanelVoiceLockBackground, 0xffffffff);
|
||||||
defaultColors.put(key_chat_messagePanelVoiceLockShadow, 0xff000000);
|
defaultColors.put(key_chat_messagePanelVoiceLockShadow, 0xff000000);
|
||||||
|
@ -1893,6 +1786,13 @@ public class Theme {
|
||||||
fallbackKeys.put(key_actionBarTabSelector, key_actionBarDefaultSelector);
|
fallbackKeys.put(key_actionBarTabSelector, key_actionBarDefaultSelector);
|
||||||
fallbackKeys.put(key_profile_status, key_avatar_subtitleInProfileBlue);
|
fallbackKeys.put(key_profile_status, key_avatar_subtitleInProfileBlue);
|
||||||
fallbackKeys.put(key_chats_menuTopBackgroundCats, key_avatar_backgroundActionBarBlue);
|
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<>();
|
themes = new ArrayList<>();
|
||||||
otherThemes = new ArrayList<>();
|
otherThemes = new ArrayList<>();
|
||||||
|
@ -2407,30 +2307,45 @@ public class Theme {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Drawable createSelectorDrawable(int color) {
|
public static Drawable createSelectorDrawable(int color) {
|
||||||
return createSelectorDrawable(color, 1);
|
return createSelectorDrawable(color, 1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Drawable createSelectorDrawable(int color, int maskType) {
|
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;
|
Drawable drawable;
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
Drawable maskDrawable = null;
|
Drawable maskDrawable = null;
|
||||||
if ((maskType == 1 || maskType == 5) && Build.VERSION.SDK_INT >= 23) {
|
if ((maskType == 1 || maskType == 5) && Build.VERSION.SDK_INT >= 23) {
|
||||||
maskDrawable = null;
|
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);
|
maskPaint.setColor(0xffffffff);
|
||||||
maskDrawable = new Drawable() {
|
maskDrawable = new Drawable() {
|
||||||
|
|
||||||
|
RectF rect;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas) {
|
public void draw(Canvas canvas) {
|
||||||
android.graphics.Rect bounds = getBounds();
|
android.graphics.Rect bounds = getBounds();
|
||||||
int rad;
|
if (maskType == 7) {
|
||||||
if (maskType == 1) {
|
if (rect == null) {
|
||||||
rad = AndroidUtilities.dp(20);
|
rect = new RectF();
|
||||||
} else if (maskType == 3) {
|
}
|
||||||
rad = (Math.max(bounds.width(), bounds.height()) / 2);
|
rect.set(bounds);
|
||||||
|
canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), maskPaint);
|
||||||
} else {
|
} 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
|
@Override
|
||||||
|
@ -2458,7 +2373,7 @@ public class Theme {
|
||||||
RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, null, maskDrawable);
|
RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, null, maskDrawable);
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
if (maskType == 1) {
|
if (maskType == 1) {
|
||||||
rippleDrawable.setRadius(AndroidUtilities.dp(20));
|
rippleDrawable.setRadius(radius <= 0 ? AndroidUtilities.dp(20) : radius);
|
||||||
} else if (maskType == 5) {
|
} else if (maskType == 5) {
|
||||||
rippleDrawable.setRadius(RippleDrawable.RADIUS_AUTO);
|
rippleDrawable.setRadius(RippleDrawable.RADIUS_AUTO);
|
||||||
}
|
}
|
||||||
|
@ -3352,16 +3267,13 @@ public class Theme {
|
||||||
|
|
||||||
chat_contextResult_shadowUnderSwitchDrawable = resources.getDrawable(R.drawable.header_shadow).mutate();
|
chat_contextResult_shadowUnderSwitchDrawable = resources.getDrawable(R.drawable.header_shadow).mutate();
|
||||||
|
|
||||||
chat_attachButtonDrawables[0] = new AttachCameraDrawable();
|
chat_attachButtonDrawables[0] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_gallery);
|
||||||
chat_attachButtonDrawables[1] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_gallery);
|
chat_attachButtonDrawables[1] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_audio);
|
||||||
chat_attachButtonDrawables[2] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_video);
|
chat_attachButtonDrawables[2] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_file);
|
||||||
chat_attachButtonDrawables[3] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_audio);
|
chat_attachButtonDrawables[3] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_contact);
|
||||||
chat_attachButtonDrawables[4] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_file);
|
chat_attachButtonDrawables[4] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_location);
|
||||||
chat_attachButtonDrawables[5] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_contact);
|
chat_attachButtonDrawables[5] = createCircleDrawableWithIcon(AndroidUtilities.dp(50), R.drawable.attach_polls);
|
||||||
chat_attachButtonDrawables[6] = createCircleDrawableWithIcon(AndroidUtilities.dp(54), R.drawable.attach_location);
|
chat_attachEmptyDrawable = resources.getDrawable(R.drawable.nophotos3);
|
||||||
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_cornerOuter[0] = resources.getDrawable(R.drawable.corner_out_tl);
|
chat_cornerOuter[0] = resources.getDrawable(R.drawable.corner_out_tl);
|
||||||
chat_cornerOuter[1] = resources.getDrawable(R.drawable.corner_out_tr);
|
chat_cornerOuter[1] = resources.getDrawable(R.drawable.corner_out_tr);
|
||||||
|
@ -3667,43 +3579,20 @@ public class Theme {
|
||||||
|
|
||||||
setDrawableColorByKey(chat_composeShadowDrawable, key_chat_messagePanelShadow);
|
setDrawableColorByKey(chat_composeShadowDrawable, key_chat_messagePanelShadow);
|
||||||
|
|
||||||
/*for (int a = 1; a < 3; a++) {
|
setCombinedDrawableColor(chat_attachButtonDrawables[0], getColor(key_chat_attachGalleryBackground), false);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 1], getColor(a == 1 ? key_chat_attachGalleryBackground : key_chat_attachGalleryBackgroundPressed), false);
|
setCombinedDrawableColor(chat_attachButtonDrawables[0], getColor(key_chat_attachGalleryIcon), true);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 1], getColor(key_chat_attachGalleryIcon), true);
|
setCombinedDrawableColor(chat_attachButtonDrawables[1], getColor(key_chat_attachAudioBackground), false);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 2], getColor(a == 1 ? key_chat_attachVideoBackground : key_chat_attachVideoBackgroundPressed), false);
|
setCombinedDrawableColor(chat_attachButtonDrawables[1], getColor(key_chat_attachAudioIcon), true);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 2], getColor(key_chat_attachVideoIcon), true);
|
setCombinedDrawableColor(chat_attachButtonDrawables[2], getColor(key_chat_attachFileBackground), false);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 3], getColor(a == 1 ? key_chat_attachAudioBackground : key_chat_attachAudioBackgroundPressed), false);
|
setCombinedDrawableColor(chat_attachButtonDrawables[2], getColor(key_chat_attachFileIcon), true);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 3], getColor(key_chat_attachAudioIcon), true);
|
setCombinedDrawableColor(chat_attachButtonDrawables[3], getColor(key_chat_attachContactBackground), false);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 4], getColor(a == 1 ? key_chat_attachFileBackground : key_chat_attachFileBackgroundPressed), false);
|
setCombinedDrawableColor(chat_attachButtonDrawables[3], getColor(key_chat_attachContactIcon), true);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 4], getColor(key_chat_attachFileIcon), true);
|
setCombinedDrawableColor(chat_attachButtonDrawables[4], getColor(key_chat_attachLocationBackground), false);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 5], getColor(a == 1 ? key_chat_attachContactBackground : key_chat_attachContactBackgroundPressed), false);
|
setCombinedDrawableColor(chat_attachButtonDrawables[4], getColor(key_chat_attachLocationIcon), true);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 5], getColor(key_chat_attachContactIcon), true);
|
setCombinedDrawableColor(chat_attachButtonDrawables[5], getColor(key_chat_attachPollBackground), false);
|
||||||
setCombinedDrawableColor(chat_attachButtonDrawables[9 * a + 6], getColor(a == 1 ? key_chat_attachLocationBackground : key_chat_attachLocationBackgroundPressed), false);
|
setCombinedDrawableColor(chat_attachButtonDrawables[5], getColor(key_chat_attachPollIcon), true);
|
||||||
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[1], getColor(key_chat_attachGalleryBackground), false);
|
setDrawableColor(chat_attachEmptyDrawable, getColor(key_chat_attachEmptyImage));
|
||||||
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);
|
|
||||||
|
|
||||||
applyChatServiceMessageColor();
|
applyChatServiceMessageColor();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
package org.telegram.ui.ActionBar;
|
package org.telegram.ui.ActionBar;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
@ -96,6 +97,7 @@ public class ThemeDescription {
|
||||||
public static int FLAG_AB_SUBMENUBACKGROUND = 0x80000000;
|
public static int FLAG_AB_SUBMENUBACKGROUND = 0x80000000;
|
||||||
|
|
||||||
private View viewToInvalidate;
|
private View viewToInvalidate;
|
||||||
|
private int alphaOverride = -1;
|
||||||
private Paint[] paintToUpdate;
|
private Paint[] paintToUpdate;
|
||||||
private Drawable[] drawablesToUpdate;
|
private Drawable[] drawablesToUpdate;
|
||||||
private Class[] listClasses;
|
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) {
|
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;
|
currentKey = key;
|
||||||
paintToUpdate = paint;
|
paintToUpdate = paint;
|
||||||
drawablesToUpdate = drawables;
|
drawablesToUpdate = drawables;
|
||||||
|
@ -164,6 +170,7 @@ public class ThemeDescription {
|
||||||
changeFlags = flags;
|
changeFlags = flags;
|
||||||
listClasses = classes;
|
listClasses = classes;
|
||||||
listClassesFieldName = classesFields;
|
listClassesFieldName = classesFields;
|
||||||
|
alphaOverride = alpha;
|
||||||
delegate = themeDescriptionDelegate;
|
delegate = themeDescriptionDelegate;
|
||||||
cachedFields = new HashMap<>();
|
cachedFields = new HashMap<>();
|
||||||
notFoundCachedFields = new HashMap<>();
|
notFoundCachedFields = new HashMap<>();
|
||||||
|
@ -211,6 +218,10 @@ public class ThemeDescription {
|
||||||
if (save) {
|
if (save) {
|
||||||
Theme.setColor(currentKey, color, useDefault);
|
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) {
|
if (paintToUpdate != null) {
|
||||||
for (int a = 0; a < paintToUpdate.length; a++) {
|
for (int a = 0; a < paintToUpdate.length; a++) {
|
||||||
if ((changeFlags & FLAG_LINKCOLOR) != 0 && paintToUpdate[a] instanceof TextPaint) {
|
if ((changeFlags & FLAG_LINKCOLOR) != 0 && paintToUpdate[a] instanceof TextPaint) {
|
||||||
|
@ -465,7 +476,6 @@ public class ThemeDescription {
|
||||||
}
|
}
|
||||||
processViewColor(viewToInvalidate, color);
|
processViewColor(viewToInvalidate, color);
|
||||||
}
|
}
|
||||||
currentColor = color;
|
|
||||||
if (delegate != null) {
|
if (delegate != null) {
|
||||||
delegate.didSetColor();
|
delegate.didSetColor();
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,6 +236,16 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement
|
||||||
lastSticker = emoji.toString();
|
lastSticker = emoji.toString();
|
||||||
stickersToLoad.clear();
|
stickersToLoad.clear();
|
||||||
boolean isValidEmoji = searchEmoji && (Emoji.isValidEmoji(originalEmoji) || Emoji.isValidEmoji(lastSticker));
|
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 (emojiOnly || SharedConfig.suggestStickers == 2 || !isValidEmoji) {
|
||||||
if (visible && (keywordResults == null || keywordResults.isEmpty())) {
|
if (visible && (keywordResults == null || keywordResults.isEmpty())) {
|
||||||
visible = false;
|
visible = false;
|
||||||
|
|
|
@ -40,6 +40,7 @@ import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.annotation.Keep;
|
import androidx.annotation.Keep;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
@ -49,12 +50,14 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.viewpager.widget.PagerAdapter;
|
import androidx.viewpager.widget.PagerAdapter;
|
||||||
import androidx.viewpager.widget.ViewPager;
|
import androidx.viewpager.widget.ViewPager;
|
||||||
import android.text.Layout;
|
import android.text.Layout;
|
||||||
|
import android.text.Selection;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.StaticLayout;
|
import android.text.StaticLayout;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.text.style.MetricAffectingSpan;
|
import android.text.style.MetricAffectingSpan;
|
||||||
import android.text.style.URLSpan;
|
import android.text.style.URLSpan;
|
||||||
import android.util.LongSparseArray;
|
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.TextPaintUrlSpan;
|
||||||
import org.telegram.ui.Components.TextPaintWebpageUrlSpan;
|
import org.telegram.ui.Components.TextPaintWebpageUrlSpan;
|
||||||
import org.telegram.ui.Components.TypefaceSpan;
|
import org.telegram.ui.Components.TypefaceSpan;
|
||||||
|
import org.telegram.ui.Components.URLSpanNoUnderline;
|
||||||
import org.telegram.ui.Components.VideoPlayer;
|
import org.telegram.ui.Components.VideoPlayer;
|
||||||
import org.telegram.ui.Components.WebPlayerView;
|
import org.telegram.ui.Components.WebPlayerView;
|
||||||
|
|
||||||
|
@ -3707,7 +3711,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
captionTextViewNext = new TextView(activity);
|
captionTextViewNext = new TextView(activity);
|
||||||
captionTextViewNext.setMaxLines(10);
|
captionTextViewNext.setMaxLines(10);
|
||||||
captionTextViewNext.setBackgroundColor(0x7f000000);
|
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.setPadding(AndroidUtilities.dp(20), AndroidUtilities.dp(8), AndroidUtilities.dp(20), AndroidUtilities.dp(8));
|
||||||
captionTextViewNext.setLinkTextColor(0xffffffff);
|
captionTextViewNext.setLinkTextColor(0xffffffff);
|
||||||
captionTextViewNext.setTextColor(0xffffffff);
|
captionTextViewNext.setTextColor(0xffffffff);
|
||||||
|
@ -3720,7 +3724,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
captionTextView = new TextView(activity);
|
captionTextView = new TextView(activity);
|
||||||
captionTextView.setMaxLines(10);
|
captionTextView.setMaxLines(10);
|
||||||
captionTextView.setBackgroundColor(0x7f000000);
|
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.setPadding(AndroidUtilities.dp(20), AndroidUtilities.dp(8), AndroidUtilities.dp(20), AndroidUtilities.dp(8));
|
||||||
captionTextView.setLinkTextColor(0xffffffff);
|
captionTextView.setLinkTextColor(0xffffffff);
|
||||||
captionTextView.setTextColor(0xffffffff);
|
captionTextView.setTextColor(0xffffffff);
|
||||||
|
@ -10409,6 +10413,22 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
|
||||||
|
|
||||||
//------------ photo viewer
|
//------------ 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 int[] coords = new int[2];
|
||||||
|
|
||||||
private boolean isPhotoVisible;
|
private boolean isPhotoVisible;
|
||||||
|
|
|
@ -8,10 +8,7 @@
|
||||||
|
|
||||||
package org.telegram.ui;
|
package org.telegram.ui;
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -22,8 +19,6 @@ import org.telegram.SQLite.SQLiteCursor;
|
||||||
import org.telegram.SQLite.SQLiteDatabase;
|
import org.telegram.SQLite.SQLiteDatabase;
|
||||||
import org.telegram.SQLite.SQLitePreparedStatement;
|
import org.telegram.SQLite.SQLitePreparedStatement;
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.ApplicationLoader;
|
|
||||||
import org.telegram.messenger.ClearCacheService;
|
|
||||||
import org.telegram.messenger.MediaDataController;
|
import org.telegram.messenger.MediaDataController;
|
||||||
import org.telegram.messenger.FileLoader;
|
import org.telegram.messenger.FileLoader;
|
||||||
import org.telegram.messenger.FileLog;
|
import org.telegram.messenger.FileLog;
|
||||||
|
@ -32,6 +27,7 @@ import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.MessagesController;
|
import org.telegram.messenger.MessagesController;
|
||||||
import org.telegram.messenger.MessagesStorage;
|
import org.telegram.messenger.MessagesStorage;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
|
import org.telegram.messenger.SharedConfig;
|
||||||
import org.telegram.messenger.UserConfig;
|
import org.telegram.messenger.UserConfig;
|
||||||
import org.telegram.messenger.Utilities;
|
import org.telegram.messenger.Utilities;
|
||||||
import org.telegram.tgnet.NativeByteBuffer;
|
import org.telegram.tgnet.NativeByteBuffer;
|
||||||
|
@ -252,26 +248,19 @@ public class CacheControlActivity extends BaseFragment {
|
||||||
if (position == keepMediaRow) {
|
if (position == keepMediaRow) {
|
||||||
BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity());
|
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) -> {
|
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) {
|
if (which == 0) {
|
||||||
editor.putInt("keep_media", 3);
|
SharedConfig.setKeepMedia(3);
|
||||||
} else if (which == 1) {
|
} else if (which == 1) {
|
||||||
editor.putInt("keep_media", 0);
|
SharedConfig.setKeepMedia(0);
|
||||||
} else if (which == 2) {
|
} else if (which == 2) {
|
||||||
editor.putInt("keep_media", 1);
|
SharedConfig.setKeepMedia(1);
|
||||||
} else if (which == 3) {
|
} else if (which == 3) {
|
||||||
editor.putInt("keep_media", 2);
|
SharedConfig.setKeepMedia(2);
|
||||||
}
|
}
|
||||||
editor.commit();
|
|
||||||
if (listAdapter != null) {
|
if (listAdapter != null) {
|
||||||
listAdapter.notifyDataSetChanged();
|
listAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
PendingIntent pintent = PendingIntent.getService(ApplicationLoader.applicationContext, 1, new Intent(ApplicationLoader.applicationContext, ClearCacheService.class), 0);
|
SharedConfig.checkKeepMedia();
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
showDialog(builder.create());
|
showDialog(builder.create());
|
||||||
} else if (position == databaseRow) {
|
} else if (position == databaseRow) {
|
||||||
|
@ -280,6 +269,9 @@ public class CacheControlActivity extends BaseFragment {
|
||||||
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
|
||||||
builder.setMessage(LocaleController.getString("LocalDatabaseClear", R.string.LocalDatabaseClear));
|
builder.setMessage(LocaleController.getString("LocalDatabaseClear", R.string.LocalDatabaseClear));
|
||||||
builder.setPositiveButton(LocaleController.getString("CacheClear", R.string.CacheClear), (dialogInterface, i) -> {
|
builder.setPositiveButton(LocaleController.getString("CacheClear", R.string.CacheClear), (dialogInterface, i) -> {
|
||||||
|
if (getParentActivity() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
final AlertDialog progressDialog = new AlertDialog(getParentActivity(), 3);
|
final AlertDialog progressDialog = new AlertDialog(getParentActivity(), 3);
|
||||||
progressDialog.setCanCacnel(false);
|
progressDialog.setCanCacnel(false);
|
||||||
progressDialog.show();
|
progressDialog.show();
|
||||||
|
@ -507,7 +499,7 @@ public class CacheControlActivity extends BaseFragment {
|
||||||
}
|
}
|
||||||
} else if (position == keepMediaRow) {
|
} else if (position == keepMediaRow) {
|
||||||
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
SharedPreferences preferences = MessagesController.getGlobalMainSettings();
|
||||||
int keepMedia = preferences.getInt("keep_media", 2);
|
int keepMedia = SharedConfig.keepMedia;
|
||||||
String value;
|
String value;
|
||||||
if (keepMedia == 0) {
|
if (keepMedia == 0) {
|
||||||
value = LocaleController.formatPluralString("Weeks", 1);
|
value = LocaleController.formatPluralString("Weeks", 1);
|
||||||
|
|
|
@ -13,12 +13,9 @@ import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
@ -29,7 +26,6 @@ import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.telephony.PhoneNumberUtils;
|
import android.telephony.PhoneNumberUtils;
|
||||||
import android.telephony.SmsManager;
|
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
|
@ -50,12 +46,10 @@ import android.widget.TextView;
|
||||||
import org.telegram.PhoneFormat.PhoneFormat;
|
import org.telegram.PhoneFormat.PhoneFormat;
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.ApplicationLoader;
|
import org.telegram.messenger.ApplicationLoader;
|
||||||
import org.telegram.messenger.BuildVars;
|
|
||||||
import org.telegram.messenger.FileLog;
|
import org.telegram.messenger.FileLog;
|
||||||
import org.telegram.messenger.LocaleController;
|
import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.NotificationCenter;
|
import org.telegram.messenger.NotificationCenter;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.SmsReceiver;
|
|
||||||
import org.telegram.tgnet.ConnectionsManager;
|
import org.telegram.tgnet.ConnectionsManager;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.ActionBar;
|
import org.telegram.ui.ActionBar.ActionBar;
|
||||||
|
@ -388,24 +382,7 @@ public class CancelAccountDeletionActivity extends BaseFragment {
|
||||||
req.hash = hash;
|
req.hash = hash;
|
||||||
req.settings = new TLRPC.TL_codeSettings();
|
req.settings = new TLRPC.TL_codeSettings();
|
||||||
req.settings.allow_flashcall = false;//simcardAvailable && allowCall;
|
req.settings.allow_flashcall = false;//simcardAvailable && allowCall;
|
||||||
if (Build.VERSION.SDK_INT >= 26) {
|
req.settings.allow_app_hash = ApplicationLoader.hasPlayServices;
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.settings.allow_flashcall) {
|
if (req.settings.allow_flashcall) {
|
||||||
try {
|
try {
|
||||||
@SuppressLint("HardwareIds") String number = tm.getLine1Number();
|
@SuppressLint("HardwareIds") String number = tm.getLine1Number();
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.telegram.messenger.FileLoader;
|
||||||
import org.telegram.messenger.ImageLocation;
|
import org.telegram.messenger.ImageLocation;
|
||||||
import org.telegram.messenger.LocaleController;
|
import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.MessageObject;
|
import org.telegram.messenger.MessageObject;
|
||||||
import org.telegram.messenger.SharedConfig;
|
import org.telegram.tgnet.TLObject;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.BackupImageView;
|
import org.telegram.ui.Components.BackupImageView;
|
||||||
|
@ -100,20 +100,38 @@ public class ArchivedStickerSetCell extends FrameLayout {
|
||||||
textView.setText(stickersSet.set.title);
|
textView.setText(stickersSet.set.title);
|
||||||
|
|
||||||
valueTextView.setText(LocaleController.formatPluralString("Stickers", set.set.count));
|
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) {
|
TLRPC.Document sticker;
|
||||||
if (MessageObject.canAutoplayAnimatedSticker(set.cover)) {
|
if (set.cover != null) {
|
||||||
imageView.setImage(ImageLocation.getForDocument(set.cover), "80_80", ImageLocation.getForDocument(thumb, set.cover), null, 0, set);
|
sticker = set.cover;
|
||||||
} else {
|
|
||||||
imageView.setImage(ImageLocation.getForDocument(thumb, set.cover), null, "webp", null, set);
|
|
||||||
}
|
|
||||||
} else if (!set.covers.isEmpty()) {
|
} else if (!set.covers.isEmpty()) {
|
||||||
TLRPC.Document document = set.covers.get(0);
|
sticker = set.covers.get(0);
|
||||||
thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
|
} else {
|
||||||
if (MessageObject.canAutoplayAnimatedSticker(document)) {
|
sticker = null;
|
||||||
imageView.setImage(ImageLocation.getForDocument(document), "80_80", ImageLocation.getForDocument(thumb, document), null, 0, set);
|
}
|
||||||
|
if (sticker != null) {
|
||||||
|
TLObject object;
|
||||||
|
if (set.set.thumb instanceof TLRPC.TL_photoSize) {
|
||||||
|
object = set.set.thumb;
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
imageView.setImage(null, null, "webp", null, set);
|
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 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) {
|
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 void didPressInstantButton(ChatMessageCell cell, int type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean isChatAdminCell(int uid) {
|
default String getAdminRank(int uid) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean needPlayMessage(MessageObject messageObject) {
|
default boolean needPlayMessage(MessageObject messageObject) {
|
||||||
|
@ -174,6 +174,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
|
|
||||||
default void didStartVideoStream(MessageObject message) {
|
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;
|
private final static int DOCUMENT_ATTACH_TYPE_NONE = 0;
|
||||||
|
@ -751,7 +758,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (link[0] == pressedLink) {
|
if (link[0] == pressedLink) {
|
||||||
delegate.didPressUrl(currentMessageObject, pressedLink, false);
|
delegate.didPressUrl(this, pressedLink, false);
|
||||||
resetPressedLink(1);
|
resetPressedLink(1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -817,7 +824,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
} else if (pressedLinkType == 3) {
|
} else if (pressedLinkType == 3) {
|
||||||
delegate.didPressUrl(currentMessageObject, pressedLink, false);
|
delegate.didPressUrl(this, pressedLink, false);
|
||||||
resetPressedLink(3);
|
resetPressedLink(3);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1256,7 +1263,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
imagePressed = true;
|
imagePressed = true;
|
||||||
result = 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()) {
|
if (x >= photoImage.getImageX() && x <= photoImage.getImageX() + photoImage.getImageWidth() && y >= photoImage.getImageY() && y <= photoImage.getImageY() + photoImage.getImageHeight()) {
|
||||||
imagePressed = true;
|
imagePressed = true;
|
||||||
result = true;
|
result = true;
|
||||||
|
@ -1652,7 +1659,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
}
|
}
|
||||||
|
|
||||||
if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
int duration = 0;
|
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);
|
photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1);
|
||||||
}
|
}
|
||||||
} else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) {
|
} 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);
|
photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, documentAttach), "b1", documentAttach.size, "webp", messageObject, 1);
|
||||||
} else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) {
|
} else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) {
|
||||||
photoImage.setNeedsQualityThumb(true);
|
photoImage.setNeedsQualityThumb(true);
|
||||||
|
@ -3618,14 +3632,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
} else if (messageObject.isAnyKindOfSticker()) { //sticker
|
} else if (messageObject.isAnyKindOfSticker()) { //sticker
|
||||||
drawBackground = false;
|
drawBackground = false;
|
||||||
boolean isWebpSticker = messageObject.type == MessageObject.TYPE_STICKER;
|
boolean isWebpSticker = messageObject.type == MessageObject.TYPE_STICKER;
|
||||||
for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) {
|
for (int a = 0; a < messageObject.getDocument().attributes.size(); a++) {
|
||||||
TLRPC.DocumentAttribute attribute = messageObject.messageOwner.media.document.attributes.get(a);
|
TLRPC.DocumentAttribute attribute = messageObject.getDocument().attributes.get(a);
|
||||||
if (attribute instanceof TLRPC.TL_documentAttributeImageSize) {
|
if (attribute instanceof TLRPC.TL_documentAttributeImageSize) {
|
||||||
photoWidth = attribute.w;
|
photoWidth = attribute.w;
|
||||||
photoHeight = attribute.h;
|
photoHeight = attribute.h;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (photoWidth == 0 && photoHeight == 0 && messageObject.isAnimatedSticker()) {
|
if (messageObject.isAnimatedSticker() && photoWidth == 0 && photoHeight == 0) {
|
||||||
photoWidth = photoHeight = 512;
|
photoWidth = photoHeight = 512;
|
||||||
}
|
}
|
||||||
float maxHeight;
|
float maxHeight;
|
||||||
|
@ -3635,15 +3650,34 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
} else {
|
} else {
|
||||||
maxHeight = maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f;
|
maxHeight = maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f;
|
||||||
}
|
}
|
||||||
if (photoWidth == 0) {
|
String filter;
|
||||||
photoHeight = (int) maxHeight;
|
if (messageObject.isAnimatedEmoji()) {
|
||||||
photoWidth = photoHeight + AndroidUtilities.dp(100);
|
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;
|
Object parentObject = messageObject;
|
||||||
photoWidth = (int) maxWidth;
|
if (messageObject.isAnimatedEmoji()) {
|
||||||
if (photoHeight > maxHeight) {
|
filter = String.format(Locale.US, "%d_%d_nr_%s" + messageObject.emojiAnimatedStickerColor, photoWidth, photoHeight, messageObject.toString());
|
||||||
photoWidth *= maxHeight / photoHeight;
|
photoImage.setAutoRepeat(delegate.shouldRepeatSticker(messageObject) ? 2 : 3);
|
||||||
photoHeight = (int) maxHeight;
|
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;
|
documentAttachType = DOCUMENT_ATTACH_TYPE_STICKER;
|
||||||
availableTimeWidth = photoWidth - AndroidUtilities.dp(14);
|
availableTimeWidth = photoWidth - AndroidUtilities.dp(14);
|
||||||
|
@ -3652,13 +3686,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40);
|
currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 40);
|
||||||
photoParentObject = messageObject.photoThumbsObject;
|
photoParentObject = messageObject.photoThumbsObject;
|
||||||
if (messageObject.attachPathExists) {
|
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",
|
ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), "b1",
|
||||||
messageObject.messageOwner.media.document.size, isWebpSticker ? "webp" : null, messageObject, 1);
|
messageObject.getDocument().size, isWebpSticker ? "webp" : null, parentObject, 1);
|
||||||
} else if (messageObject.messageOwner.media.document.id != 0) {
|
} else if (messageObject.getDocument().id != 0) {
|
||||||
photoImage.setImage(ImageLocation.getForDocument(messageObject.messageOwner.media.document), String.format(Locale.US, "%d_%d", photoWidth, photoHeight),
|
photoImage.setImage(ImageLocation.getForDocument(messageObject.getDocument()), filter,
|
||||||
ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), "b1",
|
ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), "b1",
|
||||||
messageObject.messageOwner.media.document.size, isWebpSticker ? "webp" : null, messageObject, 1);
|
messageObject.getDocument().size, isWebpSticker ? "webp" : null, parentObject, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize());
|
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) {
|
if ((w == 0 || h == 0) && messageObject.type == 8) {
|
||||||
for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) {
|
for (int a = 0; a < messageObject.getDocument().attributes.size(); a++) {
|
||||||
TLRPC.DocumentAttribute attribute = messageObject.messageOwner.media.document.attributes.get(a);
|
TLRPC.DocumentAttribute attribute = messageObject.getDocument().attributes.get(a);
|
||||||
if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) {
|
if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) {
|
||||||
float scale = (float) attribute.w / (float) photoWidth;
|
float scale = (float) attribute.w / (float) photoWidth;
|
||||||
w = (int) (attribute.w / scale);
|
w = (int) (attribute.w / scale);
|
||||||
|
@ -4068,8 +4102,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
if (autoPlayingMedia) {
|
if (autoPlayingMedia) {
|
||||||
photoImage.setAllowStartAnimation(true);
|
photoImage.setAllowStartAnimation(true);
|
||||||
photoImage.startAnimation();
|
photoImage.startAnimation();
|
||||||
TLRPC.Document document = messageObject.messageOwner.media.document;
|
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.messageOwner.media.document.size, null, messageObject, 0);
|
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) {
|
} else if (messageObject.type == 1) {
|
||||||
if (messageObject.useCustomPhoto) {
|
if (messageObject.useCustomPhoto) {
|
||||||
photoImage.setImageBitmap(getResources().getDrawable(R.drawable.theme_preview_image));
|
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) {
|
} 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;
|
int localFile = 0;
|
||||||
if (messageObject.attachPathExists) {
|
if (messageObject.attachPathExists) {
|
||||||
DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
|
DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this);
|
||||||
|
@ -4106,17 +4140,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
localFile = 2;
|
localFile = 2;
|
||||||
}
|
}
|
||||||
boolean autoDownload = false;
|
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);
|
autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject);
|
||||||
}
|
}
|
||||||
if (!messageObject.isSending() && !messageObject.isEditing() && (localFile != 0 || FileLoader.getInstance(currentAccount).isLoadingFile(fileName) || autoDownload)) {
|
if (!messageObject.isSending() && !messageObject.isEditing() && (localFile != 0 || FileLoader.getInstance(currentAccount).isLoadingFile(fileName) || autoDownload)) {
|
||||||
if (localFile != 1 && !messageObject.needDrawBluredPreview() && (localFile != 0 || messageObject.canStreamVideo() && autoDownload)) {
|
if (localFile != 1 && !messageObject.needDrawBluredPreview() && (localFile != 0 || messageObject.canStreamVideo() && autoDownload)) {
|
||||||
autoPlayingMedia = true;
|
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) {
|
} else if (localFile == 1) {
|
||||||
photoImage.setImage(ImageLocation.getForPath(messageObject.isSendError() ? null : messageObject.messageOwner.attachPath), null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0);
|
photoImage.setImage(ImageLocation.getForPath(messageObject.isSendError() ? null : messageObject.messageOwner.attachPath), null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0);
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, 0, null, messageObject, 0);
|
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
|
@Override
|
||||||
protected void onLongPress() {
|
protected void onLongPress() {
|
||||||
if (pressedLink instanceof URLSpanMono) {
|
if (pressedLink instanceof URLSpanMono) {
|
||||||
delegate.didPressUrl(currentMessageObject, pressedLink, true);
|
delegate.didPressUrl(this, pressedLink, true);
|
||||||
return;
|
return;
|
||||||
} else if (pressedLink instanceof URLSpanNoUnderline) {
|
} else if (pressedLink instanceof URLSpanNoUnderline) {
|
||||||
URLSpanNoUnderline url = (URLSpanNoUnderline) pressedLink;
|
URLSpanNoUnderline url = (URLSpanNoUnderline) pressedLink;
|
||||||
if (url.getURL().startsWith("/")) {
|
if (url.getURL().startsWith("/")) {
|
||||||
delegate.didPressUrl(currentMessageObject, pressedLink, true);
|
delegate.didPressUrl(this, pressedLink, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (pressedLink instanceof URLSpan) {
|
} else if (pressedLink instanceof URLSpan) {
|
||||||
delegate.didPressUrl(currentMessageObject, pressedLink, true);
|
delegate.didPressUrl(this, pressedLink, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resetPressedLink(-1);
|
resetPressedLink(-1);
|
||||||
|
@ -4591,7 +4625,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
if (messageObject.type == 0) {
|
if (messageObject.type == 0) {
|
||||||
documentAttach = messageObject.messageOwner.media.webpage.document;
|
documentAttach = messageObject.messageOwner.media.webpage.document;
|
||||||
} else {
|
} else {
|
||||||
documentAttach = messageObject.messageOwner.media.document;
|
documentAttach = messageObject.getDocument();
|
||||||
}
|
}
|
||||||
if (documentAttach == null) {
|
if (documentAttach == null) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4701,7 +4735,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
if (infoWidth < 0) {
|
if (infoWidth < 0) {
|
||||||
infoWidth = AndroidUtilities.dp(10);
|
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) {
|
} catch (Exception e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
|
@ -5510,7 +5544,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
imageDrawn = photoImage.draw(canvas);
|
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);
|
videoButtonX = photoImage.getImageX() + AndroidUtilities.dp(8);
|
||||||
videoButtonY = photoImage.getImageY() + AndroidUtilities.dp(8);
|
videoButtonY = photoImage.getImageY() + AndroidUtilities.dp(8);
|
||||||
videoRadialProgress.setProgressRect(videoButtonX, videoButtonY, videoButtonX + AndroidUtilities.dp(24), videoButtonY + AndroidUtilities.dp(24));
|
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;
|
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));
|
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);
|
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();
|
long newTime = System.currentTimeMillis();
|
||||||
if (Math.abs(button.lastUpdateTime - System.currentTimeMillis()) < 1000) {
|
if (Math.abs(button.lastUpdateTime - System.currentTimeMillis()) < 1000) {
|
||||||
long delta = (newTime - button.lastUpdateTime);
|
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);
|
photoImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForObject(thumb, document), thumbFilter, document.size, null, currentMessageObject, 0);
|
||||||
}
|
}
|
||||||
} else if (currentMessageObject.type == 9) {
|
} 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) {
|
} else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) {
|
||||||
FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 1, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0);
|
FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 1, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0);
|
||||||
} else if (currentMessageObject.type == 0 && documentAttachType != DOCUMENT_ATTACH_TYPE_NONE) {
|
} 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);
|
ImageLoader.getInstance().cancelForceLoadingForImageReceiver(photoImage);
|
||||||
photoImage.cancelLoadImage();
|
photoImage.cancelLoadImage();
|
||||||
} else if (currentMessageObject.type == 9) {
|
} else if (currentMessageObject.type == 9) {
|
||||||
FileLoader.getInstance(currentAccount).cancelLoadFile(currentMessageObject.messageOwner.media.document);
|
FileLoader.getInstance(currentAccount).cancelLoadFile(currentMessageObject.getDocument());
|
||||||
}
|
}
|
||||||
buttonState = 0;
|
buttonState = 0;
|
||||||
if (video) {
|
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
|
@Override
|
||||||
public void onProgressDownload(String fileName, float progress) {
|
public void onProgressDownload(String fileName, float progress) {
|
||||||
if (drawVideoImageButton) {
|
if (drawVideoImageButton) {
|
||||||
|
@ -7004,12 +7045,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
}
|
}
|
||||||
int adminWidth;
|
int adminWidth;
|
||||||
String adminString;
|
String adminString;
|
||||||
|
String adminLabel;
|
||||||
if (isMegagroup && currentChat != null && currentMessageObject.isForwardedChannelPost()) {
|
if (isMegagroup && currentChat != null && currentMessageObject.isForwardedChannelPost()) {
|
||||||
adminString = LocaleController.getString("DiscussChannel", R.string.DiscussChannel);
|
adminString = LocaleController.getString("DiscussChannel", R.string.DiscussChannel);
|
||||||
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
|
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
|
||||||
nameWidth -= adminWidth;
|
nameWidth -= adminWidth;
|
||||||
} else if (currentUser != null && !currentMessageObject.isOutOwner() && !currentMessageObject.isAnyKindOfSticker() && currentMessageObject.type != 5 && delegate.isChatAdminCell(currentUser.id)) {
|
} else if (currentUser != null && !currentMessageObject.isOutOwner() && !currentMessageObject.isAnyKindOfSticker() && currentMessageObject.type != 5 && (adminLabel = delegate.getAdminRank(currentUser.id)) != null) {
|
||||||
adminString = LocaleController.getString("ChatAdmin", R.string.ChatAdmin);
|
if (adminLabel.length() == 0) {
|
||||||
|
adminLabel = LocaleController.getString("ChatAdmin", R.string.ChatAdmin);
|
||||||
|
}
|
||||||
|
adminString = adminLabel;
|
||||||
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
|
adminWidth = (int) Math.ceil(Theme.chat_adminPaint.measureText(adminString));
|
||||||
nameWidth -= adminWidth;
|
nameWidth -= adminWidth;
|
||||||
} else {
|
} else {
|
||||||
|
@ -7838,13 +7883,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
|
|
||||||
public void setCheckBoxVisible(boolean visible, boolean animated) {
|
public void setCheckBoxVisible(boolean visible, boolean animated) {
|
||||||
if (visible && checkBox == null) {
|
if (visible && checkBox == null) {
|
||||||
checkBox = new CheckBoxBase(this);
|
checkBox = new CheckBoxBase(this, 21);
|
||||||
if (attachedToWindow) {
|
if (attachedToWindow) {
|
||||||
checkBox.onAttachedToWindow();
|
checkBox.onAttachedToWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (visible && photoCheckBox == null && currentMessagesGroup != null && currentMessagesGroup.messages.size() > 1) {
|
if (visible && photoCheckBox == null && currentMessagesGroup != null && currentMessagesGroup.messages.size() > 1) {
|
||||||
photoCheckBox = new CheckBoxBase(this);
|
photoCheckBox = new CheckBoxBase(this, 21);
|
||||||
photoCheckBox.setUseDefaultCheck(true);
|
photoCheckBox.setUseDefaultCheck(true);
|
||||||
if (attachedToWindow) {
|
if (attachedToWindow) {
|
||||||
photoCheckBox.onAttachedToWindow();
|
photoCheckBox.onAttachedToWindow();
|
||||||
|
@ -9002,7 +9047,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
|
||||||
if (virtualViewId >= LINK_IDS_START) {
|
if (virtualViewId >= LINK_IDS_START) {
|
||||||
ClickableSpan link = getLinkById(virtualViewId);
|
ClickableSpan link = getLinkById(virtualViewId);
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
delegate.didPressUrl(currentMessageObject, link, false);
|
delegate.didPressUrl(ChatMessageCell.this, link, false);
|
||||||
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED);
|
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||||
}
|
}
|
||||||
} else if (virtualViewId >= BOT_BUTTONS_START) {
|
} 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) {
|
} else if (action == AccessibilityNodeInfo.ACTION_LONG_CLICK) {
|
||||||
ClickableSpan link = getLinkById(virtualViewId);
|
ClickableSpan link = getLinkById(virtualViewId);
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
delegate.didPressUrl(currentMessageObject, link, true);
|
delegate.didPressUrl(ChatMessageCell.this, link, true);
|
||||||
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
|
sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -637,6 +637,11 @@ public class ContextLinkCell extends View implements DownloadController.FileDown
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mediaWebpage) {
|
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) {
|
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.setProgressColor(Theme.getColor(buttonPressed ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress));
|
||||||
radialProgress.draw(canvas);
|
radialProgress.draw(canvas);
|
||||||
|
|
|
@ -216,9 +216,8 @@ public class DialogCell extends BaseCell {
|
||||||
useForceThreeLines = forceThreeLines;
|
useForceThreeLines = forceThreeLines;
|
||||||
|
|
||||||
if (needCheck) {
|
if (needCheck) {
|
||||||
checkBox = new CheckBox2(context);
|
checkBox = new CheckBox2(context, 21);
|
||||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||||
checkBox.setSize(21);
|
|
||||||
checkBox.setDrawUnchecked(false);
|
checkBox.setDrawUnchecked(false);
|
||||||
checkBox.setDrawBackgroundAsArc(3);
|
checkBox.setDrawBackgroundAsArc(3);
|
||||||
addView(checkBox);
|
addView(checkBox);
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.MessageObject;
|
import org.telegram.messenger.MessageObject;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.messenger.UserConfig;
|
import org.telegram.messenger.UserConfig;
|
||||||
|
import org.telegram.tgnet.TLObject;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.BackupImageView;
|
import org.telegram.ui.Components.BackupImageView;
|
||||||
|
@ -228,21 +229,38 @@ public class FeaturedStickerSetCell extends FrameLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
valueTextView.setText(LocaleController.formatPluralString("Stickers", set.set.count));
|
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) {
|
TLRPC.Document sticker;
|
||||||
if (MessageObject.canAutoplayAnimatedSticker(set.cover)) {
|
if (set.cover != null) {
|
||||||
imageView.setImage(ImageLocation.getForDocument(set.cover), "80_80", ImageLocation.getForDocument(thumb, set.cover), null, 0, set);
|
sticker = set.cover;
|
||||||
} else {
|
|
||||||
imageView.setImage(ImageLocation.getForDocument(thumb, set.cover), null, "webp", null, set);
|
|
||||||
}
|
|
||||||
} else if (!set.covers.isEmpty()) {
|
} else if (!set.covers.isEmpty()) {
|
||||||
TLRPC.Document document = set.covers.get(0);
|
sticker = set.covers.get(0);
|
||||||
thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
|
} else {
|
||||||
if (MessageObject.canAutoplayAnimatedSticker(document)) {
|
sticker = null;
|
||||||
imageView.setImage(ImageLocation.getForDocument(document), "80_80", ImageLocation.getForDocument(thumb, document), null, 0, set);
|
}
|
||||||
|
if (sticker != null) {
|
||||||
|
TLObject object;
|
||||||
|
if (set.set.thumb instanceof TLRPC.TL_photoSize) {
|
||||||
|
object = set.set.thumb;
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
imageView.setImage(null, null, "webp", null, set);
|
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));
|
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) {
|
if (needCheck) {
|
||||||
checkBox = new CheckBox2(context);
|
checkBox = new CheckBox2(context, 21);
|
||||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||||
checkBox.setSize(21);
|
|
||||||
checkBox.setDrawUnchecked(false);
|
checkBox.setDrawUnchecked(false);
|
||||||
checkBox.setDrawBackgroundAsArc(3);
|
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));
|
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));
|
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) {
|
if (needCheck) {
|
||||||
checkBox = new CheckBox2(context);
|
checkBox = new CheckBox2(context, 21);
|
||||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||||
checkBox.setSize(21);
|
|
||||||
checkBox.setDrawUnchecked(false);
|
checkBox.setDrawUnchecked(false);
|
||||||
checkBox.setDrawBackgroundAsArc(3);
|
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));
|
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.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
|
import org.telegram.messenger.ApplicationLoader;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
public class PhotoAttachCameraCell extends FrameLayout {
|
public class PhotoAttachCameraCell extends FrameLayout {
|
||||||
|
|
||||||
private ImageView imageView;
|
private ImageView imageView;
|
||||||
|
private ImageView backgroundView;
|
||||||
|
private int itemSize;
|
||||||
|
|
||||||
public PhotoAttachCameraCell(Context context) {
|
public PhotoAttachCameraCell(Context context) {
|
||||||
super(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 = new ImageView(context);
|
||||||
imageView.setScaleType(ImageView.ScaleType.CENTER);
|
imageView.setScaleType(ImageView.ScaleType.CENTER);
|
||||||
imageView.setImageResource(R.drawable.instant_camera);
|
imageView.setImageResource(R.drawable.instant_camera);
|
||||||
imageView.setBackgroundColor(0xff000000);
|
|
||||||
addView(imageView, LayoutHelper.createFrame(80, 80));
|
addView(imageView, LayoutHelper.createFrame(80, 80));
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
|
|
||||||
|
itemSize = AndroidUtilities.dp(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
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() {
|
public ImageView getImageView() {
|
||||||
|
@ -50,4 +74,19 @@ public class PhotoAttachCameraCell extends FrameLayout {
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogCameraIcon), PorterDuff.Mode.MULTIPLY));
|
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.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
@ -33,16 +36,18 @@ import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.LocaleController;
|
import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.MediaController;
|
import org.telegram.messenger.MediaController;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.BackupImageView;
|
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.Components.LayoutHelper;
|
||||||
import org.telegram.ui.PhotoViewer;
|
import org.telegram.ui.PhotoViewer;
|
||||||
|
|
||||||
public class PhotoAttachPhotoCell extends FrameLayout {
|
public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
|
|
||||||
private BackupImageView imageView;
|
private BackupImageView imageView;
|
||||||
|
private FrameLayout container;
|
||||||
private FrameLayout checkFrame;
|
private FrameLayout checkFrame;
|
||||||
private CheckBox checkBox;
|
private CheckBox2 checkBox;
|
||||||
private TextView videoTextView;
|
private TextView videoTextView;
|
||||||
private FrameLayout videoInfoContainer;
|
private FrameLayout videoInfoContainer;
|
||||||
private AnimatorSet animatorSet;
|
private AnimatorSet animatorSet;
|
||||||
|
@ -50,8 +55,13 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
private boolean pressed;
|
private boolean pressed;
|
||||||
private static Rect rect = new Rect();
|
private static Rect rect = new Rect();
|
||||||
private PhotoAttachPhotoCellDelegate delegate;
|
private PhotoAttachPhotoCellDelegate delegate;
|
||||||
private boolean isVertical;
|
private boolean itemSizeChanged;
|
||||||
private boolean needCheckShow;
|
private boolean needCheckShow;
|
||||||
|
private int itemSize;
|
||||||
|
private boolean isVertical;
|
||||||
|
|
||||||
|
private Paint backgroundPaint = new Paint();
|
||||||
|
private AnimatorSet animator;
|
||||||
|
|
||||||
public interface PhotoAttachPhotoCellDelegate {
|
public interface PhotoAttachPhotoCellDelegate {
|
||||||
void onCheckClick(PhotoAttachPhotoCell v);
|
void onCheckClick(PhotoAttachPhotoCell v);
|
||||||
|
@ -62,46 +72,85 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
public PhotoAttachPhotoCell(Context context) {
|
public PhotoAttachPhotoCell(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
||||||
imageView = new BackupImageView(context);
|
setWillNotDraw(false);
|
||||||
addView(imageView, LayoutHelper.createFrame(80, 80));
|
|
||||||
checkFrame = new FrameLayout(context);
|
|
||||||
addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.LEFT | Gravity.TOP, 38, 0, 0, 0));
|
|
||||||
|
|
||||||
videoInfoContainer = new FrameLayout(context);
|
container = new FrameLayout(context);
|
||||||
videoInfoContainer.setBackgroundResource(R.drawable.phototime);
|
addView(container, LayoutHelper.createFrame(80, 80));
|
||||||
videoInfoContainer.setPadding(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(3), 0);
|
|
||||||
addView(videoInfoContainer, LayoutHelper.createFrame(80, 16, Gravity.BOTTOM | Gravity.LEFT));
|
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);
|
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));
|
videoInfoContainer.addView(imageView1, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL));
|
||||||
|
|
||||||
videoTextView = new TextView(context);
|
videoTextView = new TextView(context);
|
||||||
videoTextView.setTextColor(0xffffffff);
|
videoTextView.setTextColor(0xffffffff);
|
||||||
|
videoTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||||
videoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
|
videoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
|
||||||
videoTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
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 = new CheckBox2(context, 24);
|
||||||
checkBox.setSize(30);
|
checkBox.setDrawBackgroundAsArc(7);
|
||||||
checkBox.setCheckOffset(AndroidUtilities.dp(1));
|
checkBox.setColor(Theme.key_chat_attachCheckBoxBackground, Theme.key_chat_attachPhotoBackground, Theme.key_chat_attachCheckBoxCheck);
|
||||||
checkBox.setDrawBackground(true);
|
addView(checkBox, LayoutHelper.createFrame(26, 26, Gravity.LEFT | Gravity.TOP, 52, 4, 0, 0));
|
||||||
checkBox.setColor(0xff3ccaef, 0xffffffff);
|
|
||||||
addView(checkBox, LayoutHelper.createFrame(30, 30, Gravity.LEFT | Gravity.TOP, 46, 4, 0, 0));
|
|
||||||
checkBox.setVisibility(VISIBLE);
|
checkBox.setVisibility(VISIBLE);
|
||||||
setFocusable(true);
|
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) {
|
public void setIsVertical(boolean value) {
|
||||||
isVertical = 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
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
if (isVertical) {
|
if (itemSizeChanged) {
|
||||||
super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(80 + (isLast ? 0 : 6)), MeasureSpec.EXACTLY));
|
super.onMeasure(MeasureSpec.makeMeasureSpec(itemSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemSize + AndroidUtilities.dp(5), MeasureSpec.EXACTLY));
|
||||||
} else {
|
} 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;
|
return imageView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CheckBox getCheckBox() {
|
public float getScale() {
|
||||||
|
return container.getScaleX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckBox2 getCheckBox() {
|
||||||
return checkBox;
|
return checkBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,16 +192,16 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
videoInfoContainer.setVisibility(INVISIBLE);
|
videoInfoContainer.setVisibility(INVISIBLE);
|
||||||
}
|
}
|
||||||
if (photoEntry.thumbPath != null) {
|
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) {
|
} else if (photoEntry.path != null) {
|
||||||
if (photoEntry.isVideo) {
|
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 {
|
} else {
|
||||||
imageView.setOrientation(photoEntry.orientation, true);
|
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 {
|
} else {
|
||||||
imageView.setImageResource(R.drawable.nophotos);
|
imageView.setImageDrawable(Theme.chat_attachEmptyDrawable);
|
||||||
}
|
}
|
||||||
boolean showing = needCheckShow && PhotoViewer.isShowingImage(photoEntry.path);
|
boolean showing = needCheckShow && PhotoViewer.isShowingImage(photoEntry.path);
|
||||||
imageView.getImageReceiver().setVisible(!showing, true);
|
imageView.getImageReceiver().setVisible(!showing, true);
|
||||||
|
@ -157,8 +210,43 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
requestLayout();
|
requestLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChecked(int num, boolean value, boolean animated) {
|
public void setChecked(int num, boolean checked, boolean animated) {
|
||||||
checkBox.setChecked(num, value, 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) {
|
public void setNum(int num) {
|
||||||
|
@ -193,8 +281,8 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
animatorSet.setInterpolator(new DecelerateInterpolator());
|
animatorSet.setInterpolator(new DecelerateInterpolator());
|
||||||
animatorSet.setDuration(180);
|
animatorSet.setDuration(180);
|
||||||
animatorSet.playTogether(
|
animatorSet.playTogether(
|
||||||
ObjectAnimator.ofFloat(videoInfoContainer, "alpha", show ? 1.0f : 0.0f),
|
ObjectAnimator.ofFloat(videoInfoContainer, View.ALPHA, show ? 1.0f : 0.0f),
|
||||||
ObjectAnimator.ofFloat(checkBox, "alpha", show ? 1.0f : 0.0f));
|
ObjectAnimator.ofFloat(checkBox, View.ALPHA, show ? 1.0f : 0.0f));
|
||||||
animatorSet.addListener(new AnimatorListenerAdapter() {
|
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
@ -206,6 +294,18 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
animatorSet.start();
|
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
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
@ -242,6 +342,14 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
return result;
|
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
|
@Override
|
||||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||||
super.onInitializeAccessibilityNodeInfo(info);
|
super.onInitializeAccessibilityNodeInfo(info);
|
||||||
|
@ -251,8 +359,9 @@ public class PhotoAttachPhotoCell extends FrameLayout {
|
||||||
} else {
|
} else {
|
||||||
info.setText(LocaleController.getString("AttachPhoto", R.string.AttachPhoto));
|
info.setText(LocaleController.getString("AttachPhoto", R.string.AttachPhoto));
|
||||||
}
|
}
|
||||||
if (checkBox.isChecked())
|
if (checkBox.isChecked()) {
|
||||||
info.setSelected(true);
|
info.setSelected(true);
|
||||||
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.acc_action_open_photo, LocaleController.getString("Open", R.string.Open)));
|
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
|
@Override
|
||||||
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
||||||
if (action == R.id.acc_action_open_photo) {
|
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_DOWN, getLeft(), getTop() + getHeight() - 1, 0));
|
||||||
parent.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, 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;
|
package org.telegram.ui.Cells;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
|
@ -21,7 +23,6 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.MediaController;
|
import org.telegram.messenger.MediaController;
|
||||||
import org.telegram.messenger.R;
|
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.BackupImageView;
|
import org.telegram.ui.Components.BackupImageView;
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
|
@ -36,6 +37,7 @@ public class PhotoPickerAlbumsCell extends FrameLayout {
|
||||||
private MediaController.AlbumEntry[] albumEntries;
|
private MediaController.AlbumEntry[] albumEntries;
|
||||||
private int albumsCount;
|
private int albumsCount;
|
||||||
private PhotoPickerAlbumsCellDelegate delegate;
|
private PhotoPickerAlbumsCellDelegate delegate;
|
||||||
|
private Paint backgroundPaint = new Paint();
|
||||||
|
|
||||||
private class AlbumView extends FrameLayout {
|
private class AlbumView extends FrameLayout {
|
||||||
|
|
||||||
|
@ -85,6 +87,14 @@ public class PhotoPickerAlbumsCell extends FrameLayout {
|
||||||
}
|
}
|
||||||
return super.onTouchEvent(event);
|
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) {
|
public PhotoPickerAlbumsCell(Context context) {
|
||||||
|
@ -96,12 +106,9 @@ public class PhotoPickerAlbumsCell extends FrameLayout {
|
||||||
addView(albumViews[a]);
|
addView(albumViews[a]);
|
||||||
albumViews[a].setVisibility(INVISIBLE);
|
albumViews[a].setVisibility(INVISIBLE);
|
||||||
albumViews[a].setTag(a);
|
albumViews[a].setTag(a);
|
||||||
albumViews[a].setOnClickListener(new OnClickListener() {
|
albumViews[a].setOnClickListener(v -> {
|
||||||
@Override
|
if (delegate != null) {
|
||||||
public void onClick(View v) {
|
delegate.didSelectAlbum(albumEntries[(Integer) v.getTag()]);
|
||||||
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) {
|
if (albumEntry.coverPhoto != null && albumEntry.coverPhoto.path != null) {
|
||||||
albumView.imageView.setOrientation(albumEntry.coverPhoto.orientation, true);
|
albumView.imageView.setOrientation(albumEntry.coverPhoto.orientation, true);
|
||||||
if (albumEntry.coverPhoto.isVideo) {
|
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 {
|
} 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 {
|
} else {
|
||||||
albumView.imageView.setImageResource(R.drawable.nophotos);
|
albumView.imageView.setImageDrawable(Theme.chat_attachEmptyDrawable);
|
||||||
}
|
}
|
||||||
albumView.nameTextView.setText(albumEntry.bucketName);
|
albumView.nameTextView.setText(albumEntry.bucketName);
|
||||||
albumView.countTextView.setText(String.format("%d", albumEntry.photos.size()));
|
albumView.countTextView.setText(String.format("%d", albumEntry.photos.size()));
|
||||||
|
|
|
@ -13,9 +13,12 @@ import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Paint;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
import android.view.animation.DecelerateInterpolator;
|
import android.view.animation.DecelerateInterpolator;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
@ -24,17 +27,20 @@ import android.widget.TextView;
|
||||||
import org.telegram.messenger.AndroidUtilities;
|
import org.telegram.messenger.AndroidUtilities;
|
||||||
import org.telegram.messenger.FileLoader;
|
import org.telegram.messenger.FileLoader;
|
||||||
import org.telegram.messenger.ImageLocation;
|
import org.telegram.messenger.ImageLocation;
|
||||||
|
import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.MediaController;
|
import org.telegram.messenger.MediaController;
|
||||||
import org.telegram.messenger.MessageObject;
|
import org.telegram.messenger.MessageObject;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.BackupImageView;
|
import org.telegram.ui.Components.BackupImageView;
|
||||||
import org.telegram.ui.Components.CheckBox;
|
import org.telegram.ui.Components.CheckBox;
|
||||||
import org.telegram.ui.Components.LayoutHelper;
|
import org.telegram.ui.Components.LayoutHelper;
|
||||||
|
import org.telegram.ui.PhotoViewer;
|
||||||
|
|
||||||
public class PhotoPickerPhotoCell extends FrameLayout {
|
public class PhotoPickerPhotoCell extends FrameLayout {
|
||||||
|
|
||||||
public BackupImageView photoImage;
|
public BackupImageView imageView;
|
||||||
public FrameLayout checkFrame;
|
public FrameLayout checkFrame;
|
||||||
public CheckBox checkBox;
|
public CheckBox checkBox;
|
||||||
public TextView videoTextView;
|
public TextView videoTextView;
|
||||||
|
@ -43,14 +49,17 @@ public class PhotoPickerPhotoCell extends FrameLayout {
|
||||||
private AnimatorSet animatorSet;
|
private AnimatorSet animatorSet;
|
||||||
public int itemWidth;
|
public int itemWidth;
|
||||||
private boolean zoomOnSelect;
|
private boolean zoomOnSelect;
|
||||||
|
private Paint backgroundPaint = new Paint();
|
||||||
|
private MediaController.PhotoEntry photoEntry;
|
||||||
|
|
||||||
public PhotoPickerPhotoCell(Context context, boolean zoom) {
|
public PhotoPickerPhotoCell(Context context, boolean zoom) {
|
||||||
super(context);
|
super(context);
|
||||||
|
setWillNotDraw(false);
|
||||||
|
|
||||||
zoomOnSelect = zoom;
|
zoomOnSelect = zoom;
|
||||||
|
|
||||||
photoImage = new BackupImageView(context);
|
imageView = new BackupImageView(context);
|
||||||
addView(photoImage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||||
|
|
||||||
checkFrame = new FrameLayout(context);
|
checkFrame = new FrameLayout(context);
|
||||||
addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.RIGHT | Gravity.TOP));
|
addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.RIGHT | Gravity.TOP));
|
||||||
|
@ -111,21 +120,45 @@ public class PhotoPickerPhotoCell extends FrameLayout {
|
||||||
checkBox.setNum(num);
|
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) {
|
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) {
|
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) {
|
} 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) {
|
} 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) {
|
} 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)) {
|
} else if (MessageObject.isDocumentHasThumb(searchImage.document)) {
|
||||||
TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(searchImage.document.thumbs, 320);
|
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 {
|
} else {
|
||||||
photoImage.setImageDrawable(thumb);
|
imageView.setImageDrawable(thumb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,12 +170,9 @@ public class PhotoPickerPhotoCell extends FrameLayout {
|
||||||
}
|
}
|
||||||
if (zoomOnSelect) {
|
if (zoomOnSelect) {
|
||||||
if (animated) {
|
if (animated) {
|
||||||
if (checked) {
|
|
||||||
setBackgroundColor(0xff0a0a0a);
|
|
||||||
}
|
|
||||||
animator = new AnimatorSet();
|
animator = new AnimatorSet();
|
||||||
animator.playTogether(ObjectAnimator.ofFloat(photoImage, "scaleX", checked ? 0.85f : 1.0f),
|
animator.playTogether(ObjectAnimator.ofFloat(imageView, View.SCALE_X, checked ? 0.85f : 1.0f),
|
||||||
ObjectAnimator.ofFloat(photoImage, "scaleY", checked ? 0.85f : 1.0f));
|
ObjectAnimator.ofFloat(imageView, View.SCALE_Y, checked ? 0.85f : 1.0f));
|
||||||
animator.setDuration(200);
|
animator.setDuration(200);
|
||||||
animator.addListener(new AnimatorListenerAdapter() {
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -164,10 +194,20 @@ public class PhotoPickerPhotoCell extends FrameLayout {
|
||||||
});
|
});
|
||||||
animator.start();
|
animator.start();
|
||||||
} else {
|
} else {
|
||||||
setBackgroundColor(checked ? 0xff0A0A0A : 0);
|
imageView.setScaleX(checked ? 0.85f : 1.0f);
|
||||||
photoImage.setScaleX(checked ? 0.85f : 1.0f);
|
imageView.setScaleY(checked ? 0.85f : 1.0f);
|
||||||
photoImage.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.Canvas;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
@ -143,6 +144,9 @@ public class PollEditTextCell extends FrameLayout {
|
||||||
deleteImageView.setTag(null);
|
deleteImageView.setTag(null);
|
||||||
}
|
}
|
||||||
textView.setText(text);
|
textView.setText(text);
|
||||||
|
if (!TextUtils.isEmpty(text)) {
|
||||||
|
textView.setSelection(text.length());
|
||||||
|
}
|
||||||
textView.setHint(hint);
|
textView.setHint(hint);
|
||||||
needDivider = divider;
|
needDivider = divider;
|
||||||
setWillNotDraw(!divider);
|
setWillNotDraw(!divider);
|
||||||
|
|
|
@ -65,8 +65,7 @@ public class ShareDialogCell extends FrameLayout {
|
||||||
nameTextView.setEllipsize(TextUtils.TruncateAt.END);
|
nameTextView.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 66, 6, 0));
|
addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 66, 6, 0));
|
||||||
|
|
||||||
checkBox = new CheckBox2(context);
|
checkBox = new CheckBox2(context, 21);
|
||||||
checkBox.setSize(21);
|
|
||||||
checkBox.setColor(Theme.key_dialogRoundCheckBox, Theme.key_dialogBackground, Theme.key_dialogRoundCheckBoxCheck);
|
checkBox.setColor(Theme.key_dialogRoundCheckBox, Theme.key_dialogBackground, Theme.key_dialogRoundCheckBoxCheck);
|
||||||
checkBox.setDrawUnchecked(false);
|
checkBox.setDrawUnchecked(false);
|
||||||
checkBox.setDrawBackgroundAsArc(4);
|
checkBox.setDrawBackgroundAsArc(4);
|
||||||
|
|
|
@ -66,10 +66,9 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F
|
||||||
TAG = DownloadController.getInstance(currentAccount).generateObserverTag();
|
TAG = DownloadController.getInstance(currentAccount).generateObserverTag();
|
||||||
setWillNotDraw(false);
|
setWillNotDraw(false);
|
||||||
|
|
||||||
checkBox = new CheckBox2(context);
|
checkBox = new CheckBox2(context, 21);
|
||||||
checkBox.setVisibility(INVISIBLE);
|
checkBox.setVisibility(INVISIBLE);
|
||||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||||
checkBox.setSize(21);
|
|
||||||
checkBox.setDrawUnchecked(false);
|
checkBox.setDrawUnchecked(false);
|
||||||
checkBox.setDrawBackgroundAsArc(3);
|
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));
|
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));
|
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));
|
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.setVisibility(INVISIBLE);
|
||||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||||
checkBox.setSize(21);
|
|
||||||
checkBox.setDrawUnchecked(false);
|
checkBox.setDrawUnchecked(false);
|
||||||
checkBox.setDrawBackgroundAsArc(2);
|
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));
|
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));
|
linkImageView.setRoundRadius(AndroidUtilities.dp(4));
|
||||||
letterDrawable = new LetterDrawable();
|
letterDrawable = new LetterDrawable();
|
||||||
|
|
||||||
checkBox = new CheckBox2(context);
|
checkBox = new CheckBox2(context, 21);
|
||||||
checkBox.setVisibility(INVISIBLE);
|
checkBox.setVisibility(INVISIBLE);
|
||||||
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck);
|
||||||
checkBox.setSize(21);
|
|
||||||
checkBox.setDrawUnchecked(false);
|
checkBox.setDrawUnchecked(false);
|
||||||
checkBox.setDrawBackgroundAsArc(2);
|
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));
|
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));
|
selector.setBackgroundDrawable(Theme.getSelectorDrawable(false));
|
||||||
addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
addView(selector, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
|
||||||
|
|
||||||
checkBox = new CheckBox2(context);
|
checkBox = new CheckBox2(context, 21);
|
||||||
checkBox.setVisibility(INVISIBLE);
|
checkBox.setVisibility(INVISIBLE);
|
||||||
checkBox.setColor(null, Theme.key_sharedMedia_photoPlaceholder, Theme.key_checkboxCheck);
|
checkBox.setColor(null, Theme.key_sharedMedia_photoPlaceholder, Theme.key_checkboxCheck);
|
||||||
checkBox.setSize(21);
|
|
||||||
checkBox.setDrawUnchecked(false);
|
checkBox.setDrawUnchecked(false);
|
||||||
checkBox.setDrawBackgroundAsArc(1);
|
checkBox.setDrawBackgroundAsArc(1);
|
||||||
addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.RIGHT | Gravity.TOP, 0, 1, 1, 0));
|
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) {
|
if (animated) {
|
||||||
animator = new AnimatorSet();
|
animator = new AnimatorSet();
|
||||||
animator.playTogether(
|
animator.playTogether(
|
||||||
ObjectAnimator.ofFloat(container, "scaleX", checked ? 0.81f : 1.0f),
|
ObjectAnimator.ofFloat(container, View.SCALE_X, checked ? 0.81f : 1.0f),
|
||||||
ObjectAnimator.ofFloat(container, "scaleY", checked ? 0.81f : 1.0f));
|
ObjectAnimator.ofFloat(container, View.SCALE_Y, checked ? 0.81f : 1.0f));
|
||||||
animator.setDuration(200);
|
animator.setDuration(200);
|
||||||
animator.addListener(new AnimatorListenerAdapter() {
|
animator.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.telegram.messenger.ImageLocation;
|
||||||
import org.telegram.messenger.LocaleController;
|
import org.telegram.messenger.LocaleController;
|
||||||
import org.telegram.messenger.MessageObject;
|
import org.telegram.messenger.MessageObject;
|
||||||
import org.telegram.messenger.R;
|
import org.telegram.messenger.R;
|
||||||
|
import org.telegram.tgnet.TLObject;
|
||||||
import org.telegram.tgnet.TLRPC;
|
import org.telegram.tgnet.TLRPC;
|
||||||
import org.telegram.ui.ActionBar.Theme;
|
import org.telegram.ui.ActionBar.Theme;
|
||||||
import org.telegram.ui.Components.BackupImageView;
|
import org.telegram.ui.Components.BackupImageView;
|
||||||
|
@ -53,12 +54,13 @@ public class StickerSetCell extends FrameLayout {
|
||||||
textView = new TextView(context);
|
textView = new TextView(context);
|
||||||
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText));
|
||||||
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
|
||||||
|
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
|
||||||
textView.setLines(1);
|
textView.setLines(1);
|
||||||
textView.setMaxLines(1);
|
textView.setMaxLines(1);
|
||||||
textView.setSingleLine(true);
|
textView.setSingleLine(true);
|
||||||
textView.setEllipsize(TextUtils.TruncateAt.END);
|
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
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 = new TextView(context);
|
||||||
valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2));
|
valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2));
|
||||||
|
@ -67,18 +69,18 @@ public class StickerSetCell extends FrameLayout {
|
||||||
valueTextView.setMaxLines(1);
|
valueTextView.setMaxLines(1);
|
||||||
valueTextView.setSingleLine(true);
|
valueTextView.setSingleLine(true);
|
||||||
valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
|
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 = new BackupImageView(context);
|
||||||
imageView.setAspectFit(true);
|
imageView.setAspectFit(true);
|
||||||
imageView.setLayerNum(1);
|
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) {
|
if (option == 2) {
|
||||||
progressView = new RadialProgressView(getContext());
|
progressView = new RadialProgressView(getContext());
|
||||||
progressView.setProgressColor(Theme.getColor(Theme.key_dialogProgressCircle));
|
progressView.setProgressColor(Theme.getColor(Theme.key_dialogProgressCircle));
|
||||||
progressView.setSize(AndroidUtilities.dp(30));
|
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) {
|
} else if (option != 0) {
|
||||||
optionsButton = new ImageView(context);
|
optionsButton = new ImageView(context);
|
||||||
optionsButton.setFocusable(false);
|
optionsButton.setFocusable(false);
|
||||||
|
@ -87,18 +89,18 @@ public class StickerSetCell extends FrameLayout {
|
||||||
if (option == 1) {
|
if (option == 1) {
|
||||||
optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_stickers_menu), PorterDuff.Mode.MULTIPLY));
|
optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_stickers_menu), PorterDuff.Mode.MULTIPLY));
|
||||||
optionsButton.setImageResource(R.drawable.msg_actions);
|
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) {
|
} else if (option == 3) {
|
||||||
optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.MULTIPLY));
|
optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.MULTIPLY));
|
||||||
optionsButton.setImageResource(R.drawable.sticker_added);
|
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
|
@Override
|
||||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
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) {
|
public void setText(String title, String subtitle, int icon, boolean divider) {
|
||||||
|
@ -145,15 +147,34 @@ public class StickerSetCell extends FrameLayout {
|
||||||
valueTextView.setAlpha(1.0f);
|
valueTextView.setAlpha(1.0f);
|
||||||
imageView.setAlpha(1.0f);
|
imageView.setAlpha(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<TLRPC.Document> documents = set.documents;
|
ArrayList<TLRPC.Document> documents = set.documents;
|
||||||
if (documents != null && !documents.isEmpty()) {
|
if (documents != null && !documents.isEmpty()) {
|
||||||
valueTextView.setText(LocaleController.formatPluralString("Stickers", documents.size()));
|
valueTextView.setText(LocaleController.formatPluralString("Stickers", documents.size()));
|
||||||
TLRPC.Document document = documents.get(0);
|
|
||||||
TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90);
|
TLRPC.Document sticker = documents.get(0);
|
||||||
if (MessageObject.canAutoplayAnimatedSticker(document)) {
|
TLObject object;
|
||||||
imageView.setImage(ImageLocation.getForDocument(document), "80_80", ImageLocation.getForDocument(thumb, document), null, 0, set);
|
if (set.set.thumb instanceof TLRPC.TL_photoSize) {
|
||||||
|
object = set.set.thumb;
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
valueTextView.setText(LocaleController.formatPluralString("Stickers", 0));
|
valueTextView.setText(LocaleController.formatPluralString("Stickers", 0));
|
||||||
|
|
|
@ -168,17 +168,13 @@ public class UserCell extends FrameLayout {
|
||||||
addButton.setVisibility(value ? VISIBLE : GONE);
|
addButton.setVisibility(value ? VISIBLE : GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIsAdmin(int value) {
|
public void setAdminRole(String role) {
|
||||||
if (adminTextView == null) {
|
if (adminTextView == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
adminTextView.setVisibility(value != 0 ? VISIBLE : GONE);
|
adminTextView.setVisibility(role != null ? VISIBLE : GONE);
|
||||||
if (value == 1) {
|
adminTextView.setText(role);
|
||||||
adminTextView.setText(LocaleController.getString("ChannelCreator", R.string.ChannelCreator));
|
if (role != null) {
|
||||||
} else if (value == 2) {
|
|
||||||
adminTextView.setText(LocaleController.getString("ChannelAdmin", R.string.ChannelAdmin));
|
|
||||||
}
|
|
||||||
if (value != 0) {
|
|
||||||
CharSequence text = adminTextView.getText();
|
CharSequence text = adminTextView.getText();
|
||||||
int size = (int) Math.ceil(adminTextView.getPaint().measureText(text, 0, text.length()));
|
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);
|
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);
|
avatarImageView.setImage(ImageLocation.getForUser(currentUser, false), "50_50", avatarDrawable, currentUser);
|
||||||
} else if (currentChat != null) {
|
} else if (currentChat != null) {
|
||||||
avatarImageView.setImage(ImageLocation.getForChat(currentChat, false), "50_50", avatarDrawable, currentChat);
|
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