Update to 6.2.0 (1984)

This commit is contained in:
DrKLO 2020-06-05 00:47:15 +08:00 committed by 世界
parent 9c11ea0f31
commit 06bcaa7d3f
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
298 changed files with 23080 additions and 9480 deletions

View File

@ -33,7 +33,7 @@ jobs:
nativeBuild: nativeBuild:
name: Native Build name: Native Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: "contains(github.event.head_commit.message, '[N]')" if: "contains(github.event.head_commit.message, '[n]')"
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/cache@v1 - uses: actions/cache@v1
@ -100,7 +100,7 @@ jobs:
v2rayBuild: v2rayBuild:
name: V2ray Build name: V2ray Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: "contains(github.event.head_commit.message, '[v2ray]')" if: "contains(github.event.head_commit.message, '[v]')"
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: actions/setup-go@v1 - uses: actions/setup-go@v1

View File

@ -4,7 +4,7 @@ ENV ANDROID_SDK_URL https://dl.google.com/android/repository/sdk-tools-linux-385
ENV ANDROID_API_LEVEL android-29 ENV ANDROID_API_LEVEL android-29
ENV ANDROID_BUILD_TOOLS_VERSION 29.0.3 ENV ANDROID_BUILD_TOOLS_VERSION 29.0.3
ENV ANDROID_HOME /usr/local/android-sdk-linux ENV ANDROID_HOME /usr/local/android-sdk-linux
ENV ANDROID_NDK_VERSION 20.0.5594570 ENV ANDROID_NDK_VERSION 21.1.6352462
ENV ANDROID_VERSION 29 ENV ANDROID_VERSION 29
ENV ANDROID_NDK_HOME ${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}/ ENV ANDROID_NDK_HOME ${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}/
ENV PATH ${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools ENV PATH ${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools

View File

@ -567,7 +567,7 @@ endif
LOCAL_SRC_FILES += \ LOCAL_SRC_FILES += \
./jni.c \ ./jni.c \
./audio.c \ ./audio.c \
./image.c \ ./image.cpp \
./video.c \ ./video.c \
./intro/IntroRenderer.c \ ./intro/IntroRenderer.c \
./utilities.cpp \ ./utilities.cpp \

View File

@ -30,6 +30,8 @@ static const std::string av_make_error_str(int errnum) {
jclass jclass_AnimatedFileDrawableStream; jclass jclass_AnimatedFileDrawableStream;
jmethodID jclass_AnimatedFileDrawableStream_read; jmethodID jclass_AnimatedFileDrawableStream_read;
jmethodID jclass_AnimatedFileDrawableStream_cancel; jmethodID jclass_AnimatedFileDrawableStream_cancel;
jmethodID jclass_AnimatedFileDrawableStream_isFinishedLoadingFile;
jmethodID jclass_AnimatedFileDrawableStream_getFinishedFilePath;
typedef struct VideoInfo { typedef struct VideoInfo {
@ -189,6 +191,20 @@ void requestFd(VideoInfo *info) {
attached = false; attached = false;
} }
jniEnv->CallIntMethod(info->stream, jclass_AnimatedFileDrawableStream_read, (jint) 0, (jint) 1); jniEnv->CallIntMethod(info->stream, jclass_AnimatedFileDrawableStream_read, (jint) 0, (jint) 1);
jboolean loaded = jniEnv->CallBooleanMethod(info->stream, jclass_AnimatedFileDrawableStream_isFinishedLoadingFile);
if (loaded) {
delete[] info->src;
jstring src = (jstring) jniEnv->CallObjectMethod(info->stream, jclass_AnimatedFileDrawableStream_getFinishedFilePath);
char const *srcString = jniEnv->GetStringUTFChars(src, 0);
size_t len = strlen(srcString);
info->src = new char[len + 1];
memcpy(info->src, srcString, len);
info->src[len] = '\0';
if (srcString != 0) {
jniEnv->ReleaseStringUTFChars(src, srcString);
}
}
if (attached) { if (attached) {
javaVm->DetachCurrentThread(); javaVm->DetachCurrentThread();
} }
@ -579,7 +595,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, jboolean preview) { jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *env, jclass clazz, jlong ptr, jobject bitmap, jintArray data, jint stride, jboolean preview, jfloat start_time, jfloat end_time) {
if (ptr == NULL || bitmap == nullptr) { if (ptr == NULL || bitmap == nullptr) {
return 0; return 0;
} }
@ -592,9 +608,16 @@ jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *
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);
//LOGD("got packet with size %d", info->pkt.size);
if (ret >= 0) { if (ret >= 0) {
info->orig_pkt = info->pkt; double pts = info->pkt.pts * av_q2d(info->video_stream->time_base);
if (end_time > 0 && info->pkt.stream_index == info->video_stream_idx && pts > end_time) {
av_packet_unref(&info->pkt);
info->pkt.data = NULL;
info->pkt.size = 0;
} else {
info->orig_pkt = info->pkt;
}
} }
} }
@ -624,7 +647,11 @@ jint Java_org_telegram_ui_Components_AnimatedFileDrawable_getVideoFrame(JNIEnv *
} }
if (!preview && 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) { int64_t start_from = 0;
if (start_time > 0) {
start_from = (int64_t)(start_time / av_q2d(info->video_stream->time_base));
}
if ((ret = av_seek_frame(info->fmt_ctx, info->video_stream_idx, start_from, 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));
return 0; return 0;
} else { } else {
@ -710,6 +737,14 @@ jint videoOnJNILoad(JavaVM *vm, JNIEnv *env) {
if (jclass_AnimatedFileDrawableStream_cancel == 0) { if (jclass_AnimatedFileDrawableStream_cancel == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
jclass_AnimatedFileDrawableStream_isFinishedLoadingFile = env->GetMethodID(jclass_AnimatedFileDrawableStream, "isFinishedLoadingFile", "()Z");
if (jclass_AnimatedFileDrawableStream_isFinishedLoadingFile == 0) {
return JNI_FALSE;
}
jclass_AnimatedFileDrawableStream_getFinishedFilePath = env->GetMethodID(jclass_AnimatedFileDrawableStream, "getFinishedFilePath", "()Ljava/lang/String;");
if (jclass_AnimatedFileDrawableStream_getFinishedFilePath == 0) {
return JNI_FALSE;
}
return JNI_TRUE; return JNI_TRUE;
} }

View File

@ -9,8 +9,8 @@
#include <libwebp/src/webp/encode.h> #include <libwebp/src/webp/encode.h>
#include <malloc.h> #include <malloc.h>
#include "c_utils.h" #include "c_utils.h"
#include "image.h"
extern "C" {
jclass jclass_NullPointerException; jclass jclass_NullPointerException;
jclass jclass_RuntimeException; jclass jclass_RuntimeException;
@ -19,43 +19,32 @@ jfieldID jclass_Options_inJustDecodeBounds;
jfieldID jclass_Options_outHeight; jfieldID jclass_Options_outHeight;
jfieldID jclass_Options_outWidth; jfieldID jclass_Options_outWidth;
const uint32_t PGPhotoEnhanceHistogramBins = 256;
const uint32_t PGPhotoEnhanceSegments = 4;
jclass createGlobarRef(JNIEnv *env, jclass class) {
if (class) {
return (*env)->NewGlobalRef(env, class);
}
return 0;
}
jint imageOnJNILoad(JavaVM *vm, JNIEnv *env) { jint imageOnJNILoad(JavaVM *vm, JNIEnv *env) {
jclass_NullPointerException = createGlobarRef(env, (*env)->FindClass(env, "java/lang/NullPointerException")); jclass_NullPointerException = (jclass) env->NewGlobalRef(env->FindClass("java/lang/NullPointerException"));
if (jclass_NullPointerException == 0) { if (jclass_NullPointerException == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
jclass_RuntimeException = createGlobarRef(env, (*env)->FindClass(env, "java/lang/RuntimeException")); jclass_RuntimeException = (jclass) env->NewGlobalRef(env->FindClass("java/lang/RuntimeException"));
if (jclass_RuntimeException == 0) { if (jclass_RuntimeException == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
jclass_Options = (jclass) env->NewGlobalRef(env->FindClass("android/graphics/BitmapFactory$Options"));
jclass_Options = createGlobarRef(env, (*env)->FindClass(env, "android/graphics/BitmapFactory$Options"));
if (jclass_Options == 0) { if (jclass_Options == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
jclass_Options_inJustDecodeBounds = (*env)->GetFieldID(env, jclass_Options, "inJustDecodeBounds", "Z"); jclass_Options_inJustDecodeBounds = env->GetFieldID(jclass_Options, "inJustDecodeBounds", "Z");
if (jclass_Options_inJustDecodeBounds == 0) { if (jclass_Options_inJustDecodeBounds == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
jclass_Options_outHeight = (*env)->GetFieldID(env, jclass_Options, "outHeight", "I"); jclass_Options_outHeight = env->GetFieldID(jclass_Options, "outHeight", "I");
if (jclass_Options_outHeight == 0) { if (jclass_Options_outHeight == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
jclass_Options_outWidth = (*env)->GetFieldID(env, jclass_Options, "outWidth", "I"); jclass_Options_outWidth = env->GetFieldID(jclass_Options, "outWidth", "I");
if (jclass_Options_outWidth == 0) { if (jclass_Options_outWidth == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
return JNI_TRUE; return JNI_TRUE;
} }
@ -65,18 +54,18 @@ static inline uint64_t getColors(const uint8_t *p) {
static inline uint64_t getColors565(const uint8_t *p) { static inline uint64_t getColors565(const uint8_t *p) {
uint16_t *ps = (uint16_t *) p; uint16_t *ps = (uint16_t *) p;
return ((((ps[0] & 0xF800) >> 11) * 255) / 31) + (((((ps[0] & 0x07E0) >> 5) * 255) / 63) << 16) + ((uint64_t) (((ps[0] & 0x001F) * 255) / 31) << 32); return ((((ps[0] & 0xF800) >> 11) * 255) / 31) + (((((ps[0] & 0x07E0) >> 5) * 255) / 63) << 16) + ((uint64_t)(((ps[0] & 0x001F) * 255) / 31) << 32);
} }
static void fastBlurMore(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t radius) { static void fastBlurMore(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t radius) {
const int32_t r1 = radius + 1; const int32_t r1 = radius + 1;
const int32_t div = radius * 2 + 1; const int32_t div = radius * 2 + 1;
if (radius > 15 || div >= w || div >= h || w * h > 150 * 150 || stride > w * 4) { if (radius > 15 || div >= w || div >= h || w * h > 150 * 150 || stride > w * 4) {
return; return;
} }
uint64_t *rgb = malloc(w * h * sizeof(uint64_t)); uint64_t *rgb = new uint64_t[w * h];
if (rgb == NULL) { if (rgb == NULL) {
return; return;
} }
@ -89,16 +78,16 @@ static void fastBlurMore(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int
uint64_t cur = getColors(&pix[yw]); uint64_t cur = getColors(&pix[yw]);
uint64_t rgballsum = -radius * cur; uint64_t rgballsum = -radius * cur;
uint64_t rgbsum = cur * ((r1 * (r1 + 1)) >> 1); uint64_t rgbsum = cur * ((r1 * (r1 + 1)) >> 1);
for (i = 1; i <= radius; i++) { for (i = 1; i <= radius; i++) {
cur = getColors(&pix[yw + i * 4]); cur = getColors(&pix[yw + i * 4]);
rgbsum += cur * (r1 - i); rgbsum += cur * (r1 - i);
rgballsum += cur; rgballsum += cur;
} }
x = 0; x = 0;
#define update(start, middle, end) \ #define update(start, middle, end) \
rgb[y * w + x] = (rgbsum >> 6) & 0x00FF00FF00FF00FF; \ rgb[y * w + x] = (rgbsum >> 6) & 0x00FF00FF00FF00FF; \
rgballsum += getColors(&pix[yw + (start) * 4]) - 2 * getColors(&pix[yw + (middle) * 4]) + getColors(&pix[yw + (end) * 4]); \ rgballsum += getColors(&pix[yw + (start) * 4]) - 2 * getColors(&pix[yw + (middle) * 4]) + getColors(&pix[yw + (end) * 4]); \
rgbsum += rgballsum; \ rgbsum += rgballsum; \
@ -113,11 +102,11 @@ static void fastBlurMore(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int
while (x < w) { while (x < w) {
update (x - r1, x, w - 1); update (x - r1, x, w - 1);
} }
#undef update #undef update
yw += stride; yw += stride;
} }
const int32_t he = h - r1; const int32_t he = h - r1;
for (x = 0; x < w; x++) { for (x = 0; x < w; x++) {
uint64_t rgballsum = -radius * rgb[x]; uint64_t rgballsum = -radius * rgb[x];
@ -126,11 +115,11 @@ static void fastBlurMore(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int
rgbsum += rgb[i * w + x] * (r1 - i); rgbsum += rgb[i * w + x] * (r1 - i);
rgballsum += rgb[i * w + x]; rgballsum += rgb[i * w + x];
} }
y = 0; y = 0;
int32_t yi = x * 4; int32_t yi = x * 4;
#define update(start, middle, end) \ #define update(start, middle, end) \
int64_t res = rgbsum >> 6; \ int64_t res = rgbsum >> 6; \
pix[yi] = res; \ pix[yi] = res; \
pix[yi + 1] = res >> 16; \ pix[yi + 1] = res >> 16; \
@ -140,7 +129,7 @@ static void fastBlurMore(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int
rgbsum += rgballsum; \ rgbsum += rgballsum; \
y++; \ y++; \
yi += stride; yi += stride;
while (y < r1) { while (y < r1) {
update (0, y, y + r1); update (0, y, y + r1);
} }
@ -150,8 +139,10 @@ static void fastBlurMore(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int
while (y < h) { while (y < h) {
update (y - r1, y, h - 1); update (y - r1, y, h - 1);
} }
#undef update #undef update
} }
delete[] rgb;
} }
static void fastBlur(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t radius) { static void fastBlur(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t radius) {
@ -172,12 +163,12 @@ static void fastBlur(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t
} else { } else {
return; return;
} }
if (radius > 15 || div >= w || div >= h || w * h > 150 * 150 || stride > w * 4) { if (radius > 15 || div >= w || div >= h || w * h > 150 * 150 || stride > w * 4) {
return; return;
} }
uint64_t *rgb = malloc(w * h * sizeof(uint64_t)); uint64_t *rgb = new uint64_t[w * h];
if (rgb == NULL) { if (rgb == NULL) {
return; return;
} }
@ -190,16 +181,16 @@ static void fastBlur(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t
uint64_t cur = getColors(&pix[yw]); uint64_t cur = getColors(&pix[yw]);
uint64_t rgballsum = -radius * cur; uint64_t rgballsum = -radius * cur;
uint64_t rgbsum = cur * ((r1 * (r1 + 1)) >> 1); uint64_t rgbsum = cur * ((r1 * (r1 + 1)) >> 1);
for (i = 1; i <= radius; i++) { for (i = 1; i <= radius; i++) {
cur = getColors(&pix[yw + i * 4]); cur = getColors(&pix[yw + i * 4]);
rgbsum += cur * (r1 - i); rgbsum += cur * (r1 - i);
rgballsum += cur; rgballsum += cur;
} }
x = 0; x = 0;
#define update(start, middle, end) \ #define update(start, middle, end) \
rgb[y * w + x] = (rgbsum >> shift) & 0x00FF00FF00FF00FFLL; \ rgb[y * w + x] = (rgbsum >> shift) & 0x00FF00FF00FF00FFLL; \
rgballsum += getColors(&pix[yw + (start) * 4]) - 2 * getColors(&pix[yw + (middle) * 4]) + getColors(&pix[yw + (end) * 4]); \ rgballsum += getColors(&pix[yw + (start) * 4]) - 2 * getColors(&pix[yw + (middle) * 4]) + getColors(&pix[yw + (end) * 4]); \
rgbsum += rgballsum; \ rgbsum += rgballsum; \
@ -214,12 +205,12 @@ static void fastBlur(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t
while (x < w) { while (x < w) {
update (x - r1, x, w - 1); update (x - r1, x, w - 1);
} }
#undef update #undef update
yw += stride; yw += stride;
} }
const int32_t he = h - r1; const int32_t he = h - r1;
for (x = 0; x < w; x++) { for (x = 0; x < w; x++) {
uint64_t rgballsum = -radius * rgb[x]; uint64_t rgballsum = -radius * rgb[x];
@ -228,11 +219,11 @@ static void fastBlur(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t
rgbsum += rgb[i * w + x] * (r1 - i); rgbsum += rgb[i * w + x] * (r1 - i);
rgballsum += rgb[i * w + x]; rgballsum += rgb[i * w + x];
} }
y = 0; y = 0;
int32_t yi = x * 4; int32_t yi = x * 4;
#define update(start, middle, end) \ #define update(start, middle, end) \
int64_t res = rgbsum >> shift; \ int64_t res = rgbsum >> shift; \
pix[yi] = res; \ pix[yi] = res; \
pix[yi + 1] = res >> 16; \ pix[yi + 1] = res >> 16; \
@ -242,7 +233,7 @@ static void fastBlur(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t
rgbsum += rgballsum; \ rgbsum += rgballsum; \
y++; \ y++; \
yi += stride; yi += stride;
while (y < r1) { while (y < r1) {
update (0, y, y + r1); update (0, y, y + r1);
} }
@ -252,10 +243,10 @@ static void fastBlur(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t
while (y < h) { while (y < h) {
update (y - r1, y, h - 1); update (y - r1, y, h - 1);
} }
#undef update #undef update
} }
free(rgb); delete[] rgb;
} }
static void fastBlurMore565(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t radius) { static void fastBlurMore565(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t radius) {
@ -266,7 +257,7 @@ static void fastBlurMore565(int32_t w, int32_t h, int32_t stride, uint8_t *pix,
return; return;
} }
uint64_t *rgb = malloc(w * h * sizeof(uint64_t)); uint64_t *rgb = new uint64_t[w * h];
if (rgb == NULL) { if (rgb == NULL) {
return; return;
} }
@ -340,6 +331,8 @@ static void fastBlurMore565(int32_t w, int32_t h, int32_t stride, uint8_t *pix,
} }
#undef update #undef update
} }
delete[] rgb;
} }
static void fastBlur565(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t radius) { static void fastBlur565(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int32_t radius) {
@ -365,7 +358,7 @@ static void fastBlur565(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int3
return; return;
} }
uint64_t *rgb = malloc(w * h * sizeof(uint64_t)); uint64_t *rgb = new uint64_t[w * h];
if (rgb == NULL) { if (rgb == NULL) {
return; return;
} }
@ -441,10 +434,10 @@ static void fastBlur565(int32_t w, int32_t h, int32_t stride, uint8_t *pix, int3
#undef update #undef update
} }
free(rgb); delete[] rgb;
} }
JNIEXPORT int Java_org_telegram_messenger_Utilities_needInvert(JNIEnv *env, jclass class, jobject bitmap, jint unpin, jint width, jint height, jint stride) { int Java_org_telegram_messenger_Utilities_needInvert(JNIEnv *env, jclass clazz, jobject bitmap, jint unpin, jint width, jint height, jint stride) {
if (!bitmap) { if (!bitmap) {
return 0; return 0;
} }
@ -471,9 +464,9 @@ JNIEXPORT int Java_org_telegram_messenger_Utilities_needInvert(JNIEnv *env, jcla
uint8_t a = pix[index + 3]; uint8_t a = pix[index + 3];
float alpha = a / 255.0f; float alpha = a / 255.0f;
uint8_t r = (uint8_t) (pix[index] * alpha); uint8_t r = (uint8_t)(pix[index] * alpha);
uint8_t g = (uint8_t) (pix[index + 1] * alpha); uint8_t g = (uint8_t)(pix[index + 1] * alpha);
uint8_t b = (uint8_t) (pix[index + 2] * alpha); uint8_t b = (uint8_t)(pix[index + 2] * alpha);
uint8_t cmax = (r > g) ? r : g; uint8_t cmax = (r > g) ? r : g;
if (b > cmax) { if (b > cmax) {
@ -510,30 +503,30 @@ JNIEXPORT int Java_org_telegram_messenger_Utilities_needInvert(JNIEnv *env, jcla
return hasAlpha && matching / total > 0.85; return hasAlpha && matching / total > 0.85;
} }
JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap, jint radius, jint unpin, jint width, jint height, jint stride) { void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass clazz, jobject bitmap, jint radius, jint unpin, jint width, jint height, jint stride) {
if (!bitmap) { if (!bitmap) {
return; return;
} }
if (!width || !height || !stride) { if (!width || !height || !stride) {
return; return;
} }
void *pixels = 0; void *pixels = 0;
if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) { if (AndroidBitmap_lockPixels(env, bitmap, &pixels) < 0) {
return; return;
} }
if (stride == width * 2) { if (stride == width * 2) {
if (radius <= 3) { if (radius <= 3) {
fastBlur565(width, height, stride, pixels, radius); fastBlur565(width, height, stride, (uint8_t *) pixels, radius);
} else { } else {
fastBlurMore565(width, height, stride, pixels, radius); fastBlurMore565(width, height, stride, (uint8_t *) pixels, radius);
} }
} else { } else {
if (radius <= 3) { if (radius <= 3) {
fastBlur(width, height, stride, pixels, radius); fastBlur(width, height, stride, (uint8_t *) pixels, radius);
} else { } else {
fastBlurMore(width, height, stride, pixels, radius); fastBlurMore(width, height, stride, (uint8_t *) pixels, radius);
} }
} }
if (unpin) { if (unpin) {
@ -541,7 +534,10 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jcl
} }
} }
JNIEXPORT void Java_org_telegram_messenger_Utilities_calcCDT(JNIEnv *env, jclass class, jobject hsvBuffer, jint width, jint height, jobject buffer) { const uint32_t PGPhotoEnhanceHistogramBins = 256;
const uint32_t PGPhotoEnhanceSegments = 4;
void Java_org_telegram_messenger_Utilities_calcCDT(JNIEnv *env, jclass clazz, jobject hsvBuffer, jint width, jint height, jobject buffer, jobject calcBuffer) {
float imageWidth = width; float imageWidth = width;
float imageHeight = height; float imageHeight = height;
float _clipLimit = 1.25f; float _clipLimit = 1.25f;
@ -551,177 +547,173 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_calcCDT(JNIEnv *env, jclass
uint32_t clipLimit = (uint32_t) MAX(1, _clipLimit * tileArea / (float) PGPhotoEnhanceHistogramBins); uint32_t clipLimit = (uint32_t) MAX(1, _clipLimit * tileArea / (float) PGPhotoEnhanceHistogramBins);
float scale = 255.0f / (float) tileArea; float scale = 255.0f / (float) tileArea;
unsigned char *bytes = (*env)->GetDirectBufferAddress(env, hsvBuffer); unsigned char *bytes = (unsigned char *) env->GetDirectBufferAddress(hsvBuffer);
uint32_t *calcBytes = (uint32_t *) env->GetDirectBufferAddress(calcBuffer);
unsigned char *result = (unsigned char *) env->GetDirectBufferAddress(buffer);
uint32_t *cdfsMin = calcBytes;
calcBytes += totalSegments;
uint32_t *cdfsMax = calcBytes;
calcBytes += totalSegments;
uint32_t *cdfs = calcBytes;
calcBytes += totalSegments * PGPhotoEnhanceHistogramBins;
uint32_t *hist = calcBytes;
memset(hist, 0, sizeof(uint32_t) * totalSegments * PGPhotoEnhanceHistogramBins);
uint32_t **hist = calloc(totalSegments, sizeof(uint32_t *));
uint32_t **cdfs = calloc(totalSegments, sizeof(uint32_t *));
uint32_t *cdfsMin = calloc(totalSegments, sizeof(uint32_t));
uint32_t *cdfsMax = calloc(totalSegments, sizeof(uint32_t));
for (uint32_t a = 0; a < totalSegments; a++) {
hist[a] = calloc(PGPhotoEnhanceHistogramBins, sizeof(uint32_t));
cdfs[a] = calloc(PGPhotoEnhanceHistogramBins, sizeof(uint32_t));
}
float xMul = PGPhotoEnhanceSegments / imageWidth; float xMul = PGPhotoEnhanceSegments / imageWidth;
float yMul = PGPhotoEnhanceSegments / imageHeight; float yMul = PGPhotoEnhanceSegments / imageHeight;
for (uint32_t y = 0; y < imageHeight; y++) { uint32_t i, j;
uint32_t yOffset = y * width * 4;
for (uint32_t x = 0; x < imageWidth; x++) { for (i = 0; i < imageHeight; i++) {
uint32_t index = x * 4 + yOffset; uint32_t yOffset = i * width * 4;
for (j = 0; j < imageWidth; j++) {
uint32_t tx = (uint32_t)(x * xMul); uint32_t index = j * 4 + yOffset;
uint32_t ty = (uint32_t)(y * yMul);
uint32_t tx = (uint32_t)(j * xMul);
uint32_t ty = (uint32_t)(i * yMul);
uint32_t t = ty * PGPhotoEnhanceSegments + tx; uint32_t t = ty * PGPhotoEnhanceSegments + tx;
hist[t][bytes[index + 2]]++; hist[t * PGPhotoEnhanceHistogramBins + bytes[index + 2]]++;
} }
} }
for (uint32_t i = 0; i < totalSegments; i++) { for (i = 0; i < totalSegments; i++) {
if (clipLimit > 0) { if (clipLimit > 0) {
uint32_t clipped = 0; uint32_t clipped = 0;
for (uint32_t j = 0; j < PGPhotoEnhanceHistogramBins; ++j) { for (j = 0; j < PGPhotoEnhanceHistogramBins; j++) {
if (hist[i][j] > clipLimit) { if (hist[i * PGPhotoEnhanceHistogramBins + j] > clipLimit) {
clipped += hist[i][j] - clipLimit; clipped += hist[i * PGPhotoEnhanceHistogramBins + j] - clipLimit;
hist[i][j] = clipLimit; hist[i * PGPhotoEnhanceHistogramBins + j] = clipLimit;
} }
} }
uint32_t redistBatch = clipped / PGPhotoEnhanceHistogramBins; uint32_t redistBatch = clipped / PGPhotoEnhanceHistogramBins;
uint32_t residual = clipped - redistBatch * PGPhotoEnhanceHistogramBins; uint32_t residual = clipped - redistBatch * PGPhotoEnhanceHistogramBins;
for (uint32_t j = 0; j < PGPhotoEnhanceHistogramBins; ++j) { for (j = 0; j < PGPhotoEnhanceHistogramBins; j++) {
hist[i][j] += redistBatch; hist[i * PGPhotoEnhanceHistogramBins + j] += redistBatch;
} if (j < residual) {
hist[i * PGPhotoEnhanceHistogramBins + j]++;
for (uint32_t j = 0; j < residual; ++j) { }
hist[i][j]++;
} }
} }
memcpy(cdfs[i], hist[i], PGPhotoEnhanceHistogramBins * sizeof(uint32_t)); memcpy(cdfs + i * PGPhotoEnhanceHistogramBins, hist + i * PGPhotoEnhanceHistogramBins, PGPhotoEnhanceHistogramBins * sizeof(uint32_t));
uint32_t hMin = PGPhotoEnhanceHistogramBins - 1; uint32_t hMin = PGPhotoEnhanceHistogramBins - 1;
for (uint32_t j = 0; j < hMin; ++j) { for (j = 0; j < hMin; ++j) {
if (cdfs[j] != 0) { if (cdfs[i * PGPhotoEnhanceHistogramBins + j] != 0) {
hMin = j; hMin = j;
} }
} }
uint32_t cdf = 0; uint32_t cdf = 0;
for (uint32_t j = hMin; j < PGPhotoEnhanceHistogramBins; ++j) { for (j = hMin; j < PGPhotoEnhanceHistogramBins; j++) {
cdf += cdfs[i][j]; cdf += cdfs[i * PGPhotoEnhanceHistogramBins + j];
cdfs[i][j] = (uint8_t) MIN(255, cdf * scale); cdfs[i * PGPhotoEnhanceHistogramBins + j] = (uint8_t) MIN(255, cdf * scale);
} }
cdfsMin[i] = cdfs[i][hMin]; cdfsMin[i] = cdfs[i * PGPhotoEnhanceHistogramBins + hMin];
cdfsMax[i] = cdfs[i][PGPhotoEnhanceHistogramBins - 1]; cdfsMax[i] = cdfs[i * PGPhotoEnhanceHistogramBins + PGPhotoEnhanceHistogramBins - 1];
} }
uint32_t resultSize = 4 * PGPhotoEnhanceHistogramBins * totalSegments; for (j = 0; j < totalSegments; j++) {
uint32_t resultBytesPerRow = 4 * PGPhotoEnhanceHistogramBins; uint32_t yOffset = j * PGPhotoEnhanceHistogramBins * 4;
for (i = 0; i < PGPhotoEnhanceHistogramBins; i++) {
unsigned char *result = (*env)->GetDirectBufferAddress(env, buffer);
for (uint32_t tile = 0; tile < totalSegments; tile++) {
uint32_t yOffset = tile * resultBytesPerRow;
for (uint32_t i = 0; i < PGPhotoEnhanceHistogramBins; i++) {
uint32_t index = i * 4 + yOffset; uint32_t index = i * 4 + yOffset;
result[index] = (uint8_t)cdfs[tile][i]; result[index] = (uint8_t) cdfs[j * PGPhotoEnhanceHistogramBins + i];
result[index + 1] = (uint8_t)cdfsMin[tile]; result[index + 1] = (uint8_t) cdfsMin[j];
result[index + 2] = (uint8_t)cdfsMax[tile]; result[index + 2] = (uint8_t) cdfsMax[j];
result[index + 3] = 255; result[index + 3] = 255;
} }
} }
for (uint32_t a = 0; a < totalSegments; a++) {
free(hist[a]);
free(cdfs[a]);
}
free(hist);
free(cdfs);
free(cdfsMax);
free(cdfsMin);
} }
JNIEXPORT jint Java_org_telegram_messenger_Utilities_pinBitmap(JNIEnv *env, jclass class, jobject bitmap) { jint Java_org_telegram_messenger_Utilities_pinBitmap(JNIEnv *env, jclass clazz, jobject bitmap) {
if (bitmap == NULL) { if (bitmap == nullptr) {
return 0; return 0;
} }
unsigned char *pixels; void *pixels;
return AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 ? 1 : 0; return AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 ? 1 : 0;
} }
JNIEXPORT void Java_org_telegram_messenger_Utilities_unpinBitmap(JNIEnv *env, jclass class, jobject bitmap) { void Java_org_telegram_messenger_Utilities_unpinBitmap(JNIEnv *env, jclass clazz, jobject bitmap) {
if (bitmap == NULL) { if (bitmap == NULL) {
return; return;
} }
AndroidBitmap_unlockPixels(env, bitmap); AndroidBitmap_unlockPixels(env, bitmap);
} }
JNIEXPORT jboolean Java_org_telegram_messenger_Utilities_loadWebpImage(JNIEnv *env, jclass class, jobject outputBitmap, jobject buffer, jint len, jobject options, jboolean unpin) { jboolean Java_org_telegram_messenger_Utilities_loadWebpImage(JNIEnv *env, jclass clazz, jobject outputBitmap, jobject buffer, jint len, jobject options, jboolean unpin) {
if (!buffer) { if (!buffer) {
(*env)->ThrowNew(env, jclass_NullPointerException, "Input buffer can not be null"); env->ThrowNew(jclass_NullPointerException, "Input buffer can not be null");
return 0; return 0;
} }
jbyte *inputBuffer = (*env)->GetDirectBufferAddress(env, buffer); jbyte *inputBuffer = (jbyte *) env->GetDirectBufferAddress(buffer);
int32_t bitmapWidth = 0; int32_t bitmapWidth = 0;
int32_t bitmapHeight = 0; int32_t bitmapHeight = 0;
if (!WebPGetInfo((uint8_t*)inputBuffer, len, &bitmapWidth, &bitmapHeight)) { if (!WebPGetInfo((uint8_t *)inputBuffer, len, &bitmapWidth, &bitmapHeight)) {
(*env)->ThrowNew(env, jclass_RuntimeException, "Invalid WebP format"); env->ThrowNew(jclass_RuntimeException, "Invalid WebP format");
return 0; return 0;
} }
if (options && (*env)->GetBooleanField(env, options, jclass_Options_inJustDecodeBounds) == JNI_TRUE) { if (options && env->GetBooleanField(options, jclass_Options_inJustDecodeBounds) == JNI_TRUE) {
(*env)->SetIntField(env, options, jclass_Options_outWidth, bitmapWidth); env->SetIntField(options, jclass_Options_outWidth, bitmapWidth);
(*env)->SetIntField(env, options, jclass_Options_outHeight, bitmapHeight); env->SetIntField(options, jclass_Options_outHeight, bitmapHeight);
return 1; return 1;
} }
if (!outputBitmap) { if (!outputBitmap) {
(*env)->ThrowNew(env, jclass_NullPointerException, "output bitmap can not be null"); env->ThrowNew(jclass_NullPointerException, "output bitmap can not be null");
return 0; return 0;
} }
AndroidBitmapInfo bitmapInfo; AndroidBitmapInfo bitmapInfo;
if (AndroidBitmap_getInfo(env, outputBitmap, &bitmapInfo) != ANDROID_BITMAP_RESUT_SUCCESS) { if (AndroidBitmap_getInfo(env, outputBitmap, &bitmapInfo) != ANDROID_BITMAP_RESUT_SUCCESS) {
(*env)->ThrowNew(env, jclass_RuntimeException, "Failed to get Bitmap information"); env->ThrowNew(jclass_RuntimeException, "Failed to get Bitmap information");
return 0; return 0;
} }
void *bitmapPixels = 0; void *bitmapPixels = 0;
if (AndroidBitmap_lockPixels(env, outputBitmap, &bitmapPixels) != ANDROID_BITMAP_RESUT_SUCCESS) { if (AndroidBitmap_lockPixels(env, outputBitmap, &bitmapPixels) != ANDROID_BITMAP_RESUT_SUCCESS) {
(*env)->ThrowNew(env, jclass_RuntimeException, "Failed to lock Bitmap pixels"); env->ThrowNew(jclass_RuntimeException, "Failed to lock Bitmap pixels");
return 0; return 0;
} }
if (!WebPDecodeRGBAInto((uint8_t*)inputBuffer, len, (uint8_t*)bitmapPixels, bitmapInfo.height * bitmapInfo.stride, bitmapInfo.stride)) { if (!WebPDecodeRGBAInto((uint8_t *) inputBuffer, len, (uint8_t *) bitmapPixels, bitmapInfo.height * bitmapInfo.stride, bitmapInfo.stride)) {
AndroidBitmap_unlockPixels(env, outputBitmap); AndroidBitmap_unlockPixels(env, outputBitmap);
(*env)->ThrowNew(env, jclass_RuntimeException, "Failed to decode webp image"); env->ThrowNew(jclass_RuntimeException, "Failed to decode webp image");
return 0; return 0;
} }
if (unpin && AndroidBitmap_unlockPixels(env, outputBitmap) != ANDROID_BITMAP_RESUT_SUCCESS) { if (unpin && AndroidBitmap_unlockPixels(env, outputBitmap) != ANDROID_BITMAP_RESUT_SUCCESS) {
(*env)->ThrowNew(env, jclass_RuntimeException, "Failed to unlock Bitmap pixels"); env->ThrowNew(jclass_RuntimeException, "Failed to unlock Bitmap pixels");
return 0; return 0;
} }
return 1; return 1;
} }
#define SQUARE(i) ((i)*(i)) #define SQUARE(i) ((i)*(i))
inline static void zeroClearInt(int* p, size_t count) { memset(p, 0, sizeof(int) * count); }
JNIEXPORT void Java_org_telegram_messenger_Utilities_stackBlurBitmap(JNIEnv* env, jclass class, jobject bitmap, jint radius) { inline static void zeroClearInt(int *p, size_t count) {
if (radius < 1) return; memset(p, 0, sizeof(int) * count);
}
void Java_org_telegram_messenger_Utilities_stackBlurBitmap(JNIEnv *env, jclass clazz, jobject bitmap, jint radius) {
if (radius < 1) {
return;
}
AndroidBitmapInfo info; AndroidBitmapInfo info;
if (AndroidBitmap_getInfo(env, bitmap, &info) != ANDROID_BITMAP_RESULT_SUCCESS) if (AndroidBitmap_getInfo(env, bitmap, &info) != ANDROID_BITMAP_RESULT_SUCCESS) {
return; return;
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) }
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
return; return;
}
int w = info.width; int w = info.width;
int h = info.height; int h = info.height;
@ -749,17 +741,17 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_stackBlurBitmap(JNIEnv* env
zeroClearInt(vmin, MAX(w, h)); zeroClearInt(vmin, MAX(w, h));
// Large buffers // Large buffers
int *r = malloc(wh * sizeof(int)); int *r = new int[wh];
int *g = malloc(wh * sizeof(int)); int *g = new int[wh];
int *b = malloc(wh * sizeof(int)); int *b = new int[wh];
int *a = malloc(wh * sizeof(int)); int *a = new int[wh];
zeroClearInt(r, wh); zeroClearInt(r, wh);
zeroClearInt(g, wh); zeroClearInt(g, wh);
zeroClearInt(b, wh); zeroClearInt(b, wh);
zeroClearInt(a, wh); zeroClearInt(a, wh);
const size_t dvcount = 256 * divsum; const size_t dvcount = 256 * divsum;
int *dv = malloc(sizeof(int) * dvcount); int *dv = new int[dvcount];
int i; int i;
for (i = 0; (size_t) i < dvcount; i++) { for (i = 0; (size_t) i < dvcount; i++) {
dv[i] = (i / divsum); dv[i] = (i / divsum);
@ -769,7 +761,7 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_stackBlurBitmap(JNIEnv* env
int x, y; int x, y;
int *sir; int *sir;
int routsum, goutsum, boutsum, aoutsum; int routsum, goutsum, boutsum, aoutsum;
int rinsum, ginsum, binsum, ainsum; int rinsum, ginsum, binsum, ainsum;
int rsum, gsum, bsum, asum, p, yp; int rsum, gsum, bsum, asum, p, yp;
int stackpointer; int stackpointer;
int stackstart; int stackstart;
@ -955,38 +947,38 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_stackBlurBitmap(JNIEnv* env
} }
} }
free(r); delete[] r;
free(g); delete[] g;
free(b); delete[] b;
free(a); delete[] a;
free(dv); delete[] dv;
AndroidBitmap_unlockPixels(env, bitmap); AndroidBitmap_unlockPixels(env, bitmap);
} }
JNIEXPORT void Java_org_telegram_messenger_Utilities_drawDitheredGradient(JNIEnv* env, jclass class, jobject bitmap, jintArray colors, jint startX, jint startY, jint endX, jint endY) { void Java_org_telegram_messenger_Utilities_drawDitheredGradient(JNIEnv *env, jclass clazz, jobject bitmap, jintArray colors, jint startX, jint startY, jint endX, jint endY) {
AndroidBitmapInfo info; AndroidBitmapInfo info;
void* pixelsBuffer; void *pixelsBuffer;
int reason; int reason;
if ((reason = AndroidBitmap_getInfo(env, bitmap, &info)) != ANDROID_BITMAP_RESULT_SUCCESS) { if ((reason = AndroidBitmap_getInfo(env, bitmap, &info)) != ANDROID_BITMAP_RESULT_SUCCESS) {
(*env)->ThrowNew(env, jclass_RuntimeException, "AndroidBitmap_getInfo failed with a reason: " + reason); env->ThrowNew(jclass_RuntimeException, "AndroidBitmap_getInfo failed with a reason: " + reason);
return; return;
} }
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
(*env)->ThrowNew(env, jclass_RuntimeException, "Bitmap must be in ARGB_8888 format"); env->ThrowNew(jclass_RuntimeException, "Bitmap must be in ARGB_8888 format");
return; return;
} }
if ((reason = AndroidBitmap_lockPixels(env, bitmap, &pixelsBuffer)) != ANDROID_BITMAP_RESULT_SUCCESS) { if ((reason = AndroidBitmap_lockPixels(env, bitmap, &pixelsBuffer)) != ANDROID_BITMAP_RESULT_SUCCESS) {
(*env)->ThrowNew(env, jclass_RuntimeException, "AndroidBitmap_lockPixels failed with a reason: " + reason); env->ThrowNew(jclass_RuntimeException, "AndroidBitmap_lockPixels failed with a reason: " + reason);
return; return;
} }
uint8_t i, j, n; uint8_t i, j, n;
// gradient colors extracting // gradient colors extracting
jint *colorsBuffer = (*env)->GetIntArrayElements(env, colors, 0); jint *colorsBuffer = env->GetIntArrayElements(colors, 0);
uint8_t *colorsComponents = (uint8_t *) colorsBuffer; uint8_t *colorsComponents = (uint8_t *) colorsBuffer;
float colorsF[4][2]; float colorsF[4][2];
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
@ -996,7 +988,7 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_drawDitheredGradient(JNIEnv
colorsF[n][j] = colorsComponents[j * 4 + i] / 255.F; colorsF[n][j] = colorsComponents[j * 4 + i] / 255.F;
} }
} }
(*env)->ReleaseIntArrayElements(env, colors, colorsBuffer, JNI_ABORT); env->ReleaseIntArrayElements(colors, colorsBuffer, JNI_ABORT);
// gradient vector // gradient vector
const int32_t vx = endX - startX; const int32_t vx = endX - startX;
@ -1004,9 +996,10 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_drawDitheredGradient(JNIEnv
const float vSquaredMag = vx * vx + vy * vy; const float vSquaredMag = vx * vx + vy * vy;
float noise, fraction, error, componentF; float noise, fraction, error, componentF;
float *pixelsComponentsF = malloc(info.height * info.stride * 4 * sizeof(float)); float *pixelsComponentsF = new float[info.height * info.stride * 4];
memset(pixelsComponentsF, 0, info.height * info.stride * 4 * sizeof(float)); memset(pixelsComponentsF, 0, info.height * info.stride * 4 * sizeof(float));
uint8_t *bitmapPixelsComponents = (uint8_t *) pixelsBuffer; uint8_t * bitmapPixelsComponents = (uint8_t * )
pixelsBuffer;
int32_t x, y; int32_t x, y;
int32_t offset; int32_t offset;
@ -1036,7 +1029,8 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_drawDitheredGradient(JNIEnv
// draw // draw
componentF = roundf(pixelsComponentsF[position] * 255.F); componentF = roundf(pixelsComponentsF[position] * 255.F);
bitmapPixelsComponents[position] = (uint8_t) componentF; bitmapPixelsComponents[position] = (uint8_t)
componentF;
// floyd-steinberg dithering // floyd-steinberg dithering
error = pixelsComponentsF[position] - componentF / 255.F; error = pixelsComponentsF[position] - componentF / 255.F;
@ -1056,10 +1050,12 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_drawDitheredGradient(JNIEnv
} }
} }
free(pixelsComponentsF); delete[] pixelsComponentsF;
if ((reason = AndroidBitmap_unlockPixels(env, bitmap)) != ANDROID_BITMAP_RESULT_SUCCESS) { if ((reason = AndroidBitmap_unlockPixels(env, bitmap)) != ANDROID_BITMAP_RESULT_SUCCESS) {
(*env)->ThrowNew(env, jclass_RuntimeException, "AndroidBitmap_unlockPixels failed with a reason: " + reason); env->ThrowNew(jclass_RuntimeException, "AndroidBitmap_unlockPixels failed with a reason: " + reason);
return; return;
} }
}
} }

View File

@ -1,8 +0,0 @@
#ifndef image_h
#define image_h
#include <jni.h>
jint imageOnJNILoad(JavaVM *vm, JNIEnv *env);
#endif

View File

@ -10,11 +10,11 @@
#include <dirent.h> #include <dirent.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <libtgvoip/client/android/org_telegram_messenger_voip_TgVoip.h> #include <libtgvoip/client/android/org_telegram_messenger_voip_TgVoip.h>
#include "image.h"
#include "libtgvoip/client/android/tg_voip_jni.h" #include "libtgvoip/client/android/tg_voip_jni.h"
int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env); int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env);
int videoOnJNILoad(JavaVM *vm, JNIEnv *env); int videoOnJNILoad(JavaVM *vm, JNIEnv *env);
int imageOnJNILoad(JavaVM *vm, JNIEnv *env);
//int tonLibOnLoad(JavaVM *vm, JNIEnv *env); //int tonLibOnLoad(JavaVM *vm, JNIEnv *env);
jint JNI_OnLoad(JavaVM *vm, void *reserved) { jint JNI_OnLoad(JavaVM *vm, void *reserved) {

View File

@ -535,6 +535,9 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel)
{ {
// 1. create layer item // 1. create layer item
for (auto &i : mLayerData->mChildren) { for (auto &i : mLayerData->mChildren) {
if (i->type() != LOTData::Type::Layer) {
continue;
}
LOTLayerData *layerModel = static_cast<LOTLayerData *>(i.get()); LOTLayerData *layerModel = static_cast<LOTLayerData *>(i.get());
auto layerItem = LOTCompItem::createLayerItem(layerModel); auto layerItem = LOTCompItem::createLayerItem(layerModel);
if (layerItem) mLayers.push_back(std::move(layerItem)); if (layerItem) mLayers.push_back(std::move(layerItem));

View File

@ -201,10 +201,13 @@ void LOTGradient::populate(VGradientStops &stops, int frameNo)
int size = gradData.mGradient.size(); int size = gradData.mGradient.size();
float * ptr = gradData.mGradient.data(); float * ptr = gradData.mGradient.data();
int colorPoints = mColorPoints; int colorPoints = mColorPoints;
if (colorPoints == -1) { // for legacy bodymovin (ref: lottie-android) if (colorPoints < 0 || colorPoints * 4 > size) { // for legacy bodymovin (ref: lottie-android)
colorPoints = size / 4; colorPoints = size / 4;
} }
int opacityArraySize = size - colorPoints * 4; int opacityArraySize = size - colorPoints * 4;
if (opacityArraySize % 2 != 0 || colorPoints > opacityArraySize / 2 && opacityArraySize < 4) {
opacityArraySize = 0;
}
float *opacityPtr = ptr + (colorPoints * 4); float *opacityPtr = ptr + (colorPoints * 4);
stops.clear(); stops.clear();
int j = 0; int j = 0;
@ -257,6 +260,9 @@ void LOTGradient::populate(VGradientStops &stops, int frameNo)
stops.push_back(std::make_pair(colorStop, color.toColor())); stops.push_back(std::make_pair(colorStop, color.toColor()));
} }
ptr += 4; ptr += 4;
if (stops.empty()) {
stops.push_back(std::make_pair(0.0f, VColor(255, 255, 255, 255)));
}
} }
} }

View File

@ -155,7 +155,7 @@ bool VGradientCache::generateGradientColorTable(const VGradientStops &stops,
colorTable[pos++] = curColor; colorTable[pos++] = curColor;
while (fpos <= curr->first) { while (fpos <= curr->first && pos < size) {
colorTable[pos] = colorTable[pos - 1]; colorTable[pos] = colorTable[pos - 1];
pos++; pos++;
fpos += incr; fpos += incr;

View File

@ -125,6 +125,10 @@ ConnectionsManager::~ConnectionsManager() {
close(epolFd); close(epolFd);
epolFd = 0; epolFd = 0;
} }
if (pipeFd != nullptr) {
delete[] pipeFd;
pipeFd = nullptr;
}
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
} }
@ -1664,6 +1668,7 @@ void ConnectionsManager::initDatacenters() {
if (datacenters.find(2) == datacenters.end()) { if (datacenters.find(2) == datacenters.end()) {
datacenter = new Datacenter(instanceNum, 2); datacenter = new Datacenter(instanceNum, 2);
datacenter->addAddressAndPort("149.154.167.51", 443, 0, ""); datacenter->addAddressAndPort("149.154.167.51", 443, 0, "");
datacenter->addAddressAndPort("95.161.76.100", 443, 0, "");
datacenter->addAddressAndPort("2001:67c:4e8:f002:0000:0000:0000:000a", 443, 1, ""); datacenter->addAddressAndPort("2001:67c:4e8:f002:0000:0000:0000:000a", 443, 1, "");
datacenters[2] = datacenter; datacenters[2] = datacenter;
} }
@ -2328,8 +2333,6 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
if (genericConnection != nullptr && !sessionsToDestroy.empty() && genericConnection->getConnectionToken() != 0) { if (genericConnection != nullptr && !sessionsToDestroy.empty() && genericConnection->getConnectionToken() != 0) {
std::vector<int64_t>::iterator iter = sessionsToDestroy.begin(); std::vector<int64_t>::iterator iter = sessionsToDestroy.begin();
sessionsToDestroy.erase(iter);
if (abs(currentTime - lastDestroySessionRequestTime) > 2) { if (abs(currentTime - lastDestroySessionRequestTime) > 2) {
lastDestroySessionRequestTime = currentTime; lastDestroySessionRequestTime = currentTime;
TL_destroy_session *request = new TL_destroy_session(); TL_destroy_session *request = new TL_destroy_session();
@ -2343,6 +2346,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t
networkMessage->message->seqno = genericConnection->generateMessageSeqNo(false); networkMessage->message->seqno = genericConnection->generateMessageSeqNo(false);
addMessageToDatacenter(defaultDatacenter->getDatacenterId(), networkMessage, genericMessagesToDatacenters); addMessageToDatacenter(defaultDatacenter->getDatacenterId(), networkMessage, genericMessagesToDatacenters);
} }
sessionsToDestroy.erase(iter);
} }
} }

View File

@ -201,7 +201,7 @@ private:
std::vector<ConnectionSocket *> activeConnectionsCopy; std::vector<ConnectionSocket *> activeConnectionsCopy;
int epolFd; int epolFd;
int eventFd; int eventFd;
int *pipeFd; int *pipeFd = nullptr;
NativeByteBuffer *networkBuffer; NativeByteBuffer *networkBuffer;
requestsList requestsQueue; requestsList requestsQueue;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -20,6 +20,8 @@ import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import org.telegram.messenger.BuildVars;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -33,9 +35,9 @@ import java.util.List;
* When RecyclerView needs direct access to the view group children, it can call unfiltered * When RecyclerView needs direct access to the view group children, it can call unfiltered
* methods like get getUnfilteredChildCount or getUnfilteredChildAt. * methods like get getUnfilteredChildCount or getUnfilteredChildAt.
*/ */
class ChildHelper { public class ChildHelper {
private static final boolean DEBUG = false; private static final boolean DEBUG = BuildVars.DEBUG_VERSION;
private static final String TAG = "ChildrenHelper"; private static final String TAG = "ChildrenHelper";
@ -56,7 +58,7 @@ class ChildHelper {
* *
* @param child View to hide. * @param child View to hide.
*/ */
private void hideViewInternal(View child) { public void hideViewInternal(View child) {
mHiddenViews.add(child); mHiddenViews.add(child);
mCallback.onEnteredHiddenState(child); mCallback.onEnteredHiddenState(child);
} }
@ -66,7 +68,7 @@ class ChildHelper {
* *
* @param child View to hide. * @param child View to hide.
*/ */
private boolean unhideViewInternal(View child) { public boolean unhideViewInternal(View child) {
if (mHiddenViews.remove(child)) { if (mHiddenViews.remove(child)) {
mCallback.onLeftHiddenState(child); mCallback.onLeftHiddenState(child);
return true; return true;
@ -75,7 +77,7 @@ class ChildHelper {
} }
} }
protected int getHiddenChildCount() { public int getHiddenChildCount() {
return mHiddenViews.size(); return mHiddenViews.size();
} }
@ -260,7 +262,7 @@ class ChildHelper {
* @return Number of children that are not hidden. * @return Number of children that are not hidden.
* @see #getChildAt(int) * @see #getChildAt(int)
*/ */
int getChildCount() { public int getChildCount() {
return mCallback.getChildCount() - mHiddenViews.size(); return mCallback.getChildCount() - mHiddenViews.size();
} }

View File

@ -22,11 +22,15 @@ import android.animation.ValueAnimator;
import android.os.Build; import android.os.Build;
import android.view.View; import android.view.View;
import android.view.ViewPropertyAnimator; import android.view.ViewPropertyAnimator;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import org.telegram.messenger.BuildVars;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
/** /**
@ -37,14 +41,15 @@ import java.util.List;
* @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator) * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator)
*/ */
public class DefaultItemAnimator extends SimpleItemAnimator { public class DefaultItemAnimator extends SimpleItemAnimator {
private static final boolean DEBUG = false; private static final boolean DEBUG = BuildVars.DEBUG_VERSION;
private static TimeInterpolator sDefaultInterpolator; private static TimeInterpolator sDefaultInterpolator;
protected Interpolator translationInterpolator;
private ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>(); protected ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>(); protected ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>(); protected ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>(); protected ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();
ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>(); ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>();
ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>(); ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
@ -55,9 +60,9 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>(); ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>();
ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList<>(); ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList<>();
private boolean delayAnimations = true; protected boolean delayAnimations = true;
private static class MoveInfo { protected static class MoveInfo {
public RecyclerView.ViewHolder holder; public RecyclerView.ViewHolder holder;
public int fromX, fromY, toX, toY; public int fromX, fromY, toX, toY;
@ -70,7 +75,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
} }
} }
private static class ChangeInfo { protected static class ChangeInfo {
public RecyclerView.ViewHolder oldHolder, newHolder; public RecyclerView.ViewHolder oldHolder, newHolder;
public int fromX, fromY, toX, toY; public int fromX, fromY, toX, toY;
private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) { private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
@ -125,8 +130,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
@Override @Override
public void run() { public void run() {
for (MoveInfo moveInfo : moves) { for (MoveInfo moveInfo : moves) {
animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY, animateMoveImpl(moveInfo.holder, moveInfo);
moveInfo.toX, moveInfo.toY);
} }
moves.clear(); moves.clear();
mMovesList.remove(moves); mMovesList.remove(moves);
@ -134,7 +138,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
}; };
if (delayAnimations && removalsPending) { if (delayAnimations && removalsPending) {
View view = moves.get(0).holder.itemView; View view = moves.get(0).holder.itemView;
ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration()); ViewCompat.postOnAnimationDelayed(view, mover, getMoveAnimationDelay());
} else { } else {
mover.run(); mover.run();
} }
@ -191,8 +195,12 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
} }
} }
protected long getMoveAnimationDelay() {
return getRemoveDuration();
}
@Override @Override
public boolean animateRemove(final RecyclerView.ViewHolder holder) { public boolean animateRemove(final RecyclerView.ViewHolder holder, ItemHolderInfo info) {
resetAnimation(holder); resetAnimation(holder);
mPendingRemovals.add(holder); mPendingRemovals.add(holder);
return true; return true;
@ -202,7 +210,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
delayAnimations = value; delayAnimations = value;
} }
private void animateRemoveImpl(final RecyclerView.ViewHolder holder) { protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView; final View view = holder.itemView;
final ViewPropertyAnimator animation = view.animate(); final ViewPropertyAnimator animation = view.animate();
mRemoveAnimations.add(holder); mRemoveAnimations.add(holder);
@ -217,6 +225,8 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
public void onAnimationEnd(Animator animator) { public void onAnimationEnd(Animator animator) {
animation.setListener(null); animation.setListener(null);
view.setAlpha(1); view.setAlpha(1);
view.setTranslationX(0);
view.setTranslationY(0);
dispatchRemoveFinished(holder); dispatchRemoveFinished(holder);
mRemoveAnimations.remove(holder); mRemoveAnimations.remove(holder);
dispatchFinishedWhenDone(); dispatchFinishedWhenDone();
@ -232,7 +242,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
return true; return true;
} }
void animateAddImpl(final RecyclerView.ViewHolder holder) { public void animateAddImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView; final View view = holder.itemView;
final ViewPropertyAnimator animation = view.animate(); final ViewPropertyAnimator animation = view.animate();
mAddAnimations.add(holder); mAddAnimations.add(holder);
@ -259,7 +269,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
} }
@Override @Override
public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY, public boolean animateMove(final RecyclerView.ViewHolder holder, ItemHolderInfo info, int fromX, int fromY,
int toX, int toY) { int toX, int toY) {
final View view = holder.itemView; final View view = holder.itemView;
fromX += (int) holder.itemView.getTranslationX(); fromX += (int) holder.itemView.getTranslationX();
@ -285,7 +295,11 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
} }
void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) { void animateMoveImpl(final RecyclerView.ViewHolder holder, MoveInfo moveInfo) {
int fromX = moveInfo.fromX;
int fromY = moveInfo.fromY;
int toX = moveInfo.toX;
int toY = moveInfo.toY;
final View view = holder.itemView; final View view = holder.itemView;
final int deltaX = toX - fromX; final int deltaX = toX - fromX;
final int deltaY = toY - fromY; final int deltaY = toY - fromY;
@ -303,6 +317,9 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
if (Build.VERSION.SDK_INT >= 19) { if (Build.VERSION.SDK_INT >= 19) {
animation.setUpdateListener(animation1 -> onMoveAnimationUpdate(holder)); animation.setUpdateListener(animation1 -> onMoveAnimationUpdate(holder));
} }
if (translationInterpolator != null) {
animation.setInterpolator(translationInterpolator);
}
animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() { animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationStart(Animator animator) { public void onAnimationStart(Animator animator) {
@ -330,12 +347,12 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
} }
@Override @Override
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, ItemHolderInfo info,
int fromX, int fromY, int toX, int toY) { int fromX, int fromY, int toX, int toY) {
if (oldHolder == newHolder) { if (oldHolder == newHolder) {
// Don't know how to run change animations when the same view holder is re-used. // Don't know how to run change animations when the same view holder is re-used.
// run a move animation to handle position changes. // run a move animation to handle position changes.
return animateMove(oldHolder, fromX, fromY, toX, toY); return animateMove(oldHolder,info, fromX, fromY, toX, toY);
} }
final float prevTranslationX = oldHolder.itemView.getTranslationX(); final float prevTranslationX = oldHolder.itemView.getTranslationX();
final float prevTranslationY = oldHolder.itemView.getTranslationY(); final float prevTranslationY = oldHolder.itemView.getTranslationY();
@ -421,7 +438,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
} }
} }
private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) { protected void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
if (changeInfo.oldHolder != null) { if (changeInfo.oldHolder != null) {
endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder); endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
} }
@ -429,7 +446,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder); endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
} }
} }
private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) { protected boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, RecyclerView.ViewHolder item) {
boolean oldItem = false; boolean oldItem = false;
if (changeInfo.newHolder == item) { if (changeInfo.newHolder == item) {
changeInfo.newHolder = null; changeInfo.newHolder = null;
@ -507,32 +524,32 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
// animations should be ended by the cancel above. // animations should be ended by the cancel above.
//noinspection PointlessBooleanExpression,ConstantConditions //noinspection PointlessBooleanExpression,ConstantConditions
if (mRemoveAnimations.remove(item) && DEBUG) { if (mRemoveAnimations.remove(item) && BuildVars.DEBUG_VERSION) {
throw new IllegalStateException("after animation is cancelled, item should not be in " throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mRemoveAnimations list"); + "mRemoveAnimations list");
} }
//noinspection PointlessBooleanExpression,ConstantConditions //noinspection PointlessBooleanExpression,ConstantConditions
if (mAddAnimations.remove(item) && DEBUG) { if (mAddAnimations.remove(item) && BuildVars.DEBUG_VERSION) {
throw new IllegalStateException("after animation is cancelled, item should not be in " throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mAddAnimations list"); + "mAddAnimations list");
} }
//noinspection PointlessBooleanExpression,ConstantConditions //noinspection PointlessBooleanExpression,ConstantConditions
if (mChangeAnimations.remove(item) && DEBUG) { if (mChangeAnimations.remove(item) && BuildVars.DEBUG_VERSION) {
throw new IllegalStateException("after animation is cancelled, item should not be in " throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mChangeAnimations list"); + "mChangeAnimations list");
} }
//noinspection PointlessBooleanExpression,ConstantConditions //noinspection PointlessBooleanExpression,ConstantConditions
if (mMoveAnimations.remove(item) && DEBUG) { if (mMoveAnimations.remove(item) && BuildVars.DEBUG_VERSION) {
throw new IllegalStateException("after animation is cancelled, item should not be in " throw new IllegalStateException("after animation is cancelled, item should not be in "
+ "mMoveAnimations list"); + "mMoveAnimations list");
} }
dispatchFinishedWhenDone(); dispatchFinishedWhenDone();
} }
private void resetAnimation(RecyclerView.ViewHolder holder) { public void resetAnimation(RecyclerView.ViewHolder holder) {
if (sDefaultInterpolator == null) { if (sDefaultInterpolator == null) {
sDefaultInterpolator = new ValueAnimator().getInterpolator(); sDefaultInterpolator = new ValueAnimator().getInterpolator();
} }
@ -560,7 +577,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator {
* pending/running, call {@link #dispatchAnimationsFinished()} to notify any * pending/running, call {@link #dispatchAnimationsFinished()} to notify any
* listeners. * listeners.
*/ */
void dispatchFinishedWhenDone() { protected void dispatchFinishedWhenDone() {
if (!isRunning()) { if (!isRunning()) {
dispatchAnimationsFinished(); dispatchAnimationsFinished();
onAllAnimationsDone(); onAllAnimationsDone();

View File

@ -34,6 +34,8 @@ import androidx.annotation.RestrictTo;
import androidx.core.os.TraceCompat; import androidx.core.os.TraceCompat;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import org.telegram.messenger.BuildVars;
import java.util.List; import java.util.List;
/** /**
@ -45,7 +47,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements
private static final String TAG = "LinearLayoutManager"; private static final String TAG = "LinearLayoutManager";
static final boolean DEBUG = false; static final boolean DEBUG = BuildVars.DEBUG_VERSION;
public static final int HORIZONTAL = RecyclerView.HORIZONTAL; public static final int HORIZONTAL = RecyclerView.HORIZONTAL;

View File

@ -23,6 +23,8 @@ import android.view.View;
import android.view.animation.DecelerateInterpolator; import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator; import android.view.animation.LinearInterpolator;
import org.telegram.messenger.BuildVars;
/** /**
* {@link RecyclerView.SmoothScroller} implementation which uses a {@link LinearInterpolator} until * {@link RecyclerView.SmoothScroller} implementation which uses a {@link LinearInterpolator} until
* the target position becomes a child of the RecyclerView and then uses a * the target position becomes a child of the RecyclerView and then uses a
@ -35,7 +37,7 @@ import android.view.animation.LinearInterpolator;
*/ */
public class LinearSmoothScroller extends RecyclerView.SmoothScroller { public class LinearSmoothScroller extends RecyclerView.SmoothScroller {
private static final boolean DEBUG = false; private static final boolean DEBUG = BuildVars.DEBUG_VERSION;
private static final float MILLISECONDS_PER_INCH = 25f; private static final float MILLISECONDS_PER_INCH = 25f;

View File

@ -59,6 +59,8 @@ import android.widget.LinearLayout;
import android.widget.OverScroller; import android.widget.OverScroller;
import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BuildConfig;
import org.telegram.messenger.BuildVars;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
@ -212,7 +214,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
static final String TAG = "RecyclerView"; static final String TAG = "RecyclerView";
static final boolean DEBUG = false; static final boolean DEBUG = BuildVars.DEBUG_VERSION;
static final boolean VERBOSE_TRACING = false; static final boolean VERBOSE_TRACING = false;
@ -363,7 +365,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver(); private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
final Recycler mRecycler = new Recycler(); public final Recycler mRecycler = new Recycler();
private SavedState mPendingSavedState; private SavedState mPendingSavedState;
@ -375,7 +377,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
/** /**
* Handles abstraction between LayoutManager children and RecyclerView children * Handles abstraction between LayoutManager children and RecyclerView children
*/ */
ChildHelper mChildHelper; public ChildHelper mChildHelper;
/** /**
* Keeps data about views to be used for animations * Keeps data about views to be used for animations
@ -11294,7 +11296,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView,
mIsRecyclableCount = recyclable ? mIsRecyclableCount - 1 : mIsRecyclableCount + 1; mIsRecyclableCount = recyclable ? mIsRecyclableCount - 1 : mIsRecyclableCount + 1;
if (mIsRecyclableCount < 0) { if (mIsRecyclableCount < 0) {
mIsRecyclableCount = 0; mIsRecyclableCount = 0;
if (DEBUG) { if (BuildVars.DEBUG_VERSION) {
throw new RuntimeException("isRecyclable decremented below 0: " throw new RuntimeException("isRecyclable decremented below 0: "
+ "unmatched pair of setIsRecyable() calls for " + this); + "unmatched pair of setIsRecyable() calls for " + this);
} }

View File

@ -55,14 +55,14 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* If you set this property to false, actions on the data set which change the * If you set this property to false, actions on the data set which change the
* contents of items will not be animated. What those animations do is left * contents of items will not be animated. What those animations do is left
* up to the discretion of the ItemAnimator subclass, in its * up to the discretion of the ItemAnimator subclass, in its
* {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} implementation. * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int)} implementation.
* The value of this property is true by default. * The value of this property is true by default.
* *
* @param supportsChangeAnimations true if change animations are supported by * @param supportsChangeAnimations true if change animations are supported by
* this ItemAnimator, false otherwise. If the property is false, * this ItemAnimator, false otherwise. If the property is false,
* the ItemAnimator * the ItemAnimator
* will not receive a call to * will not receive a call to
* {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int,
* int)} when changes occur. * int)} when changes occur.
* @see RecyclerView.Adapter#notifyItemChanged(int) * @see RecyclerView.Adapter#notifyItemChanged(int)
* @see RecyclerView.Adapter#notifyItemRangeChanged(int, int) * @see RecyclerView.Adapter#notifyItemRangeChanged(int, int)
@ -99,15 +99,17 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "DISAPPEARING: " + viewHolder + " with view " + disappearingItemView); Log.d(TAG, "DISAPPEARING: " + viewHolder + " with view " + disappearingItemView);
} }
return animateMove(viewHolder, oldLeft, oldTop, newLeft, newTop); return animateMove(viewHolder, preLayoutInfo, oldLeft, oldTop, newLeft, newTop);
} else { } else {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "REMOVED: " + viewHolder + " with view " + disappearingItemView); Log.d(TAG, "REMOVED: " + viewHolder + " with view " + disappearingItemView);
} }
return animateRemove(viewHolder); return animateRemove(viewHolder, preLayoutInfo);
} }
} }
@Override @Override
public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder,
@Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) { @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
@ -117,7 +119,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "APPEARING: " + viewHolder + " with view " + viewHolder); Log.d(TAG, "APPEARING: " + viewHolder + " with view " + viewHolder);
} }
return animateMove(viewHolder, preLayoutInfo.left, preLayoutInfo.top, return animateMove(viewHolder,preLayoutInfo, preLayoutInfo.left, preLayoutInfo.top,
postLayoutInfo.left, postLayoutInfo.top); postLayoutInfo.left, postLayoutInfo.top);
} else { } else {
if (DEBUG) { if (DEBUG) {
@ -135,7 +137,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
Log.d(TAG, "PERSISTENT: " + viewHolder Log.d(TAG, "PERSISTENT: " + viewHolder
+ " with view " + viewHolder.itemView); + " with view " + viewHolder.itemView);
} }
return animateMove(viewHolder, return animateMove(viewHolder, preInfo,
preInfo.left, preInfo.top, postInfo.left, postInfo.top); preInfo.left, preInfo.top, postInfo.left, postInfo.top);
} }
dispatchMoveFinished(viewHolder); dispatchMoveFinished(viewHolder);
@ -158,7 +160,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
toLeft = postInfo.left; toLeft = postInfo.left;
toTop = postInfo.top; toTop = postInfo.top;
} }
return animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft, toTop); return animateChange(oldHolder, newHolder, preInfo, fromLeft, fromTop, toLeft, toTop);
} }
/** /**
@ -170,9 +172,9 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* ItemAnimator's {@link #runPendingAnimations()} method should be called at the * ItemAnimator's {@link #runPendingAnimations()} method should be called at the
* next opportunity. This mechanism allows ItemAnimator to set up individual animations * next opportunity. This mechanism allows ItemAnimator to set up individual animations
* as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()}, * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()},
* {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()}, * {@link #animateMove(RecyclerView.ViewHolder,RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int) animateMove()},
* {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and * {@link #animateRemove(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo) animateRemove()}, and
* {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one, * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int)} come in one by one,
* then start the animations together in the later call to {@link #runPendingAnimations()}. * then start the animations together in the later call to {@link #runPendingAnimations()}.
* *
* <p>This method may also be called for disappearing items which continue to exist in the * <p>This method may also be called for disappearing items which continue to exist in the
@ -184,7 +186,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* @return true if a later call to {@link #runPendingAnimations()} is requested, * @return true if a later call to {@link #runPendingAnimations()} is requested,
* false otherwise. * false otherwise.
*/ */
public abstract boolean animateRemove(RecyclerView.ViewHolder holder); public abstract boolean animateRemove(RecyclerView.ViewHolder holder, ItemHolderInfo info);
/** /**
* Called when an item is added to the RecyclerView. Implementors can choose * Called when an item is added to the RecyclerView. Implementors can choose
@ -195,9 +197,9 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* ItemAnimator's {@link #runPendingAnimations()} method should be called at the * ItemAnimator's {@link #runPendingAnimations()} method should be called at the
* next opportunity. This mechanism allows ItemAnimator to set up individual animations * next opportunity. This mechanism allows ItemAnimator to set up individual animations
* as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()}, * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()},
* {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()}, * {@link #animateMove(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int) animateMove()},
* {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and * {@link #animateRemove(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo) animateRemove()}, and
* {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one, * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int)} come in one by one,
* then start the animations together in the later call to {@link #runPendingAnimations()}. * then start the animations together in the later call to {@link #runPendingAnimations()}.
* *
* <p>This method may also be called for appearing items which were already in the * <p>This method may also be called for appearing items which were already in the
@ -220,16 +222,16 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* ItemAnimator's {@link #runPendingAnimations()} method should be called at the * ItemAnimator's {@link #runPendingAnimations()} method should be called at the
* next opportunity. This mechanism allows ItemAnimator to set up individual animations * next opportunity. This mechanism allows ItemAnimator to set up individual animations
* as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()}, * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()},
* {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()}, * {@link #animateMove(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int) animateMove()},
* {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and * {@link #animateRemove(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo) animateRemove()}, and
* {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one, * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int)} come in one by one,
* then start the animations together in the later call to {@link #runPendingAnimations()}. * then start the animations together in the later call to {@link #runPendingAnimations()}.
* *
* @param holder The item that is being moved. * @param holder The item that is being moved.
* @return true if a later call to {@link #runPendingAnimations()} is requested, * @return true if a later call to {@link #runPendingAnimations()} is requested,
* false otherwise. * false otherwise.
*/ */
public abstract boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, public abstract boolean animateMove(RecyclerView.ViewHolder holder, ItemHolderInfo info, int fromX, int fromY,
int toX, int toY); int toX, int toY);
/** /**
@ -248,9 +250,9 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* ItemAnimator's {@link #runPendingAnimations()} method should be called at the * ItemAnimator's {@link #runPendingAnimations()} method should be called at the
* next opportunity. This mechanism allows ItemAnimator to set up individual animations * next opportunity. This mechanism allows ItemAnimator to set up individual animations
* as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()}, * as separate calls to {@link #animateAdd(RecyclerView.ViewHolder) animateAdd()},
* {@link #animateMove(RecyclerView.ViewHolder, int, int, int, int) animateMove()}, * {@link #animateMove(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int) animateMove()},
* {@link #animateRemove(RecyclerView.ViewHolder) animateRemove()}, and * {@link #animateRemove(RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo) animateRemove()}, and
* {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)} come in one by one, * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder,RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int)} come in one by one,
* then start the animations together in the later call to {@link #runPendingAnimations()}. * then start the animations together in the later call to {@link #runPendingAnimations()}.
* *
* @param oldHolder The original item that changed. * @param oldHolder The original item that changed.
@ -263,7 +265,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* false otherwise. * false otherwise.
*/ */
public abstract boolean animateChange(RecyclerView.ViewHolder oldHolder, public abstract boolean animateChange(RecyclerView.ViewHolder oldHolder,
RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop); RecyclerView.ViewHolder newHolder, ItemHolderInfo info, int fromLeft, int fromTop, int toLeft, int toTop);
/** /**
* Method to be called by subclasses when a remove animation is done. * Method to be called by subclasses when a remove animation is done.
@ -307,10 +309,10 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* *
* @param item The item which has been changed (this method must be called for * @param item The item which has been changed (this method must be called for
* each non-null ViewHolder passed into * each non-null ViewHolder passed into
* {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}). * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int)}).
* @param oldItem true if this is the old item that was changed, false if * @param oldItem true if this is the old item that was changed, false if
* it is the new item that replaced the old item. * it is the new item that replaced the old item.
* @see #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int) * @see #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int)
*/ */
public final void dispatchChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) { public final void dispatchChangeFinished(RecyclerView.ViewHolder item, boolean oldItem) {
onChangeFinished(item, oldItem); onChangeFinished(item, oldItem);
@ -349,7 +351,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
* *
* @param item The item which has been changed (this method must be called for * @param item The item which has been changed (this method must be called for
* each non-null ViewHolder passed into * each non-null ViewHolder passed into
* {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, int, int, int, int)}). * {@link #animateChange(RecyclerView.ViewHolder, RecyclerView.ViewHolder, RecyclerView.ItemAnimator.ItemHolderInfo, int, int, int, int)}).
* @param oldItem true if this is the old item that was changed, false if * @param oldItem true if this is the old item that was changed, false if
* it is the new item that replaced the old item. * it is the new item that replaced the old item.
*/ */

View File

@ -15,6 +15,8 @@
*/ */
package androidx.recyclerview.widget; package androidx.recyclerview.widget;
import org.telegram.messenger.BuildVars;
import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR; import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR;
import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR_AND_DISAPPEAR; import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR_AND_DISAPPEAR;
import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR_PRE_AND_POST; import static androidx.recyclerview.widget.ViewInfoStore.InfoRecord.FLAG_APPEAR_PRE_AND_POST;
@ -36,6 +38,8 @@ class ViewInfoStore {
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
private boolean processing;
/** /**
* View data records for pre-layout * View data records for pre-layout
*/ */
@ -113,6 +117,12 @@ class ViewInfoStore {
} }
// if not pre-post flag is left, clear. // if not pre-post flag is left, clear.
if ((record.flags & (FLAG_PRE | FLAG_POST)) == 0) { if ((record.flags & (FLAG_PRE | FLAG_POST)) == 0) {
if (processing) {
if (BuildVars.DEBUG_VERSION) {
throw new RuntimeException("popFromLayoutStep while processing");
}
return null;
}
mLayoutHolderMap.removeAt(index); mLayoutHolderMap.removeAt(index);
InfoRecord.recycle(record); InfoRecord.recycle(record);
} }
@ -214,6 +224,7 @@ class ViewInfoStore {
} }
void process(ProcessCallback callback) { void process(ProcessCallback callback) {
processing = true;
for (int index = mLayoutHolderMap.size() - 1; index >= 0; index--) { for (int index = mLayoutHolderMap.size() - 1; index >= 0; index--) {
final RecyclerView.ViewHolder viewHolder = mLayoutHolderMap.keyAt(index); final RecyclerView.ViewHolder viewHolder = mLayoutHolderMap.keyAt(index);
final InfoRecord record = mLayoutHolderMap.removeAt(index); final InfoRecord record = mLayoutHolderMap.removeAt(index);
@ -248,6 +259,7 @@ class ViewInfoStore {
} }
InfoRecord.recycle(record); InfoRecord.recycle(record);
} }
processing = false;
} }
/** /**
@ -261,8 +273,15 @@ class ViewInfoStore {
break; break;
} }
} }
final InfoRecord info = mLayoutHolderMap.remove(holder); final InfoRecord info = mLayoutHolderMap.get(holder);
if (info != null) { if (info != null) {
if (processing) {
if (BuildVars.DEBUG_VERSION) {
throw new RuntimeException("removeViewHolder while processing");
}
return;
}
mLayoutHolderMap.remove(holder);
InfoRecord.recycle(info); InfoRecord.recycle(info);
} }
} }

View File

@ -1239,19 +1239,6 @@ public static class VcardItem {
return false; return false;
} }
public static boolean isKeyboardShowed(View view) {
if (view == null) {
return false;
}
try {
InputMethodManager inputManager = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return inputManager.isActive(view);
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
public static String[] getCurrentKeyboardLanguage() { public static String[] getCurrentKeyboardLanguage() {
try { try {
InputMethodManager inputManager = (InputMethodManager) ApplicationLoader.applicationContext.getSystemService(Context.INPUT_METHOD_SERVICE); InputMethodManager inputManager = (InputMethodManager) ApplicationLoader.applicationContext.getSystemService(Context.INPUT_METHOD_SERVICE);
@ -1900,7 +1887,7 @@ public static class LinkMovementMethodMy extends LinkMovementMethod {
return; return;
} }
AnimatorSet animatorSet = new AnimatorSet(); AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(ObjectAnimator.ofFloat(view, "translationX", AndroidUtilities.dp(x))); animatorSet.playTogether(ObjectAnimator.ofFloat(view, "translationX", dp(x)));
animatorSet.setDuration(50); animatorSet.setDuration(50);
animatorSet.addListener(new AnimatorListenerAdapter() { animatorSet.addListener(new AnimatorListenerAdapter() {
@Override @Override

View File

@ -16,6 +16,10 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
private int lastOffset; private int lastOffset;
private boolean waitingForLoad; private boolean waitingForLoad;
private boolean preview; private boolean preview;
private boolean finishedLoadingFile;
private String finishedFilePath;
private boolean ignored;
public AnimatedFileDrawableStream(TLRPC.Document d, Object p, int a, boolean prev) { public AnimatedFileDrawableStream(TLRPC.Document d, Object p, int a, boolean prev) {
document = d; document = d;
@ -25,6 +29,14 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
loadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, 0, preview); loadOperation = FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, 0, preview);
} }
public boolean isFinishedLoadingFile() {
return finishedLoadingFile;
}
public String getFinishedFilePath() {
return finishedFilePath;
}
public int read(int offset, int readLength) { public int read(int offset, int readLength) {
synchronized (sync) { synchronized (sync) {
if (canceled) { if (canceled) {
@ -37,7 +49,12 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream {
int availableLength = 0; int availableLength = 0;
try { try {
while (availableLength == 0) { while (availableLength == 0) {
availableLength = loadOperation.getDownloadedLengthFromOffset(offset, readLength); int[] result = loadOperation.getDownloadedLengthFromOffset(offset, readLength);
availableLength = result[0];
if (!finishedLoadingFile && result[1] != 0) {
finishedLoadingFile = true;
finishedFilePath = loadOperation.getCacheFileFinal().getAbsolutePath();
}
if (availableLength == 0) { if (availableLength == 0) {
if (loadOperation.isPaused() || lastOffset != offset || preview) { if (loadOperation.isPaused() || lastOffset != offset || preview) {
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, offset, preview); FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, offset, preview);

View File

@ -9,6 +9,7 @@
package org.telegram.messenger; package org.telegram.messenger;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.Application; import android.app.Application;
import android.app.PendingIntent; import android.app.PendingIntent;
@ -54,7 +55,6 @@ public class ApplicationLoader extends Application {
public static volatile Context applicationContext; public static volatile Context applicationContext;
public static volatile NetworkInfo currentNetworkInfo; public static volatile NetworkInfo currentNetworkInfo;
public static volatile boolean unableGetCurrentNetwork;
public static volatile Handler applicationHandler; public static volatile Handler applicationHandler;
private static ConnectivityManager connectivityManager; private static ConnectivityManager connectivityManager;
@ -252,7 +252,6 @@ public class ApplicationLoader extends Application {
}; };
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
ApplicationLoader.applicationContext.registerReceiver(networkStateReceiver, filter); ApplicationLoader.applicationContext.registerReceiver(networkStateReceiver, filter);
//Utilities.globalQueue.postRunnable(ApplicationLoader::ensureCurrentNetworkGet);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -345,7 +344,16 @@ public class ApplicationLoader extends Application {
NativeLoader.initNativeLibs(ApplicationLoader.applicationContext); NativeLoader.initNativeLibs(ApplicationLoader.applicationContext);
ConnectionsManager.native_setJava(false); ConnectionsManager.native_setJava(false);
new ForegroundDetector(this); new ForegroundDetector(this) {
@Override
public void onActivityStarted(Activity activity) {
boolean wasInBackground = isBackground();
super.onActivityStarted(activity);
if (wasInBackground) {
ensureCurrentNetworkGet(true);
}
}
};
applicationHandler = new Handler(applicationContext.getMainLooper()); applicationHandler = new Handler(applicationContext.getMainLooper());
@ -418,24 +426,22 @@ public class ApplicationLoader extends Application {
} }
} }
/* private static void ensureCurrentNetworkGet(boolean force) {
private static void ensureCurrentNetworkGet() { if (force || currentNetworkInfo == null) {
if (currentNetworkInfo == null) {
try { try {
if (connectivityManager == null) { if (connectivityManager == null) {
connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
} }
currentNetworkInfo = connectivityManager.getActiveNetworkInfo(); currentNetworkInfo = connectivityManager.getActiveNetworkInfo();
unableGetCurrentNetwork = false;
} catch (Throwable ignore) { } catch (Throwable ignore) {
unableGetCurrentNetwork = true;
} }
} }
} }
public static boolean isRoaming() { public static boolean isRoaming() {
try { try {
ensureCurrentNetworkGet(); ensureCurrentNetworkGet(false);
return currentNetworkInfo != null && currentNetworkInfo.isRoaming(); return currentNetworkInfo != null && currentNetworkInfo.isRoaming();
} catch (Exception e) { } catch (Exception e) {
FileLog.e(e); FileLog.e(e);
@ -445,8 +451,8 @@ public class ApplicationLoader extends Application {
public static boolean isConnectedOrConnectingToWiFi() { public static boolean isConnectedOrConnectingToWiFi() {
try { try {
ensureCurrentNetworkGet(); ensureCurrentNetworkGet(false);
if (currentNetworkInfo != null && currentNetworkInfo.getType() == ) { if (currentNetworkInfo != null && currentNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
NetworkInfo.State state = currentNetworkInfo.getState(); NetworkInfo.State state = currentNetworkInfo.getState();
if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING || state == NetworkInfo.State.SUSPENDED) { if (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING || state == NetworkInfo.State.SUSPENDED) {
return true; return true;
@ -460,7 +466,7 @@ public class ApplicationLoader extends Application {
public static boolean isConnectedToWiFi() { public static boolean isConnectedToWiFi() {
try { try {
ensureCurrentNetworkGet(); ensureCurrentNetworkGet(false);
if (currentNetworkInfo != null && currentNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI && currentNetworkInfo.getState() == NetworkInfo.State.CONNECTED) { if (currentNetworkInfo != null && currentNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI && currentNetworkInfo.getState() == NetworkInfo.State.CONNECTED) {
return true; return true;
} }
@ -472,7 +478,7 @@ public class ApplicationLoader extends Application {
public static boolean isConnectionSlow() { public static boolean isConnectionSlow() {
try { try {
ensureCurrentNetworkGet(); ensureCurrentNetworkGet(false);
if (currentNetworkInfo != null && currentNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) { if (currentNetworkInfo != null && currentNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
switch (currentNetworkInfo.getSubtype()) { switch (currentNetworkInfo.getSubtype()) {
case TelephonyManager.NETWORK_TYPE_1xRTT: case TelephonyManager.NETWORK_TYPE_1xRTT:
@ -489,60 +495,6 @@ public class ApplicationLoader extends Application {
return false; return false;
} }
public static boolean isNetworkOnline() {
try {
ensureCurrentNetworkGet();
if (!unableGetCurrentNetwork && currentNetworkInfo == null) {
return false;
}
if (currentNetworkInfo.isConnectedOrConnecting() || currentNetworkInfo.isAvailable()) {
return true;
}
NetworkInfo netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
} else {
netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
}
} catch (Exception e) {
FileLog.e(e);
return true;
}
return false;
}
*/
public static boolean isRoaming() {
try {
ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
if (netInfo != null) {
return netInfo.isRoaming();
}
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
public static boolean isConnectedOrConnectingToWiFi() {
try {
ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo.State state = netInfo.getState();
if (netInfo != null && (state == NetworkInfo.State.CONNECTED || state == NetworkInfo.State.CONNECTING || state == NetworkInfo.State.SUSPENDED)) {
return true;
}
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
public static int getAutodownloadNetworkType() { public static int getAutodownloadNetworkType() {
try { try {
ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
@ -566,19 +518,6 @@ public class ApplicationLoader extends Application {
return StatsController.TYPE_MOBILE; return StatsController.TYPE_MOBILE;
} }
public static boolean isConnectedToWiFi() {
try {
ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (netInfo != null && netInfo.getState() == NetworkInfo.State.CONNECTED) {
return true;
}
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
public static int getCurrentNetworkType() { public static int getCurrentNetworkType() {
if (isConnectedOrConnectingToWiFi()) { if (isConnectedOrConnectingToWiFi()) {
return StatsController.TYPE_WIFI; return StatsController.TYPE_WIFI;
@ -589,27 +528,33 @@ public class ApplicationLoader extends Application {
} }
} }
public static boolean isConnectionSlow() { public static boolean isNetworkOnlineFast() {
try { try {
ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); ensureCurrentNetworkGet(false);
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); if (currentNetworkInfo == null) {
if (netInfo.getType() == ConnectivityManager.TYPE_MOBILE) { return true;
switch (netInfo.getSubtype()) { }
case TelephonyManager.NETWORK_TYPE_1xRTT: if (currentNetworkInfo.isConnectedOrConnecting() || currentNetworkInfo.isAvailable()) {
case TelephonyManager.NETWORK_TYPE_CDMA: return true;
case TelephonyManager.NETWORK_TYPE_EDGE: }
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_IDEN: NetworkInfo netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
return true; if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
} else {
netInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
} }
} }
} catch (Throwable ignore) { } catch (Exception e) {
FileLog.e(e);
return true;
} }
return false; return false;
} }
public static boolean isNetworkOnline() { public static boolean isNetworkOnlineRealtime() {
try { try {
ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager connectivityManager = (ConnectivityManager) ApplicationLoader.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo(); NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
@ -633,4 +578,15 @@ public class ApplicationLoader extends Application {
} }
return false; return false;
} }
public static boolean isNetworkOnline() {
boolean result = isNetworkOnlineRealtime();
if (BuildVars.DEBUG_PRIVATE_VERSION) {
boolean result2 = isNetworkOnlineFast();
if (result != result2) {
FileLog.d("network online mismatch");
}
}
return result;
}
} }

View File

@ -11,6 +11,7 @@ package org.telegram.messenger;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.SystemClock;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
@ -18,10 +19,17 @@ public class DispatchQueue extends Thread {
private volatile Handler handler = null; private volatile Handler handler = null;
private CountDownLatch syncLatch = new CountDownLatch(1); private CountDownLatch syncLatch = new CountDownLatch(1);
private long lastTaskTime;
public DispatchQueue(final String threadName) { public DispatchQueue(final String threadName) {
this(threadName, true);
}
public DispatchQueue(final String threadName, boolean start) {
setName(threadName); setName(threadName);
start(); if (start) {
start();
}
} }
public void sendMessage(Message msg, int delay) { public void sendMessage(Message msg, int delay) {
@ -59,6 +67,7 @@ public class DispatchQueue extends Thread {
public void postRunnable(Runnable runnable) { public void postRunnable(Runnable runnable) {
postRunnable(runnable, 0); postRunnable(runnable, 0);
lastTaskTime = SystemClock.elapsedRealtime();
} }
public void postRunnable(Runnable runnable, long delay) { public void postRunnable(Runnable runnable, long delay) {
@ -87,6 +96,10 @@ public class DispatchQueue extends Thread {
} }
public long getLastTaskTime() {
return lastTaskTime;
}
public void recycle() { public void recycle() {
handler.getLooper().quit(); handler.getLooper().quit();
} }

View File

@ -0,0 +1,89 @@
package org.telegram.messenger;
import android.os.SystemClock;
import java.util.HashMap;
import java.util.LinkedList;
import androidx.annotation.UiThread;
public class DispatchQueuePool {
private LinkedList<DispatchQueue> queues = new LinkedList<>();
private HashMap<DispatchQueue, Integer> busyQueuesMap = new HashMap<>();
private LinkedList<DispatchQueue> busyQueues = new LinkedList<>();
private int maxCount;
private int createdCount;
private int guid;
private int totalTasksCount;
private boolean cleanupScheduled;
private Runnable cleanupRunnable = new Runnable() {
@Override
public void run() {
if (!queues.isEmpty()) {
long currentTime = SystemClock.elapsedRealtime();
for (int a = 0, N = queues.size(); a < N; a++) {
DispatchQueue queue = queues.get(a);
if (queue.getLastTaskTime() < currentTime - 30000) {
queue.recycle();
queues.remove(a);
createdCount--;
a--;
N--;
}
}
}
if (!queues.isEmpty() || !busyQueues.isEmpty()) {
AndroidUtilities.runOnUIThread(this, 30000);
cleanupScheduled = true;
} else {
cleanupScheduled = false;
}
}
};
public DispatchQueuePool(int count) {
maxCount = count;
guid = Utilities.random.nextInt();
}
@UiThread
public void execute(Runnable runnable) {
DispatchQueue queue;
if (!busyQueues.isEmpty() && (totalTasksCount / 2 <= busyQueues.size() || queues.isEmpty() && createdCount >= maxCount)) {
queue = busyQueues.remove(0);
} else if (queues.isEmpty()) {
queue = new DispatchQueue("DispatchQueuePool" + guid + "_" + Utilities.random.nextInt());
queue.setPriority(Thread.MAX_PRIORITY);
createdCount++;
} else {
queue = queues.remove(0);
}
if (!cleanupScheduled) {
AndroidUtilities.runOnUIThread(cleanupRunnable, 30000);
cleanupScheduled = true;
}
totalTasksCount++;
busyQueues.add(queue);
Integer count = busyQueuesMap.get(queue);
if (count == null) {
count = 0;
}
busyQueuesMap.put(queue, count + 1);
queue.postRunnable(() -> {
runnable.run();
AndroidUtilities.runOnUIThread(() -> {
totalTasksCount--;
int remainingTasksCount = busyQueuesMap.get(queue) - 1;
if (remainingTasksCount == 0) {
busyQueuesMap.remove(queue);
busyQueues.remove(queue);
queues.add(queue);
} else {
busyQueuesMap.put(queue, remainingTasksCount);
}
});
});
}
}

View File

@ -45,7 +45,7 @@ public class Emoji {
private static int bigImgSize; private static int bigImgSize;
private static boolean inited = false; private static boolean inited = false;
private static Paint placeholderPaint; private static Paint placeholderPaint;
private static int[] emojiCounts = new int[]{1620, 184, 115, 328, 125, 206, 288, 258}; private static int[] emojiCounts = new int[]{1620, 184, 115, 328, 125, 207, 288, 258};
private static Bitmap[][] emojiBmp = new Bitmap[8][]; private static Bitmap[][] emojiBmp = new Bitmap[8][];
private static boolean[][] loadingEmoji = new boolean[8][]; private static boolean[][] loadingEmoji = new boolean[8][];
@ -75,7 +75,27 @@ public class Emoji {
placeholderPaint.setColor(0x00000000); placeholderPaint.setColor(0x00000000);
} }
public static void preloadEmoji(CharSequence code) {
final DrawableInfo info = getDrawableInfo(code);
if (info != null) {
loadEmoji(info.page, info.page2);
}
}
private static void loadEmoji(final byte page, final short page2) { private static void loadEmoji(final byte page, final short page2) {
if (emojiBmp[page][page2] == null) {
if (loadingEmoji[page][page2]) {
return;
}
loadingEmoji[page][page2] = true;
Utilities.globalQueue.postRunnable(() -> {
loadEmojiInternal(page, page2);
loadingEmoji[page][page2] = false;
});
}
}
private static void loadEmojiInternal(final byte page, final short page2) {
try { try {
float scale; float scale;
int imageResize = 1; int imageResize = 1;
@ -170,13 +190,7 @@ public class Emoji {
} }
public static EmojiDrawable getEmojiDrawable(CharSequence code) { public static EmojiDrawable getEmojiDrawable(CharSequence code) {
DrawableInfo info = rects.get(code); DrawableInfo info = getDrawableInfo(code);
if (info == null) {
CharSequence newCode = EmojiData.emojiAliasMap.get(code);
if (newCode != null) {
info = Emoji.rects.get(newCode);
}
}
if (info == null) { if (info == null) {
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
FileLog.d("No drawable for emoji " + code); FileLog.d("No drawable for emoji " + code);
@ -188,6 +202,17 @@ public class Emoji {
return ed; return ed;
} }
private static DrawableInfo getDrawableInfo(CharSequence code) {
DrawableInfo info = rects.get(code);
if (info == null) {
CharSequence newCode = EmojiData.emojiAliasMap.get(code);
if (newCode != null) {
info = Emoji.rects.get(newCode);
}
}
return info;
}
public static boolean isValidEmoji(CharSequence code) { public static boolean isValidEmoji(CharSequence code) {
DrawableInfo info = rects.get(code); DrawableInfo info = rects.get(code);
if (info == null) { if (info == null) {
@ -255,14 +280,7 @@ public class Emoji {
return; return;
} }
if (emojiBmp[info.page][info.page2] == null) { if (emojiBmp[info.page][info.page2] == null) {
if (loadingEmoji[info.page][info.page2]) { loadEmoji(info.page, info.page2);
return;
}
loadingEmoji[info.page][info.page2] = true;
Utilities.globalQueue.postRunnable(() -> {
loadEmoji(info.page, info.page2);
loadingEmoji[info.page][info.page2] = false;
});
canvas.drawRect(getBounds(), placeholderPaint); canvas.drawRect(getBounds(), placeholderPaint);
return; return;
} }

View File

@ -70,7 +70,7 @@ public class EmojiData {
"👨‍🍳", "👩‍🎓", "🧑‍🎓", "👨‍🎓", "👩‍🎤", "🧑‍🎤", "👨‍🎤", "👩‍🏫", "🧑‍🏫", "👨‍🏫", "👩‍🏭", "🧑‍🏭", "👨‍🏭", "👩‍💻", "🧑‍💻", "👨‍💻", "👨‍🍳", "👩‍🎓", "🧑‍🎓", "👨‍🎓", "👩‍🎤", "🧑‍🎤", "👨‍🎤", "👩‍🏫", "🧑‍🏫", "👨‍🏫", "👩‍🏭", "🧑‍🏭", "👨‍🏭", "👩‍💻", "🧑‍💻", "👨‍💻",
"👩‍💼", "🧑‍💼", "👨‍💼", "👩‍🔧", "🧑‍🔧", "👨‍🔧", "👩‍🔬", "🧑‍🔬", "👨‍🔬", "👩‍🎨", "🧑‍🎨", "👨‍🎨", "👩‍🚒", "🧑‍🚒", "👨‍🚒", "👩‍✈", "👩‍💼", "🧑‍💼", "👨‍💼", "👩‍🔧", "🧑‍🔧", "👨‍🔧", "👩‍🔬", "🧑‍🔬", "👨‍🔬", "👩‍🎨", "🧑‍🎨", "👨‍🎨", "👩‍🚒", "🧑‍🚒", "👨‍🚒", "👩‍✈",
"🧑‍✈", "👨‍✈", "👩‍🚀", "🧑‍🚀", "👨‍🚀", "👩‍⚖", "🧑‍⚖", "👨‍⚖", "👰", "🤵", "👸", "🤴", "🦸‍♀", "🦸", "🦸‍♂", "🦹‍♀", "🧑‍✈", "👨‍✈", "👩‍🚀", "🧑‍🚀", "👨‍🚀", "👩‍⚖", "🧑‍⚖", "👨‍⚖", "👰", "🤵", "👸", "🤴", "🦸‍♀", "🦸", "🦸‍♂", "🦹‍♀",
"🦹", "🦹‍♂", "🤶", "🎅", "🧙‍♀", "🧙", "🧙‍♂", "🧝‍♀", "🧝", "🧝‍♂", "🧛‍♀", "🧛", "🧛‍♂", "🧟‍♀", "🧜‍♀", "🧜", "🦹", "🦹‍♂", "🤶", "🎅", "🧙‍♀", "🧙", "🧙‍♂", "🧝‍♀", "🧝", "🧝‍♂", "🧛‍♀", "🧛", "🧛‍♂", "🧜‍♀", "🧜",
"🧜‍♂", "🧚‍♀", "🧚", "🧚‍♂", "👼", "🤰", "🤱", "🙇‍♀", "🙇", "🙇‍♂", "💁‍♀", "💁", "💁‍♂", "🙅‍♀", "🙅", "🙅‍♂", "🧜‍♂", "🧚‍♀", "🧚", "🧚‍♂", "👼", "🤰", "🤱", "🙇‍♀", "🙇", "🙇‍♂", "💁‍♀", "💁", "💁‍♂", "🙅‍♀", "🙅", "🙅‍♂",
"🙆‍♀", "🙆", "🙆‍♂", "🙋‍♀", "🙋", "🙋‍♂", "🧏‍♀", "🧏", "🧏‍♂", "🤦‍♀", "🤦", "🤦‍♂", "🤷‍♀", "🤷", "🤷‍♂", "🙎‍♀", "🙆‍♀", "🙆", "🙆‍♂", "🙋‍♀", "🙋", "🙋‍♂", "🧏‍♀", "🧏", "🧏‍♂", "🤦‍♀", "🤦", "🤦‍♂", "🤷‍♀", "🤷", "🤷‍♂", "🙎‍♀",
"🙎", "🙎‍♂", "🙍‍♀", "🙍", "🙍‍♂", "💇‍♀", "💇", "💇‍♂", "💆‍♀", "💆", "💆‍♂", "🧖‍♀", "🧖", "🧖‍♂", "💅", "🤳", "🙎", "🙎‍♂", "🙍‍♀", "🙍", "🙍‍♂", "💇‍♀", "💇", "💇‍♂", "💆‍♀", "💆", "💆‍♂", "🧖‍♀", "🧖", "🧖‍♂", "💅", "🤳",
@ -377,7 +377,7 @@ public class EmojiData {
new String[]{ new String[]{
"", "📱", "📲", "💻", "", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", "📞", "", "📟", "📠", "📺", "📻", "🎙", "🎚", "🎛", "🧭", "", "", "", "🕰", "", "", "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🪔", "🧯", "🛢", "💸", "💵", "💴", "💶", "💷", "💰", "💳", "💎", "", "🧰", "🔧", "🔨", "", "🛠", "", "🔩", "", "🧱", "", "🧲", "🔫", "💣", "🧨", "🪓", "🔪", "🗡", "", "🛡", "🚬", "", "", "🏺", "🔮", "📿", "🧿", "💈", "", "🔭", "🔬", "🕳", "🩹", "🩺", "💊", "💉", "🩸", "🧬", "🦠", "🧫", "🧪", "🌡", "🧹", "🧺", "🧻", "🚽", "🚰", "🚿", "🛁", "", "📱", "📲", "💻", "", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", "📞", "", "📟", "📠", "📺", "📻", "🎙", "🎚", "🎛", "🧭", "", "", "", "🕰", "", "", "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🪔", "🧯", "🛢", "💸", "💵", "💴", "💶", "💷", "💰", "💳", "💎", "", "🧰", "🔧", "🔨", "", "🛠", "", "🔩", "", "🧱", "", "🧲", "🔫", "💣", "🧨", "🪓", "🔪", "🗡", "", "🛡", "🚬", "", "", "🏺", "🔮", "📿", "🧿", "💈", "", "🔭", "🔬", "🕳", "🩹", "🩺", "💊", "💉", "🩸", "🧬", "🦠", "🧫", "🧪", "🌡", "🧹", "🧺", "🧻", "🚽", "🚰", "🚿", "🛁",
"🛀", "🛀",
"🧼", "🪒", "🧽", "🧴", "🛎", "🔑", "🗝", "🚪", "🪑", "🛋", "🛏", "🛌", "🧸", "🖼", "🛍", "🛒", "🎁", "🎈", "🎏", "🎀", "🎊", "🎉", "🎎", "🏮", "🎐", "🧧", "", "📩", "📨", "📧", "💌", "📥", "📤", "📦", "🏷", "📪", "📫", "📬", "📭", "📮", "📯📜", "📃", "📄", "📑", "🧾", "📊", "📈", "📉", "🗒", "🗓", "📆", "📅", "🗑", "📇", "🗃", "🗳", "🗄", "📋", "📁", "📂", "🗂", "🗞", "📰", "📓", "📔", "📒", "📕", "📗", "📘", "📙", "📚", "📖", "🔖", "🧷", "🔗", "📎", "🖇", "📐", "📏", "🧮", "📌", "📍", "", "🖊", "🖋", "", "🖌", "🖍", "📝", "", "🔍", "🔎", "🔏", "🔐", "🔒", "🔓" "🧼", "🪒", "🧽", "🧴", "🛎", "🔑", "🗝", "🚪", "🪑", "🛋", "🛏", "🛌", "🧸", "🖼", "🛍", "🛒", "🎁", "🎈", "🎏", "🎀", "🎊", "🎉", "🎎", "🏮", "🎐", "🧧", "", "📩", "📨", "📧", "💌", "📥", "📤", "📦", "🏷", "📪", "📫", "📬", "📭", "📮", "📯", "📜", "📃", "📄", "📑", "🧾", "📊", "📈", "📉", "🗒", "🗓", "📆", "📅", "🗑", "📇", "🗃", "🗳", "🗄", "📋", "📁", "📂", "🗂", "🗞", "📰", "📓", "📔", "📒", "📕", "📗", "📘", "📙", "📚", "📖", "🔖", "🧷", "🔗", "📎", "🖇", "📐", "📏", "🧮", "📌", "📍", "", "🖊", "🖋", "", "🖌", "🖍", "📝", "", "🔍", "🔎", "🔏", "🔐", "🔒", "🔓"
}, },
null, null,
null null
@ -779,7 +779,7 @@ public class EmojiData {
new String[]{ new String[]{
"", "📱", "📲", "💻", "", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", "📞", "", "📟", "📠", "📺", "📻", "🎙", "🎚", "🎛", "🧭", "", "", "", "🕰", "", "", "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🪔", "🧯", "🛢", "💸", "💵", "💴", "💶", "💷", "💰", "💳", "💎", "", "🧰", "🔧", "🔨", "", "🛠", "", "🔩", "", "🧱", "", "🧲", "🔫", "💣", "🧨", "🪓", "🔪", "🗡", "", "🛡", "🚬", "", "", "🏺", "🔮", "📿", "🧿", "💈", "", "🔭", "🔬", "🕳", "🩹", "🩺", "💊", "💉", "🩸", "🧬", "🦠", "🧫", "🧪", "🌡", "🧹", "🧺", "🧻", "🚽", "🚰", "🚿", "🛁", "", "📱", "📲", "💻", "", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", "📞", "", "📟", "📠", "📺", "📻", "🎙", "🎚", "🎛", "🧭", "", "", "", "🕰", "", "", "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🪔", "🧯", "🛢", "💸", "💵", "💴", "💶", "💷", "💰", "💳", "💎", "", "🧰", "🔧", "🔨", "", "🛠", "", "🔩", "", "🧱", "", "🧲", "🔫", "💣", "🧨", "🪓", "🔪", "🗡", "", "🛡", "🚬", "", "", "🏺", "🔮", "📿", "🧿", "💈", "", "🔭", "🔬", "🕳", "🩹", "🩺", "💊", "💉", "🩸", "🧬", "🦠", "🧫", "🧪", "🌡", "🧹", "🧺", "🧻", "🚽", "🚰", "🚿", "🛁",
"🛀", "🛀🏻", "🛀🏼", "🛀🏽", "🛀🏾", "🛀🏿", "🛀", "🛀🏻", "🛀🏼", "🛀🏽", "🛀🏾", "🛀🏿",
"🧼", "🪒", "🧽", "🧴", "🛎", "🔑", "🗝", "🚪", "🪑", "🛋", "🛏", "🛌", "🧸", "🖼", "🛍", "🛒", "🎁", "🎈", "🎏", "🎀", "🎊", "🎉", "🎎", "🏮", "🎐", "🧧", "", "📩", "📨", "📧", "💌", "📥", "📤", "📦", "🏷", "📪", "📫", "📬", "📭", "📮", "📯📜", "📃", "📄", "📑", "🧾", "📊", "📈", "📉", "🗒", "🗓", "📆", "📅", "🗑", "📇", "🗃", "🗳", "🗄", "📋", "📁", "📂", "🗂", "🗞", "📰", "📓", "📔", "📒", "📕", "📗", "📘", "📙", "📚", "📖", "🔖", "🧷", "🔗", "📎", "🖇", "📐", "📏", "🧮", "📌", "📍", "", "🖊", "🖋", "", "🖌", "🖍", "📝", "", "🔍", "🔎", "🔏", "🔐", "🔒", "🔓" "🧼", "🪒", "🧽", "🧴", "🛎", "🔑", "🗝", "🚪", "🪑", "🛋", "🛏", "🛌", "🧸", "🖼", "🛍", "🛒", "🎁", "🎈", "🎏", "🎀", "🎊", "🎉", "🎎", "🏮", "🎐", "🧧", "", "📩", "📨", "📧", "💌", "📥", "📤", "📦", "🏷", "📪", "📫", "📬", "📭", "📮", "📯", "📜", "📃", "📄", "📑", "🧾", "📊", "📈", "📉", "🗒", "🗓", "📆", "📅", "🗑", "📇", "🗃", "🗳", "🗄", "📋", "📁", "📂", "🗂", "🗞", "📰", "📓", "📔", "📒", "📕", "📗", "📘", "📙", "📚", "📖", "🔖", "🧷", "🔗", "📎", "🖇", "📐", "📏", "🧮", "📌", "📍", "", "🖊", "🖋", "", "🖌", "🖍", "📝", "", "🔍", "🔎", "🔏", "🔐", "🔒", "🔓"
}, },
new String[]{ new String[]{
"", "🧡", "💛", "💚", "💙", "💜", "🖤", "🤍", "🤎", "💔", "", "💕", "💞", "💓", "💗", "💖", "💘", "💝", "💟", "", "", "", "🕉", "", "", "🔯", "🕎", "", "", "🛐", "", "", "", "", "", "", "", "", "", "", "", "", "", "🆔", "", "🉑", "", "", "📴", "📳", "🈶", "🈚", "🈸", "🈺", "🈷", "", "🆚", "💮", "🉐", "", "", "🈴", "🈵", "🈹", "🈲", "🅰", "🅱", "🆎", "🆑", "🅾", "🆘", "", "", "🛑", "", "📛", "🚫", "💯", "💢", "", "🚷", "🚯", "🚳", "🚱", "🔞", "📵", "🚭", "", "", "", "", "", "", "🔅", "🔆", "", "", "🚸", "🔱", "", "🔰", "", "", "🈯", "💹", "", "", "", "🌐", "💠", "", "🌀", "💤", "🏧", "🚾", "", "🅿", "🈳", "🈂", "🛂", "🛃", "🛄", "🛅", "🚹", "🚺", "🚼", "🚻", "🚮", "🎦", "📶", "🈁", "🔣", "", "🔤", "🔡", "🔠", "🆖", "🆗", "🆙", "🆒", "🆕", "🆓", "0⃣", "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟", "🔢", "#⃣", "*⃣", "", "", "", "", "", "", "", "", "", "", "", "", "", "🔼", "🔽", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "🔀", "🔁", "🔂", "🔄", "🔃", "🎵", "🎶", "", "", "", "", "", "💲", "💱", "", "©", "®", "👁‍🗨", "🔚", "🔙", "🔛", "🔝", "🔜", "", "", "", "", "", "🔘", "🔴", "🟠", "🟡", "🟢", "🔵", "🟣", "", "", "🟤", "🔺", "🔻", "🔸", "🔹", "🔶", "🔷", "🔳", "🔲", "", "", "", "", "", "", "🟥", "🟧", "🟨", "🟩", "🟦", "🟪", "", "", "🟫", "🔈", "🔇", "🔉", "🔊", "🔔", "🔕", "📣", "📢", "💬", "💭", "🗯", "", "", "", "", "🃏", "🎴", "🀄", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", "🕛", "🕜", "🕝", "🕞", "🕟", "🕠", "🕡", "🕢", "🕣", "🕤", "🕥", "🕦", "🕧" "", "🧡", "💛", "💚", "💙", "💜", "🖤", "🤍", "🤎", "💔", "", "💕", "💞", "💓", "💗", "💖", "💘", "💝", "💟", "", "", "", "🕉", "", "", "🔯", "🕎", "", "", "🛐", "", "", "", "", "", "", "", "", "", "", "", "", "", "🆔", "", "🉑", "", "", "📴", "📳", "🈶", "🈚", "🈸", "🈺", "🈷", "", "🆚", "💮", "🉐", "", "", "🈴", "🈵", "🈹", "🈲", "🅰", "🅱", "🆎", "🆑", "🅾", "🆘", "", "", "🛑", "", "📛", "🚫", "💯", "💢", "", "🚷", "🚯", "🚳", "🚱", "🔞", "📵", "🚭", "", "", "", "", "", "", "🔅", "🔆", "", "", "🚸", "🔱", "", "🔰", "", "", "🈯", "💹", "", "", "", "🌐", "💠", "", "🌀", "💤", "🏧", "🚾", "", "🅿", "🈳", "🈂", "🛂", "🛃", "🛄", "🛅", "🚹", "🚺", "🚼", "🚻", "🚮", "🎦", "📶", "🈁", "🔣", "", "🔤", "🔡", "🔠", "🆖", "🆗", "🆙", "🆒", "🆕", "🆓", "0⃣", "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟", "🔢", "#⃣", "*⃣", "", "", "", "", "", "", "", "", "", "", "", "", "", "🔼", "🔽", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "🔀", "🔁", "🔂", "🔄", "🔃", "🎵", "🎶", "", "", "", "", "", "💲", "💱", "", "©", "®", "👁‍🗨", "🔚", "🔙", "🔛", "🔝", "🔜", "", "", "", "", "", "🔘", "🔴", "🟠", "🟡", "🟢", "🔵", "🟣", "", "", "🟤", "🔺", "🔻", "🔸", "🔹", "🔶", "🔷", "🔳", "🔲", "", "", "", "", "", "", "🟥", "🟧", "🟨", "🟩", "🟦", "🟪", "", "", "🟫", "🔈", "🔇", "🔉", "🔊", "🔔", "🔕", "📣", "📢", "💬", "💭", "🗯", "", "", "", "", "🃏", "🎴", "🀄", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", "🕛", "🕜", "🕝", "🕞", "🕟", "🕠", "🕡", "🕢", "🕣", "🕤", "🕥", "🕦", "🕧"

View File

@ -473,6 +473,10 @@ public class FileLoadOperation {
} }
} }
protected File getCacheFileFinal() {
return cacheFileFinal;
}
protected File getCurrentFile() { protected File getCurrentFile() {
final CountDownLatch countDownLatch = new CountDownLatch(1); final CountDownLatch countDownLatch = new CountDownLatch(1);
final File[] result = new File[1]; final File[] result = new File[1];
@ -532,11 +536,14 @@ public class FileLoadOperation {
return progress + getDownloadedLengthFromOffsetInternal(ranges, (int) (totalBytesCount * progress), totalBytesCount) / (float) totalBytesCount; return progress + getDownloadedLengthFromOffsetInternal(ranges, (int) (totalBytesCount * progress), totalBytesCount) / (float) totalBytesCount;
} }
protected int getDownloadedLengthFromOffset(final int offset, final int length) { protected int[] getDownloadedLengthFromOffset(final int offset, final int length) {
final CountDownLatch countDownLatch = new CountDownLatch(1); final CountDownLatch countDownLatch = new CountDownLatch(1);
final int[] result = new int[1]; final int[] result = new int[2];
Utilities.stageQueue.postRunnable(() -> { Utilities.stageQueue.postRunnable(() -> {
result[0] = getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, offset, length); result[0] = getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, offset, length);
if (state == stateFinished) {
result[1] = 1;
}
countDownLatch.countDown(); countDownLatch.countDown();
}); });
try { try {
@ -544,7 +551,7 @@ public class FileLoadOperation {
} catch (Exception ignore) { } catch (Exception ignore) {
} }
return result[0]; return result;
} }
public String getFileName() { public String getFileName() {
@ -922,8 +929,8 @@ public class FileLoadOperation {
} }
if (!isPreloadVideoOperation && downloadedBytes != 0 && totalBytesCount > 0) { if (!isPreloadVideoOperation && downloadedBytes != 0 && totalBytesCount > 0) {
copyNotLoadedRanges(); copyNotLoadedRanges();
delegate.didChangedLoadProgress(FileLoadOperation.this, downloadedBytes, totalBytesCount);
} }
updateProgress();
try { try {
fileOutputStream = new RandomAccessFile(cacheFileTemp, "rws"); fileOutputStream = new RandomAccessFile(cacheFileTemp, "rws");
if (downloadedBytes != 0) { if (downloadedBytes != 0) {
@ -959,6 +966,12 @@ public class FileLoadOperation {
return true; return true;
} }
public void updateProgress() {
if (delegate != null && downloadedBytes != totalBytesCount && totalBytesCount > 0) {
delegate.didChangedLoadProgress(FileLoadOperation.this, downloadedBytes, totalBytesCount);
}
}
public boolean isPaused() { public boolean isPaused() {
return paused; return paused;
} }

View File

@ -19,7 +19,6 @@ import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
@ -598,6 +597,7 @@ public class FileLoader extends BaseController {
} }
} }
} }
operation.updateProgress();
return operation; return operation;
} }
@ -1035,13 +1035,13 @@ public class FileLoader extends BaseController {
continue; continue;
} }
if (byMinSide) { if (byMinSide) {
int currentSide = obj.h >= obj.w ? obj.w : obj.h; int currentSide = Math.min(obj.h, obj.w);
if (closestObject == null || side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE || obj instanceof TLRPC.TL_photoCachedSize || side > lastSide && lastSide < currentSide) { if (closestObject == null || side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE || obj instanceof TLRPC.TL_photoCachedSize || side > lastSide && lastSide < currentSide) {
closestObject = obj; closestObject = obj;
lastSide = currentSide; lastSide = currentSide;
} }
} else { } else {
int currentSide = obj.w >= obj.h ? obj.w : obj.h; int currentSide = Math.max(obj.w, obj.h);
if (closestObject == null || side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE || obj instanceof TLRPC.TL_photoCachedSize || currentSide <= side && lastSide < currentSide) { if (closestObject == null || side > 100 && closestObject.location != null && closestObject.location.dc_id == Integer.MIN_VALUE || obj instanceof TLRPC.TL_photoCachedSize || currentSide <= side && lastSide < currentSide) {
closestObject = obj; closestObject = obj;
lastSide = currentSide; lastSide = currentSide;
@ -1258,45 +1258,4 @@ public class FileLoader extends BaseController {
out.close(); out.close();
return true; return true;
} }
public static long getTempFileSize(TLRPC.Document documentLocation, boolean encrypt) {
long location_id = documentLocation.id;
long datacenterId = documentLocation.dc_id;
if (datacenterId == 0 || location_id == 0) {
return 0;
}
String fileName = datacenterId + "_" + location_id + (encrypt ? ".temp.enc" : ".temp");
String fileNameParts = datacenterId + "_" + location_id + ".pt";
File f = new File(getDirectory(MEDIA_DIR_CACHE), fileName);
long size = 0;
if (f.exists()) {
size = f.length();
}
if (size != 0) {
File cacheFileParts = new File(getDirectory(MEDIA_DIR_CACHE), fileNameParts);
try {
RandomAccessFile filePartsStream = new RandomAccessFile(cacheFileParts, "r");
long len = filePartsStream.length();
if (len % 8 == 4) {
len -= 4;
int count = filePartsStream.readInt();
if (count <= len / 2) {
size = documentLocation.size;
for (int a = 0; a < count; a++) {
int start = filePartsStream.readInt();
int end = filePartsStream.readInt();
size -= end - start;
}
}
}
} catch (Exception e) {
FileLog.e(e);
}
}
return size;
}
} }

View File

@ -25,6 +25,17 @@ public class FileRefController extends BaseController {
private long firstQueryTime; private long firstQueryTime;
} }
private static class Waiter {
private String locationKey;
private String parentKey;
public Waiter(String loc, String parent) {
locationKey = loc;
parentKey = parent;
}
}
private HashMap<String, ArrayList<Requester>> locationRequester = new HashMap<>(); private HashMap<String, ArrayList<Requester>> locationRequester = new HashMap<>();
private HashMap<String, ArrayList<Requester>> parentRequester = new HashMap<>(); private HashMap<String, ArrayList<Requester>> parentRequester = new HashMap<>();
private HashMap<String, CachedResult> responseCache = new HashMap<>(); private HashMap<String, CachedResult> responseCache = new HashMap<>();
@ -32,6 +43,11 @@ public class FileRefController extends BaseController {
private long lastCleanupTime = SystemClock.elapsedRealtime(); private long lastCleanupTime = SystemClock.elapsedRealtime();
private ArrayList<Waiter> wallpaperWaiters = new ArrayList<>();
private ArrayList<Waiter> savedGifsWaiters = new ArrayList<>();
private ArrayList<Waiter> recentStickersWaiter = new ArrayList<>();
private ArrayList<Waiter> favStickersWaiter = new ArrayList<>();
private static volatile FileRefController[] Instance = new FileRefController[UserConfig.MAX_ACCOUNT_COUNT]; private static volatile FileRefController[] Instance = new FileRefController[UserConfig.MAX_ACCOUNT_COUNT];
public static FileRefController getInstance(int num) { public static FileRefController getInstance(int num) {
@ -263,6 +279,14 @@ public class FileRefController extends BaseController {
requestReferenceFromServer(parentObject, locationKey, parentKey, args); requestReferenceFromServer(parentObject, locationKey, parentKey, args);
} }
private void broadcastWaitersData(ArrayList<Waiter> waiters, TLObject response) {
for (int a = 0, N = waiters.size(); a < N; a++) {
Waiter waiter = waiters.get(a);
onRequestComplete(waiter.locationKey, waiter.parentKey, response, a == N - 1);
}
waiters.clear();
}
private void requestReferenceFromServer(Object parentObject, String locationKey, String parentKey, Object[] args) { private void requestReferenceFromServer(Object parentObject, String locationKey, String parentKey, Object[] args) {
if (parentObject instanceof MessageObject) { if (parentObject instanceof MessageObject) {
MessageObject messageObject = (MessageObject) parentObject; MessageObject messageObject = (MessageObject) parentObject;
@ -324,17 +348,29 @@ public class FileRefController extends BaseController {
} else if (parentObject instanceof String) { } else if (parentObject instanceof String) {
String string = (String) parentObject; String string = (String) parentObject;
if ("wallpaper".equals(string)) { if ("wallpaper".equals(string)) {
TLRPC.TL_account_getWallPapers req = new TLRPC.TL_account_getWallPapers(); if (wallpaperWaiters.isEmpty()) {
getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); TLRPC.TL_account_getWallPapers req = new TLRPC.TL_account_getWallPapers();
getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(wallpaperWaiters, response));
}
wallpaperWaiters.add(new Waiter(locationKey, parentKey));
} else if (string.startsWith("gif")) { } else if (string.startsWith("gif")) {
TLRPC.TL_messages_getSavedGifs req = new TLRPC.TL_messages_getSavedGifs(); if (savedGifsWaiters.isEmpty()) {
getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); TLRPC.TL_messages_getSavedGifs req = new TLRPC.TL_messages_getSavedGifs();
getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(savedGifsWaiters, response));
}
savedGifsWaiters.add(new Waiter(locationKey, parentKey));
} else if ("recent".equals(string)) { } else if ("recent".equals(string)) {
TLRPC.TL_messages_getRecentStickers req = new TLRPC.TL_messages_getRecentStickers(); if (recentStickersWaiter.isEmpty()) {
getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); TLRPC.TL_messages_getRecentStickers req = new TLRPC.TL_messages_getRecentStickers();
getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(recentStickersWaiter, response));
}
recentStickersWaiter.add(new Waiter(locationKey, parentKey));
} else if ("fav".equals(string)) { } else if ("fav".equals(string)) {
TLRPC.TL_messages_getFavedStickers req = new TLRPC.TL_messages_getFavedStickers(); if (favStickersWaiter.isEmpty()) {
getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true)); TLRPC.TL_messages_getFavedStickers req = new TLRPC.TL_messages_getFavedStickers();
getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(favStickersWaiter, response));
}
favStickersWaiter.add(new Waiter(locationKey, parentKey));
} else if (string.startsWith("avatar_")) { } else if (string.startsWith("avatar_")) {
int id = Utilities.parseInt(string); int id = Utilities.parseInt(string);
if (id > 0) { if (id > 0) {
@ -608,13 +644,13 @@ public class FileRefController extends BaseController {
} }
} }
} }
getMessagesStorage().replaceMessageIfExists(message, currentAccount, res.users, res.chats, false); getMessagesStorage().replaceMessageIfExists(message, res.users, res.chats, false);
} }
break; break;
} }
} }
if (result == null) { if (result == null) {
getMessagesStorage().replaceMessageIfExists(res.messages.get(0), currentAccount, res.users, res.chats,true); getMessagesStorage().replaceMessageIfExists(res.messages.get(0), res.users, res.chats,true);
if (BuildVars.DEBUG_VERSION) { if (BuildVars.DEBUG_VERSION) {
FileLog.d("file ref not found in messages, replacing message"); FileLog.d("file ref not found in messages, replacing message");
} }

View File

@ -96,7 +96,7 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO
readLength = (int) bytesRemaining; readLength = (int) bytesRemaining;
} }
while (availableLength == 0 && opened) { while (availableLength == 0 && opened) {
availableLength = loadOperation.getDownloadedLengthFromOffset(currentOffset, readLength); availableLength = loadOperation.getDownloadedLengthFromOffset(currentOffset, readLength)[0];
if (availableLength == 0) { if (availableLength == 0) {
FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, currentOffset, false); FileLoader.getInstance(currentAccount).loadStreamFile(this, document, parentObject, currentOffset, false);
countDownLatch = new CountDownLatch(1); countDownLatch = new CountDownLatch(1);

View File

@ -25,7 +25,7 @@ import java.util.ArrayList;
public class FileUploadOperation { public class FileUploadOperation {
private class UploadCachedResult { private static class UploadCachedResult {
private long bytesOffset; private long bytesOffset;
private byte[] iv; private byte[] iv;
} }

View File

@ -0,0 +1,565 @@
package org.telegram.messenger;
public abstract class FourierTransform {
protected static final int LINAVG = 1;
protected static final int LOGAVG = 2;
protected static final int NOAVG = 3;
protected static final float TWO_PI = (float) (2 * Math.PI);
protected int timeSize;
protected int sampleRate;
protected float bandWidth;
protected float[] real;
protected float[] imag;
protected float[] spectrum;
protected float[] averages;
protected int whichAverage;
protected int octaves;
protected int avgPerOctave;
/**
* Construct a FourierTransform that will analyze sample buffers that are
* <code>ts</code> samples long and contain samples with a <code>sr</code>
* sample rate.
*
* @param ts the length of the buffers that will be analyzed
* @param sr the sample rate of the samples that will be analyzed
*/
FourierTransform(int ts, float sr) {
timeSize = ts;
sampleRate = (int) sr;
bandWidth = (2f / timeSize) * ((float) sampleRate / 2f);
noAverages();
allocateArrays();
}
// allocating real, imag, and spectrum are the responsibility of derived
// classes
// because the size of the arrays will depend on the implementation being used
// this enforces that responsibility
protected abstract void allocateArrays();
protected void setComplex(float[] r, float[] i) {
if (real.length != r.length && imag.length != i.length) {
} else {
System.arraycopy(r, 0, real, 0, r.length);
System.arraycopy(i, 0, imag, 0, i.length);
}
}
// fill the spectrum array with the amps of the data in real and imag
// used so that this class can handle creating the average array
// and also do spectrum shaping if necessary
protected void fillSpectrum() {
for (int i = 0; i < spectrum.length; i++) {
spectrum[i] = (float) Math.sqrt(real[i] * real[i] + imag[i] * imag[i]);
}
if (whichAverage == LINAVG) {
int avgWidth = (int) spectrum.length / averages.length;
for (int i = 0; i < averages.length; i++) {
float avg = 0;
int j;
for (j = 0; j < avgWidth; j++) {
int offset = j + i * avgWidth;
if (offset < spectrum.length) {
avg += spectrum[offset];
} else {
break;
}
}
avg /= j + 1;
averages[i] = avg;
}
} else if (whichAverage == LOGAVG) {
for (int i = 0; i < octaves; i++) {
float lowFreq, hiFreq, freqStep;
if (i == 0) {
lowFreq = 0;
} else {
lowFreq = (sampleRate / 2) / (float) Math.pow(2, octaves - i);
}
hiFreq = (sampleRate / 2) / (float) Math.pow(2, octaves - i - 1);
freqStep = (hiFreq - lowFreq) / avgPerOctave;
float f = lowFreq;
for (int j = 0; j < avgPerOctave; j++) {
int offset = j + i * avgPerOctave;
averages[offset] = calcAvg(f, f + freqStep);
f += freqStep;
}
}
}
}
/**
* Sets the object to not compute averages.
*/
public void noAverages() {
averages = new float[0];
whichAverage = NOAVG;
}
/**
* Sets the number of averages used when computing the spectrum and spaces the
* averages in a linear manner. In other words, each average band will be
* <code>specSize() / numAvg</code> bands wide.
*
* @param numAvg how many averages to compute
*/
public void linAverages(int numAvg) {
if (numAvg > spectrum.length / 2) {
return;
} else {
averages = new float[numAvg];
}
whichAverage = LINAVG;
}
/**
* Sets the number of averages used when computing the spectrum based on the
* minimum bandwidth for an octave and the number of bands per octave. For
* example, with audio that has a sample rate of 44100 Hz,
* <code>logAverages(11, 1)</code> will result in 12 averages, each
* corresponding to an octave, the first spanning 0 to 11 Hz. To ensure that
* each octave band is a full octave, the number of octaves is computed by
* dividing the Nyquist frequency by two, and then the result of that by two,
* and so on. This means that the actual bandwidth of the lowest octave may
* not be exactly the value specified.
*
* @param minBandwidth the minimum bandwidth used for an octave
* @param bandsPerOctave how many bands to split each octave into
*/
public void logAverages(int minBandwidth, int bandsPerOctave) {
float nyq = (float) sampleRate / 2f;
octaves = 1;
while ((nyq /= 2) > minBandwidth) {
octaves++;
}
avgPerOctave = bandsPerOctave;
averages = new float[octaves * bandsPerOctave];
whichAverage = LOGAVG;
}
/**
* Sets the window to use on the samples before taking the forward transform.
* If an invalid window is asked for, an error will be reported and the
* current window will not be changed.
*
* @param windowFunction
*/
/**
* Returns the length of the time domain signal expected by this transform.
*
* @return the length of the time domain signal expected by this transform
*/
public int timeSize() {
return timeSize;
}
/**
* Returns the size of the spectrum created by this transform. In other words,
* the number of frequency bands produced by this transform. This is typically
* equal to <code>timeSize()/2 + 1</code>, see above for an explanation.
*
* @return the size of the spectrum
*/
public int specSize() {
return spectrum.length;
}
/**
* Returns the amplitude of the requested frequency band.
*
* @param i the index of a frequency band
* @return the amplitude of the requested frequency band
*/
public float getBand(int i) {
if (i < 0) i = 0;
if (i > spectrum.length - 1) i = spectrum.length - 1;
return spectrum[i];
}
/**
* Returns the width of each frequency band in the spectrum (in Hz). It should
* be noted that the bandwidth of the first and last frequency bands is half
* as large as the value returned by this function.
*
* @return the width of each frequency band in Hz.
*/
public float getBandWidth() {
return bandWidth;
}
/**
* Sets the amplitude of the <code>i<sup>th</sup></code> frequency band to
* <code>a</code>. You can use this to shape the spectrum before using
* <code>inverse()</code>.
*
* @param i the frequency band to modify
* @param a the new amplitude
*/
public abstract void setBand(int i, float a);
/**
* Scales the amplitude of the <code>i<sup>th</sup></code> frequency band
* by <code>s</code>. You can use this to shape the spectrum before using
* <code>inverse()</code>.
*
* @param i the frequency band to modify
* @param s the scaling factor
*/
public abstract void scaleBand(int i, float s);
/**
* Returns the index of the frequency band that contains the requested
* frequency.
*
* @param freq the frequency you want the index for (in Hz)
* @return the index of the frequency band that contains freq
*/
public int freqToIndex(float freq) {
// special case: freq is lower than the bandwidth of spectrum[0]
if (freq < getBandWidth() / 2) return 0;
// special case: freq is within the bandwidth of spectrum[spectrum.length - 1]
if (freq > sampleRate / 2 - getBandWidth() / 2) return spectrum.length - 1;
// all other cases
float fraction = freq / (float) sampleRate;
int i = Math.round(timeSize * fraction);
return i;
}
/**
* Returns the middle frequency of the i<sup>th</sup> band.
*
* @param i the index of the band you want to middle frequency of
*/
public float indexToFreq(int i) {
float bw = getBandWidth();
// special case: the width of the first bin is half that of the others.
// so the center frequency is a quarter of the way.
if (i == 0) return bw * 0.25f;
// special case: the width of the last bin is half that of the others.
if (i == spectrum.length - 1) {
float lastBinBeginFreq = (sampleRate / 2) - (bw / 2);
float binHalfWidth = bw * 0.25f;
return lastBinBeginFreq + binHalfWidth;
}
// the center frequency of the ith band is simply i*bw
// because the first band is half the width of all others.
// treating it as if it wasn't offsets us to the middle
// of the band.
return i * bw;
}
/**
* Calculate the average amplitude of the frequency band bounded by
* <code>lowFreq</code> and <code>hiFreq</code>, inclusive.
*
* @param lowFreq the lower bound of the band
* @param hiFreq the upper bound of the band
* @return the average of all spectrum values within the bounds
*/
public float calcAvg(float lowFreq, float hiFreq) {
int lowBound = freqToIndex(lowFreq);
int hiBound = freqToIndex(hiFreq);
float avg = 0;
for (int i = lowBound; i <= hiBound; i++) {
avg += spectrum[i];
}
avg /= (hiBound - lowBound + 1);
return avg;
}
/**
* Get the Real part of the Complex representation of the spectrum.
*/
public float[] getSpectrumReal() {
return real;
}
/**
* Get the Imaginary part of the Complex representation of the spectrum.
*/
public float[] getSpectrumImaginary() {
return imag;
}
/**
* Performs a forward transform on <code>buffer</code>.
*
* @param buffer the buffer to analyze
*/
public abstract void forward(float[] buffer);
/**
* Performs a forward transform on values in <code>buffer</code>.
*
* @param buffer the buffer of samples
* @param startAt the index to start at in the buffer. there must be at least timeSize() samples
* between the starting index and the end of the buffer. If there aren't, an
* error will be issued and the operation will not be performed.
*/
public void forward(float[] buffer, int startAt) {
if (buffer.length - startAt < timeSize) {
return;
}
// copy the section of samples we want to analyze
float[] section = new float[timeSize];
System.arraycopy(buffer, startAt, section, 0, section.length);
forward(section);
}
/**
* Performs an inverse transform of the frequency spectrum and places the
* result in <code>buffer</code>.
*
* @param buffer the buffer to place the result of the inverse transform in
*/
public abstract void inverse(float[] buffer);
/**
* Performs an inverse transform of the frequency spectrum represented by
* freqReal and freqImag and places the result in buffer.
*
* @param freqReal the real part of the frequency spectrum
* @param freqImag the imaginary part the frequency spectrum
* @param buffer the buffer to place the inverse transform in
*/
public void inverse(float[] freqReal, float[] freqImag, float[] buffer) {
setComplex(freqReal, freqImag);
inverse(buffer);
}
/**
* FFT stands for Fast Fourier Transform. It is an efficient way to calculate the Complex
* Discrete Fourier Transform. There is not much to say about this class other than the fact
* that when you want to analyze the spectrum of an audio buffer you will almost always use
* this class. One restriction of this class is that the audio buffers you want to analyzeV
* must have a length that is a power of two. If you try to construct an FFT with a
* <code>timeSize</code> that is not a power of two, an IllegalArgumentException will be
* thrown.
*
* @author Damien Di Fede
* @see FourierTransform
* @see <a href="http://www.dspguide.com/ch12.htm">The Fast Fourier Transform</a>
*/
public static class FFT extends FourierTransform {
/**
* Constructs an FFT that will accept sample buffers that are
* <code>timeSize</code> long and have been recorded with a sample rate of
* <code>sampleRate</code>. <code>timeSize</code> <em>must</em> be a
* power of two. This will throw an exception if it is not.
*
* @param timeSize the length of the sample buffers you will be analyzing
* @param sampleRate the sample rate of the audio you will be analyzing
*/
public FFT(int timeSize, float sampleRate) {
super(timeSize, sampleRate);
if ((timeSize & (timeSize - 1)) != 0)
throw new IllegalArgumentException(
"FFT: timeSize must be a power of two.");
buildReverseTable();
buildTrigTables();
}
protected void allocateArrays() {
spectrum = new float[timeSize / 2 + 1];
real = new float[timeSize];
imag = new float[timeSize];
}
public void scaleBand(int i, float s) {
if (s < 0) {
// Minim.error("Can't scale a frequency band by a negative value.");
return;
}
real[i] *= s;
imag[i] *= s;
spectrum[i] *= s;
if (i != 0 && i != timeSize / 2) {
real[timeSize - i] = real[i];
imag[timeSize - i] = -imag[i];
}
}
public void setBand(int i, float a) {
if (a < 0) {
// Minim.error("Can't set a frequency band to a negative value.");
return;
}
if (real[i] == 0 && imag[i] == 0) {
real[i] = a;
spectrum[i] = a;
} else {
real[i] /= spectrum[i];
imag[i] /= spectrum[i];
spectrum[i] = a;
real[i] *= spectrum[i];
imag[i] *= spectrum[i];
}
if (i != 0 && i != timeSize / 2) {
real[timeSize - i] = real[i];
imag[timeSize - i] = -imag[i];
}
}
// performs an in-place fft on the data in the real and imag arrays
// bit reversing is not necessary as the data will already be bit reversed
private void fft() {
for (int halfSize = 1; halfSize < real.length; halfSize *= 2) {
// float k = -(float)Math.PI/halfSize;
// phase shift step
// float phaseShiftStepR = (float)Math.cos(k);
// float phaseShiftStepI = (float)Math.sin(k);
// using lookup table
float phaseShiftStepR = cos(halfSize);
float phaseShiftStepI = sin(halfSize);
// current phase shift
float currentPhaseShiftR = 1.0f;
float currentPhaseShiftI = 0.0f;
for (int fftStep = 0; fftStep < halfSize; fftStep++) {
for (int i = fftStep; i < real.length; i += 2 * halfSize) {
int off = i + halfSize;
float tr = (currentPhaseShiftR * real[off]) - (currentPhaseShiftI * imag[off]);
float ti = (currentPhaseShiftR * imag[off]) + (currentPhaseShiftI * real[off]);
real[off] = real[i] - tr;
imag[off] = imag[i] - ti;
real[i] += tr;
imag[i] += ti;
}
float tmpR = currentPhaseShiftR;
currentPhaseShiftR = (tmpR * phaseShiftStepR) - (currentPhaseShiftI * phaseShiftStepI);
currentPhaseShiftI = (tmpR * phaseShiftStepI) + (currentPhaseShiftI * phaseShiftStepR);
}
}
}
public void forward(float[] buffer) {
if (buffer.length != timeSize) {
// Minim.error("FFT.forward: The length of the passed sample buffer must be equal to timeSize().");
return;
}
// doWindow(buffer);
// copy samples to real/imag in bit-reversed order
bitReverseSamples(buffer, 0);
// perform the fft
fft();
// fill the spectrum buffer with amplitudes
fillSpectrum();
}
@Override
public void forward(float[] buffer, int startAt) {
if (buffer.length - startAt < timeSize) {
/* Minim.error( "FourierTransform.forward: not enough samples in the buffer between " +
startAt + " and " + buffer.length + " to perform a transform."
);
*/
return;
}
// windowFunction.apply( buffer, startAt, timeSize );
bitReverseSamples(buffer, startAt);
fft();
fillSpectrum();
}
/**
* Performs a forward transform on the passed buffers.
*
* @param buffReal the real part of the time domain signal to transform
* @param buffImag the imaginary part of the time domain signal to transform
*/
public void forward(float[] buffReal, float[] buffImag) {
if (buffReal.length != timeSize || buffImag.length != timeSize) {
// Minim.error("FFT.forward: The length of the passed buffers must be equal to timeSize().");
return;
}
setComplex(buffReal, buffImag);
bitReverseComplex();
fft();
fillSpectrum();
}
public void inverse(float[] buffer) {
if (buffer.length > real.length) {
// Minim.error("FFT.inverse: the passed array's length must equal FFT.timeSize().");
return;
}
// conjugate
for (int i = 0; i < timeSize; i++) {
imag[i] *= -1;
}
bitReverseComplex();
fft();
// copy the result in real into buffer, scaling as we do
for (int i = 0; i < buffer.length; i++) {
buffer[i] = real[i] / real.length;
}
}
private int[] reverse;
private void buildReverseTable() {
int N = timeSize;
reverse = new int[N];
// set up the bit reversing table
reverse[0] = 0;
for (int limit = 1, bit = N / 2; limit < N; limit <<= 1, bit >>= 1)
for (int i = 0; i < limit; i++)
reverse[i + limit] = reverse[i] + bit;
}
// copies the values in the samples array into the real array
// in bit reversed order. the imag array is filled with zeros.
private void bitReverseSamples(float[] samples, int startAt) {
for (int i = 0; i < timeSize; ++i) {
real[i] = samples[startAt + reverse[i]];
imag[i] = 0.0f;
}
}
// bit reverse real[] and imag[]
private void bitReverseComplex() {
float[] revReal = new float[real.length];
float[] revImag = new float[imag.length];
for (int i = 0; i < real.length; i++) {
revReal[i] = real[reverse[i]];
revImag[i] = imag[reverse[i]];
}
real = revReal;
imag = revImag;
}
// lookup tables
private float[] sinlookup;
private float[] coslookup;
private float sin(int i) {
return sinlookup[i];
}
private float cos(int i) {
return coslookup[i];
}
private void buildTrigTables() {
int N = timeSize;
sinlookup = new float[N];
coslookup = new float[N];
for (int i = 0; i < N; i++) {
sinlookup[i] = (float) Math.sin(-(float) Math.PI / i);
coslookup[i] = (float) Math.cos(-(float) Math.PI / i);
}
}
}
}

View File

@ -18,7 +18,6 @@ import android.graphics.BitmapFactory;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.media.ThumbnailUtils;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
@ -673,11 +672,11 @@ public class ImageLoader {
if (mediaType == FileLoader.MEDIA_DIR_IMAGE) { if (mediaType == FileLoader.MEDIA_DIR_IMAGE) {
originalBitmap = ImageLoader.loadBitmap(originalPath.toString(), null, size, size, false); originalBitmap = ImageLoader.loadBitmap(originalPath.toString(), null, size, size, false);
} else if (mediaType == FileLoader.MEDIA_DIR_VIDEO) { } else if (mediaType == FileLoader.MEDIA_DIR_VIDEO) {
originalBitmap = ThumbnailUtils.createVideoThumbnail(originalPath.toString(), info.big ? MediaStore.Video.Thumbnails.FULL_SCREEN_KIND : MediaStore.Video.Thumbnails.MINI_KIND); originalBitmap = SendMessagesHelper.createVideoThumbnail(originalPath.toString(), info.big ? MediaStore.Video.Thumbnails.FULL_SCREEN_KIND : MediaStore.Video.Thumbnails.MINI_KIND);
} else if (mediaType == FileLoader.MEDIA_DIR_DOCUMENT) { } else if (mediaType == FileLoader.MEDIA_DIR_DOCUMENT) {
String path = originalPath.toString().toLowerCase(); String path = originalPath.toString().toLowerCase();
if (path.endsWith("mp4")) { if (path.endsWith("mp4")) {
originalBitmap = ThumbnailUtils.createVideoThumbnail(originalPath.toString(), info.big ? MediaStore.Video.Thumbnails.FULL_SCREEN_KIND : MediaStore.Video.Thumbnails.MINI_KIND); originalBitmap = SendMessagesHelper.createVideoThumbnail(originalPath.toString(), info.big ? MediaStore.Video.Thumbnails.FULL_SCREEN_KIND : MediaStore.Video.Thumbnails.MINI_KIND);
} else if (path.endsWith(".jpg") || path.endsWith(".jpeg") || path.endsWith(".png") || path.endsWith(".gif")) { } else if (path.endsWith(".jpg") || path.endsWith(".jpeg") || path.endsWith(".png") || path.endsWith(".gif")) {
originalBitmap = ImageLoader.loadBitmap(path, null, size, size, false); originalBitmap = ImageLoader.loadBitmap(path, null, size, size, false);
} }
@ -1267,10 +1266,18 @@ public class ImageLoader {
Bitmap scaledBitmap; Bitmap scaledBitmap;
if (bitmapW > bitmapH && w_filter > h_filter) { if (bitmapW > bitmapH && w_filter > h_filter) {
float scaleFactor = bitmapW / w_filter; float scaleFactor = bitmapW / w_filter;
scaledBitmap = Bitmaps.createScaledBitmap(image, (int) w_filter, (int) (bitmapH / scaleFactor), true); if (scaleFactor > 1) {
scaledBitmap = Bitmaps.createScaledBitmap(image, (int) w_filter, (int) (bitmapH / scaleFactor), true);
} else {
scaledBitmap = image;
}
} else { } else {
float scaleFactor = bitmapH / h_filter; float scaleFactor = bitmapH / h_filter;
scaledBitmap = Bitmaps.createScaledBitmap(image, (int) (bitmapW / scaleFactor), (int) h_filter, true); if (scaleFactor > 1) {
scaledBitmap = Bitmaps.createScaledBitmap(image, (int) (bitmapW / scaleFactor), (int) h_filter, true);
} else {
scaledBitmap = image;
}
} }
if (image != scaledBitmap) { if (image != scaledBitmap) {
image.recycle(); image.recycle();
@ -1698,7 +1705,7 @@ public class ImageLoader {
public void fileLoadProgressChanged(final String location, long uploadedSize, long totalSize) { public void fileLoadProgressChanged(final String location, long uploadedSize, long totalSize) {
fileProgresses.put(location, new long[]{uploadedSize, totalSize}); fileProgresses.put(location, new long[]{uploadedSize, totalSize});
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 500) { if (lastProgressUpdateTime == 0 || lastProgressUpdateTime < currentTime - 500 || uploadedSize == 0) {
lastProgressUpdateTime = currentTime; lastProgressUpdateTime = currentTime;
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.FileLoadProgressChanged, location, uploadedSize, totalSize)); AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.FileLoadProgressChanged, location, uploadedSize, totalSize));
} }
@ -1851,17 +1858,17 @@ public class ImageLoader {
File srcFile = null; File srcFile = null;
File dstFile = null; File dstFile = null;
if (type == FileLoader.MEDIA_DIR_IMAGE) { if (type == FileLoader.MEDIA_DIR_IMAGE) {
srcFile = new File(from, "000000000_999999_temp.jpg"); srcFile = new File(from, "000000000_999999_temp.f");
dstFile = new File(to, "000000000_999999.jpg"); dstFile = new File(to, "000000000_999999.f");
} else if (type == FileLoader.MEDIA_DIR_DOCUMENT) { } else if (type == FileLoader.MEDIA_DIR_DOCUMENT) {
srcFile = new File(from, "000000000_999999_temp.doc"); srcFile = new File(from, "000000000_999999_temp.f");
dstFile = new File(to, "000000000_999999.doc"); dstFile = new File(to, "000000000_999999.f");
} else if (type == FileLoader.MEDIA_DIR_AUDIO) { } else if (type == FileLoader.MEDIA_DIR_AUDIO) {
srcFile = new File(from, "000000000_999999_temp.ogg"); srcFile = new File(from, "000000000_999999_temp.f");
dstFile = new File(to, "000000000_999999.ogg"); dstFile = new File(to, "000000000_999999.f");
} else if (type == FileLoader.MEDIA_DIR_VIDEO) { } else if (type == FileLoader.MEDIA_DIR_VIDEO) {
srcFile = new File(from, "000000000_999999_temp.mp4"); srcFile = new File(from, "000000000_999999_temp.f");
dstFile = new File(to, "000000000_999999.mp4"); dstFile = new File(to, "000000000_999999.f");
} }
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
srcFile.createNewFile(); srcFile.createNewFile();
@ -2282,7 +2289,7 @@ public class ImageLoader {
boolean isEncrypted = imageLocation.isEncrypted(); boolean isEncrypted = imageLocation.isEncrypted();
CacheImage img = new CacheImage(); CacheImage img = new CacheImage();
if (!currentKeyQuality) { if (!currentKeyQuality) {
if (MessageObject.isGifDocument(imageLocation.webFile) || MessageObject.isGifDocument(imageLocation.document) || MessageObject.isRoundVideoDocument(imageLocation.document)) { if (imageLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION || MessageObject.isGifDocument(imageLocation.webFile) || MessageObject.isGifDocument(imageLocation.document) || MessageObject.isRoundVideoDocument(imageLocation.document)) {
img.imageType = FileLoader.IMAGE_TYPE_ANIMATION; img.imageType = FileLoader.IMAGE_TYPE_ANIMATION;
} else if (imageLocation.path != null) { } else if (imageLocation.path != null) {
String location = imageLocation.path; String location = imageLocation.path;
@ -2540,17 +2547,38 @@ public class ImageLoader {
imageKey = null; imageKey = null;
thumbKey = null; thumbKey = null;
mediaKey = null; mediaKey = null;
String ext = imageReceiver.getExt(); String imageExt;
if (ext == null) { if (imageLocation != null && imageLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION) {
ext = "jpg"; imageExt = "mp4";
} else {
imageExt = null;
}
String mediaExt;
if (mediaLocation != null && mediaLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION) {
mediaExt = "mp4";
} else {
mediaExt = null;
}
String thumbExt = imageReceiver.getExt();
if (thumbExt == null) {
thumbExt = "jpg";
}
if (imageExt == null) {
imageExt = thumbExt;
}
if (mediaExt == null) {
mediaExt = thumbExt;
} }
for (int a = 0; a < 2; a++) { for (int a = 0; a < 2; a++) {
ImageLocation object; ImageLocation object;
String ext;
if (a == 0) { if (a == 0) {
object = imageLocation; object = imageLocation;
ext = imageExt;
} else { } else {
object = mediaLocation; object = mediaLocation;
ext = mediaExt;
} }
if (object == null) { if (object == null) {
continue; continue;
@ -2627,9 +2655,9 @@ public class ImageLoader {
if (thumbLocation.path != null) { if (thumbLocation.path != null) {
thumbUrl = thumbUrl + "." + getHttpUrlExtension(thumbLocation.path, "jpg"); thumbUrl = thumbUrl + "." + getHttpUrlExtension(thumbLocation.path, "jpg");
} else if (thumbLocation.photoSize instanceof TLRPC.TL_photoStrippedSize) { } else if (thumbLocation.photoSize instanceof TLRPC.TL_photoStrippedSize) {
thumbUrl = thumbUrl + "." + ext; thumbUrl = thumbUrl + "." + thumbExt;
} else if (thumbLocation.location != null) { } else if (thumbLocation.location != null) {
thumbUrl = thumbUrl + "." + ext; thumbUrl = thumbUrl + "." + thumbExt;
} }
} }
@ -2644,8 +2672,8 @@ public class ImageLoader {
} }
if (imageLocation != null && imageLocation.path != null) { if (imageLocation != null && imageLocation.path != null) {
createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, ext, thumbLocation, thumbFilter, 0, 1, ImageReceiver.TYPE_THUMB, thumbSet ? 2 : 1, guid); createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, thumbExt, thumbLocation, thumbFilter, 0, 1, ImageReceiver.TYPE_THUMB, thumbSet ? 2 : 1, guid);
createLoadOperationForImageReceiver(imageReceiver, imageKey, imageUrl, ext, imageLocation, imageFilter, imageReceiver.getSize(), 1, ImageReceiver.TYPE_IMAGE, 0, guid); createLoadOperationForImageReceiver(imageReceiver, imageKey, imageUrl, imageExt, imageLocation, imageFilter, imageReceiver.getSize(), 1, ImageReceiver.TYPE_IMAGE, 0, guid);
} else if (mediaLocation != null) { } else if (mediaLocation != null) {
int mediaCacheType = imageReceiver.getCacheType(); int mediaCacheType = imageReceiver.getCacheType();
int imageCacheType = 1; int imageCacheType = 1;
@ -2654,20 +2682,20 @@ public class ImageLoader {
} }
int thumbCacheType = mediaCacheType == 0 ? 1 : mediaCacheType; int thumbCacheType = mediaCacheType == 0 ? 1 : mediaCacheType;
if (!thumbSet) { if (!thumbSet) {
createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, ext, thumbLocation, thumbFilter, 0, thumbCacheType, ImageReceiver.TYPE_THUMB, thumbSet ? 2 : 1, guid); createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, thumbExt, thumbLocation, thumbFilter, 0, thumbCacheType, ImageReceiver.TYPE_THUMB, thumbSet ? 2 : 1, guid);
} }
if (!imageSet) { if (!imageSet) {
createLoadOperationForImageReceiver(imageReceiver, imageKey, imageUrl, ext, imageLocation, imageFilter, 0, imageCacheType, ImageReceiver.TYPE_IMAGE, 0, guid); createLoadOperationForImageReceiver(imageReceiver, imageKey, imageUrl, imageExt, imageLocation, imageFilter, 0, imageCacheType, ImageReceiver.TYPE_IMAGE, 0, guid);
} }
createLoadOperationForImageReceiver(imageReceiver, mediaKey, mediaUrl, ext, mediaLocation, mediaFilter, imageReceiver.getSize(), mediaCacheType, ImageReceiver.TYPE_MEDIA, 0, guid); createLoadOperationForImageReceiver(imageReceiver, mediaKey, mediaUrl, mediaExt, mediaLocation, mediaFilter, imageReceiver.getSize(), mediaCacheType, ImageReceiver.TYPE_MEDIA, 0, guid);
} else { } else {
int imageCacheType = imageReceiver.getCacheType(); int imageCacheType = imageReceiver.getCacheType();
if (imageCacheType == 0 && saveImageToCache) { if (imageCacheType == 0 && saveImageToCache) {
imageCacheType = 1; imageCacheType = 1;
} }
int thumbCacheType = imageCacheType == 0 ? 1 : imageCacheType; int thumbCacheType = imageCacheType == 0 ? 1 : imageCacheType;
createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, ext, thumbLocation, thumbFilter, 0, thumbCacheType, ImageReceiver.TYPE_THUMB, thumbSet ? 2 : 1, guid); createLoadOperationForImageReceiver(imageReceiver, thumbKey, thumbUrl, thumbExt, thumbLocation, thumbFilter, 0, thumbCacheType, ImageReceiver.TYPE_THUMB, thumbSet ? 2 : 1, guid);
createLoadOperationForImageReceiver(imageReceiver, imageKey, imageUrl, ext, imageLocation, imageFilter, imageReceiver.getSize(), imageCacheType, ImageReceiver.TYPE_IMAGE, 0, guid); createLoadOperationForImageReceiver(imageReceiver, imageKey, imageUrl, imageExt, imageLocation, imageFilter, imageReceiver.getSize(), imageCacheType, ImageReceiver.TYPE_IMAGE, 0, guid);
} }
} }
@ -2976,6 +3004,14 @@ public class ImageLoader {
} }
} }
scaleFactor /= bmOptions.inSampleSize;
if (scaleFactor > 1) {
if (matrix == null) {
matrix = new Matrix();
}
matrix.postScale(1.0f / scaleFactor, 1.0f / scaleFactor);
}
Bitmap b = null; Bitmap b = null;
if (path != null) { if (path != null) {
try { try {
@ -3055,7 +3091,7 @@ public class ImageLoader {
} }
} }
private static TLRPC.PhotoSize scaleAndSaveImageInternal(TLRPC.PhotoSize photoSize, Bitmap bitmap, int w, int h, float photoW, float photoH, float scaleFactor, int quality, boolean cache, boolean scaleAnyway, boolean forceCacheDir) throws Exception { private static TLRPC.PhotoSize scaleAndSaveImageInternal(TLRPC.PhotoSize photoSize, Bitmap bitmap, Bitmap.CompressFormat compressFormat, int w, int h, float photoW, float photoH, float scaleFactor, int quality, boolean cache, boolean scaleAnyway, boolean forceCacheDir) throws Exception {
Bitmap scaledBitmap; Bitmap scaledBitmap;
if (scaleFactor > 1 || scaleAnyway) { if (scaleFactor > 1 || scaleAnyway) {
scaledBitmap = Bitmaps.createScaledBitmap(bitmap, w, h, true); scaledBitmap = Bitmaps.createScaledBitmap(bitmap, w, h, true);
@ -3100,10 +3136,10 @@ public class ImageLoader {
} }
final File cacheFile = new File(fileDir, fileName); final File cacheFile = new File(fileDir, fileName);
FileOutputStream stream = new FileOutputStream(cacheFile); FileOutputStream stream = new FileOutputStream(cacheFile);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream); scaledBitmap.compress(compressFormat, quality, stream);
if (cache) { if (cache) {
ByteArrayOutputStream stream2 = new ByteArrayOutputStream(); ByteArrayOutputStream stream2 = new ByteArrayOutputStream();
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream2); scaledBitmap.compress(compressFormat, quality, stream2);
photoSize.bytes = stream2.toByteArray(); photoSize.bytes = stream2.toByteArray();
photoSize.size = photoSize.bytes.length; photoSize.size = photoSize.bytes.length;
stream2.close(); stream2.close();
@ -3119,18 +3155,22 @@ public class ImageLoader {
} }
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache) { public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache) {
return scaleAndSaveImage(null, bitmap, maxWidth, maxHeight, quality, cache, 0, 0, false); return scaleAndSaveImage(null, bitmap, Bitmap.CompressFormat.JPEG, maxWidth, maxHeight, quality, cache, 0, 0, false);
} }
public static TLRPC.PhotoSize scaleAndSaveImage(TLRPC.PhotoSize photoSize, Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache, boolean forceCacheDir) { public static TLRPC.PhotoSize scaleAndSaveImage(TLRPC.PhotoSize photoSize, Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache, boolean forceCacheDir) {
return scaleAndSaveImage(photoSize, bitmap, maxWidth, maxHeight, quality, cache, 0, 0, forceCacheDir); return scaleAndSaveImage(photoSize, bitmap, Bitmap.CompressFormat.JPEG, maxWidth, maxHeight, quality, cache, 0, 0, forceCacheDir);
} }
public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache, int minWidth, int minHeight) { public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache, int minWidth, int minHeight) {
return scaleAndSaveImage(null, bitmap, maxWidth, maxHeight, quality, cache, minWidth, minHeight, false); return scaleAndSaveImage(null, bitmap, Bitmap.CompressFormat.JPEG, maxWidth, maxHeight, quality, cache, minWidth, minHeight, false);
} }
public static TLRPC.PhotoSize scaleAndSaveImage(TLRPC.PhotoSize photoSize, Bitmap bitmap, float maxWidth, float maxHeight, int quality, boolean cache, int minWidth, int minHeight, boolean forceCacheDir) { public static TLRPC.PhotoSize scaleAndSaveImage(Bitmap bitmap, Bitmap.CompressFormat compressFormat, float maxWidth, float maxHeight, int quality, boolean cache, int minWidth, int minHeight) {
return scaleAndSaveImage(null, bitmap, compressFormat, maxWidth, maxHeight, quality, cache, minWidth, minHeight, false);
}
public static TLRPC.PhotoSize scaleAndSaveImage(TLRPC.PhotoSize photoSize, Bitmap bitmap, Bitmap.CompressFormat compressFormat, float maxWidth, float maxHeight, int quality, boolean cache, int minWidth, int minHeight, boolean forceCacheDir) {
if (bitmap == null) { if (bitmap == null) {
return null; return null;
} }
@ -3158,13 +3198,13 @@ public class ImageLoader {
} }
try { try {
return scaleAndSaveImageInternal(photoSize, bitmap, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway, forceCacheDir); return scaleAndSaveImageInternal(photoSize, bitmap, compressFormat, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway, forceCacheDir);
} catch (Throwable e) { } catch (Throwable e) {
FileLog.e(e); FileLog.e(e);
ImageLoader.getInstance().clearMemory(); ImageLoader.getInstance().clearMemory();
System.gc(); System.gc();
try { try {
return scaleAndSaveImageInternal(photoSize, bitmap, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway, forceCacheDir); return scaleAndSaveImageInternal(photoSize, bitmap, compressFormat, w, h, photoW, photoH, scaleFactor, quality, cache, scaleAnyway, forceCacheDir);
} catch (Throwable e2) { } catch (Throwable e2) {
FileLog.e(e2); FileLog.e(e2);
return null; return null;

View File

@ -176,6 +176,15 @@ public class ImageLocation {
return imageLocation; return imageLocation;
} }
public static ImageLocation getForDocument(TLRPC.TL_videoSize videoSize, TLRPC.Document document) {
if (videoSize == null || document == null) {
return null;
}
ImageLocation location = getForPhoto(videoSize.location, videoSize.size, null, document, null, false, document.dc_id, null, videoSize.type);
location.imageType = FileLoader.IMAGE_TYPE_ANIMATION;
return location;
}
public static ImageLocation getForDocument(TLRPC.PhotoSize photoSize, TLRPC.Document document) { public static ImageLocation getForDocument(TLRPC.PhotoSize photoSize, TLRPC.Document document) {
if (photoSize instanceof TLRPC.TL_photoStrippedSize) { if (photoSize instanceof TLRPC.TL_photoStrippedSize) {
ImageLocation imageLocation = new ImageLocation(); ImageLocation imageLocation = new ImageLocation();

View File

@ -124,6 +124,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private final static int TYPE_CROSSFDADE = 2; private final static int TYPE_CROSSFDADE = 2;
public final static int TYPE_MEDIA = 3; public final static int TYPE_MEDIA = 3;
public final static int DEFAULT_CROSSFADE_DURATION = 150;
private int currentAccount; private int currentAccount;
private View parentView; private View parentView;
@ -174,6 +176,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private int currentSize; private int currentSize;
private int currentCacheType; private int currentCacheType;
private boolean allowStartAnimation = true; private boolean allowStartAnimation = true;
private boolean allowStartLottieAnimation = true;
private boolean useSharedAnimationQueue; private boolean useSharedAnimationQueue;
private boolean allowDecodeSingleFrame; private boolean allowDecodeSingleFrame;
private int autoRepeat = 1; private int autoRepeat = 1;
@ -191,7 +194,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private boolean currentKeyQuality; private boolean currentKeyQuality;
private boolean invalidateAll; private boolean invalidateAll;
private int imageX, imageY, imageW, imageH; private float imageX, imageY, imageW, imageH;
private float sideClip; private float sideClip;
private RectF drawRegion = new RectF(); private RectF drawRegion = new RectF();
private boolean isVisible = true; private boolean isVisible = true;
@ -199,6 +202,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private boolean forcePreview; private boolean forcePreview;
private boolean forceCrossfade; private boolean forceCrossfade;
private int[] roundRadius = new int[4]; private int[] roundRadius = new int[4];
private boolean isRoundRect;
private Paint roundPaint; private Paint roundPaint;
private RectF roundRect = new RectF(); private RectF roundRect = new RectF();
@ -217,6 +221,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private boolean crossfadeWithThumb; private boolean crossfadeWithThumb;
private ColorFilter colorFilter; private ColorFilter colorFilter;
private boolean isRoundVideo; private boolean isRoundVideo;
private long startTime;
private long endTime;
private int crossfadeDuration = DEFAULT_CROSSFADE_DURATION;
private float pressedProgress;
private int animateFromIsPressed;
public ImageReceiver() { public ImageReceiver() {
this(null); this(null);
@ -322,7 +331,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (invalidateAll) { if (invalidateAll) {
parentView.invalidate(); parentView.invalidate();
} else { } else {
parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); parentView.invalidate((int) imageX, (int) imageY, (int) (imageX + imageW), (int) (imageY + imageH));
} }
} }
if (delegate != null) { if (delegate != null) {
@ -358,7 +367,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (delegate != null) { if (delegate != null) {
delegate.didSetImage(this, currentImageDrawable != null || currentThumbDrawable != null || staticThumbDrawable != null || currentMediaDrawable != null, currentImageDrawable == null && currentMediaDrawable == null, false); delegate.didSetImage(this, currentImageDrawable != null || currentThumbDrawable != null || staticThumbDrawable != null || currentMediaDrawable != null, currentImageDrawable == null && currentMediaDrawable == null, false);
} }
if (!canceledLoading && !forcePreview) { if (!canceledLoading) {
return; return;
} }
} }
@ -376,7 +385,20 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
} }
if (crossfadeWithOldImage) { if (crossfadeWithOldImage) {
if (currentImageDrawable != null) { if (currentMediaDrawable != null) {
if (currentMediaDrawable instanceof AnimatedFileDrawable) {
((AnimatedFileDrawable) currentMediaDrawable).stop();
}
recycleBitmap(thumbKey, TYPE_THUMB);
recycleBitmap(null, TYPE_CROSSFDADE);
recycleBitmap(mediaKey, TYPE_IMAGE);
crossfadeImage = currentMediaDrawable;
crossfadeShader = mediaShader;
crossfadeKey = currentImageKey;
crossfadingWithThumb = false;
currentMediaDrawable = null;
currentMediaKey = null;
} else if (currentImageDrawable != null) {
recycleBitmap(thumbKey, TYPE_THUMB); recycleBitmap(thumbKey, TYPE_THUMB);
recycleBitmap(null, TYPE_CROSSFDADE); recycleBitmap(null, TYPE_CROSSFDADE);
recycleBitmap(mediaKey, TYPE_MEDIA); recycleBitmap(mediaKey, TYPE_MEDIA);
@ -451,7 +473,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (invalidateAll) { if (invalidateAll) {
parentView.invalidate(); parentView.invalidate();
} else { } else {
parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); parentView.invalidate((int)imageX, (int) imageY, (int) (imageX + imageW), (int) (imageY + imageH));
} }
} }
@ -570,7 +592,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
} else if (bitmap instanceof RLottieDrawable) { } else if (bitmap instanceof RLottieDrawable) {
RLottieDrawable fileDrawable = (RLottieDrawable) bitmap; RLottieDrawable fileDrawable = (RLottieDrawable) bitmap;
fileDrawable.addParentView(parentView); fileDrawable.addParentView(parentView);
if (currentOpenedLayerFlags == 0) { if (allowStartLottieAnimation && currentOpenedLayerFlags == 0) {
fileDrawable.start(); fileDrawable.start();
} }
fileDrawable.setAllowDecodeSingleFrame(true); fileDrawable.setAllowDecodeSingleFrame(true);
@ -610,7 +632,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (invalidateAll) { if (invalidateAll) {
parentView.invalidate(); parentView.invalidate();
} else { } else {
parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); parentView.invalidate((int)imageX, (int) imageY, (int) (imageX + imageW), (int) (imageY + imageH));
} }
} }
if (forceCrossfade && crossfadeWithOldImage && crossfadeImage != null) { if (forceCrossfade && crossfadeWithOldImage && crossfadeImage != null) {
@ -687,6 +709,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
thumbShader = null; thumbShader = null;
} }
clearImage(); clearImage();
if (isPressed == 0) {
pressedProgress = 0f;
}
} }
private boolean setBackupImage() { private boolean setBackupImage() {
@ -696,7 +721,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
setImage(temp.mediaLocation, temp.mediaFilter, temp.imageLocation, temp.imageFilter, temp.thumbLocation, temp.thumbFilter, temp.thumb, temp.size, temp.ext, temp.parentObject, temp.cacheType); setImage(temp.mediaLocation, temp.mediaFilter, temp.imageLocation, temp.imageFilter, temp.thumbLocation, temp.thumbFilter, temp.thumb, temp.size, temp.ext, temp.parentObject, temp.cacheType);
temp.clear(); temp.clear();
setImageBackup = temp; setImageBackup = temp;
if (currentOpenedLayerFlags == 0) { if (allowStartLottieAnimation && currentOpenedLayerFlags == 0) {
RLottieDrawable lottieDrawable = getLottieAnimation(); RLottieDrawable lottieDrawable = getLottieAnimation();
if (lottieDrawable != null) { if (lottieDrawable != null) {
lottieDrawable.start(); lottieDrawable.start();
@ -716,7 +741,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (setBackupImage()) { if (setBackupImage()) {
return true; return true;
} }
if (currentOpenedLayerFlags == 0) { if (allowStartLottieAnimation && currentOpenedLayerFlags == 0) {
RLottieDrawable lottieDrawable = getLottieAnimation(); RLottieDrawable lottieDrawable = getLottieAnimation();
if (lottieDrawable != null) { if (lottieDrawable != null) {
lottieDrawable.start(); lottieDrawable.start();
@ -726,6 +751,28 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
} }
private void drawDrawable(Canvas canvas, Drawable drawable, int alpha, BitmapShader shader, int orientation) { private void drawDrawable(Canvas canvas, Drawable drawable, int alpha, BitmapShader shader, int orientation) {
if (isPressed == 0 && pressedProgress != 0) {
pressedProgress -= 16 / 150f;
if (pressedProgress < 0) {
pressedProgress = 0;
}
if (parentView != null) {
parentView.invalidate();
}
}
if (isPressed != 0) {
pressedProgress = 1f;
animateFromIsPressed = isPressed;
}
if (pressedProgress == 0 || pressedProgress == 1f) {
drawDrawable(canvas, drawable, alpha, shader, orientation, isPressed);
} else {
drawDrawable(canvas, drawable, alpha, shader, orientation, isPressed);
drawDrawable(canvas, drawable, (int) (alpha * pressedProgress), shader, orientation, animateFromIsPressed);
}
}
private void drawDrawable(Canvas canvas, Drawable drawable, int alpha, BitmapShader shader, int orientation, int isPressed) {
if (drawable instanceof BitmapDrawable) { if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
@ -805,14 +852,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
roundPaint.setAlpha(alpha); roundPaint.setAlpha(alpha);
roundRect.set(drawRegion); roundRect.set(drawRegion);
for (int a = 0; a < roundRadius.length; a++) { if (isRoundRect) {
radii[a * 2] = roundRadius[a]; canvas.drawRoundRect(roundRect,roundRadius[0], roundRadius[0],roundPaint);
radii[a * 2 + 1] = roundRadius[a]; } else {
for (int a = 0; a < roundRadius.length; a++) {
radii[a * 2] = roundRadius[a];
radii[a * 2 + 1] = roundRadius[a];
}
roundPath.reset();
roundPath.addRoundRect(roundRect, radii, Path.Direction.CW);
roundPath.close();
canvas.drawPath(roundPath, roundPaint);
} }
roundPath.reset();
roundPath.addRoundRect(roundRect, radii, Path.Direction.CW);
roundPath.close();
canvas.drawPath(roundPath, roundPaint);
} }
} else { } else {
roundPaint.setShader(shader); roundPaint.setShader(shader);
@ -851,14 +902,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
shader.setLocalMatrix(shaderMatrix); shader.setLocalMatrix(shaderMatrix);
roundPaint.setAlpha(alpha); roundPaint.setAlpha(alpha);
for (int a = 0; a < roundRadius.length; a++) { if (isRoundRect) {
radii[a * 2] = roundRadius[a]; canvas.drawRoundRect(roundRect,roundRadius[0], roundRadius[0],roundPaint);
radii[a * 2 + 1] = roundRadius[a]; } else {
for (int a = 0; a < roundRadius.length; a++) {
radii[a * 2] = roundRadius[a];
radii[a * 2 + 1] = roundRadius[a];
}
roundPath.reset();
roundPath.addRoundRect(roundRect, radii, Path.Direction.CW);
roundPath.close();
canvas.drawPath(roundPath, roundPaint);
} }
roundPath.reset();
roundPath.addRoundRect(roundRect, radii, Path.Direction.CW);
roundPath.close();
canvas.drawPath(roundPath, roundPaint);
} }
} }
} else { } else {
@ -1002,7 +1057,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (dt > 18) { if (dt > 18) {
dt = 18; dt = 18;
} }
currentAlpha += dt / 150.0f; currentAlpha += dt / (float) crossfadeDuration;
if (currentAlpha > 1) { if (currentAlpha > 1) {
currentAlpha = 1; currentAlpha = 1;
if (crossfadeImage != null) { if (crossfadeImage != null) {
@ -1016,7 +1071,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (invalidateAll) { if (invalidateAll) {
parentView.invalidate(); parentView.invalidate();
} else { } else {
parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); parentView.invalidate((int)imageX, (int) imageY, (int) (imageX + imageW), (int) (imageY + imageH));
} }
} }
} }
@ -1262,7 +1317,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (invalidateAll) { if (invalidateAll) {
parentView.invalidate(); parentView.invalidate();
} else { } else {
parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); parentView.invalidate((int) imageX, (int) imageY, (int) (imageX + imageW), (int) (imageY + imageH));
} }
} }
} }
@ -1329,7 +1384,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
imageW = width; imageW = width;
} }
public void setImageCoords(int x, int y, int width, int height) { public void setImageCoords(float x, float y, float width, float height) {
imageX = x; imageX = x;
imageY = y; imageY = y;
imageW = width; imageW = width;
@ -1348,27 +1403,27 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
return imageY + imageH / 2.0f; return imageY + imageH / 2.0f;
} }
public int getImageX() { public float getImageX() {
return imageX; return imageX;
} }
public int getImageX2() { public float getImageX2() {
return imageX + imageW; return imageX + imageW;
} }
public int getImageY() { public float getImageY() {
return imageY; return imageY;
} }
public int getImageY2() { public float getImageY2() {
return imageY + imageH; return imageY + imageH;
} }
public int getImageWidth() { public float getImageWidth() {
return imageW; return imageW;
} }
public int getImageHeight() { public float getImageHeight() {
return imageH; return imageH;
} }
@ -1458,14 +1513,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
public void setRoundRadius(int[] value) { public void setRoundRadius(int[] value) {
boolean changed = false; boolean changed = false;
int firstValue = value[0];
isRoundRect = true;
for (int a = 0; a < roundRadius.length; a++) { for (int a = 0; a < roundRadius.length; a++) {
if (roundRadius[a] != value[a]) { if (roundRadius[a] != value[a]) {
changed = true; changed = true;
break;
} }
if (firstValue != value[a]) {
isRoundRect = false;
}
roundRadius[a] = value[a];
} }
if (changed) { if (changed) {
System.arraycopy(value, 0, roundRadius, 0, roundRadius.length);
if (currentImageDrawable != null && imageShader == null) { if (currentImageDrawable != null && imageShader == null) {
updateDrawableRadius(currentImageDrawable); updateDrawableRadius(currentImageDrawable);
} }
@ -1534,6 +1593,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
allowStartAnimation = value; allowStartAnimation = value;
} }
public void setAllowStartLottieAnimation(boolean value) {
allowStartLottieAnimation = value;
}
public void setAllowDecodeSingleFrame(boolean value) { public void setAllowDecodeSingleFrame(boolean value) {
allowDecodeSingleFrame = value; allowDecodeSingleFrame = value;
} }
@ -1640,6 +1703,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
} }
if (!(drawable instanceof AnimatedFileDrawable)) { if (!(drawable instanceof AnimatedFileDrawable)) {
ImageLoader.getInstance().incrementUseCount(currentImageKey); ImageLoader.getInstance().incrementUseCount(currentImageKey);
} else {
((AnimatedFileDrawable) drawable).setStartEndTime(startTime, endTime);
} }
currentImageDrawable = drawable; currentImageDrawable = drawable;
if (drawable instanceof ExtendedBitmapDrawable) { if (drawable instanceof ExtendedBitmapDrawable) {
@ -1668,6 +1733,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
} }
if (!(drawable instanceof AnimatedFileDrawable)) { if (!(drawable instanceof AnimatedFileDrawable)) {
ImageLoader.getInstance().incrementUseCount(currentMediaKey); ImageLoader.getInstance().incrementUseCount(currentMediaKey);
} else {
((AnimatedFileDrawable) drawable).setStartEndTime(startTime, endTime);
} }
currentMediaDrawable = drawable; currentMediaDrawable = drawable;
updateDrawableRadius(drawable); updateDrawableRadius(drawable);
@ -1735,7 +1802,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
} else if (drawable instanceof RLottieDrawable) { } else if (drawable instanceof RLottieDrawable) {
RLottieDrawable fileDrawable = (RLottieDrawable) drawable; RLottieDrawable fileDrawable = (RLottieDrawable) drawable;
fileDrawable.addParentView(parentView); fileDrawable.addParentView(parentView);
if (currentOpenedLayerFlags == 0) { if (allowStartLottieAnimation && currentOpenedLayerFlags == 0) {
fileDrawable.start(); fileDrawable.start();
} }
fileDrawable.setAllowDecodeSingleFrame(true); fileDrawable.setAllowDecodeSingleFrame(true);
@ -1746,12 +1813,21 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
if (invalidateAll) { if (invalidateAll) {
parentView.invalidate(); parentView.invalidate();
} else { } else {
parentView.invalidate(imageX, imageY, imageX + imageW, imageY + imageH); parentView.invalidate((int) imageX, (int) imageY, (int) (imageX + imageW), (int) (imageY + imageH));
} }
} }
return true; return true;
} }
public void setMediaStartEndTime(long startTime, long endTime) {
this.startTime = startTime;
this.endTime = endTime;
if (currentMediaDrawable instanceof AnimatedFileDrawable) {
((AnimatedFileDrawable) currentMediaDrawable).setStartEndTime(startTime, endTime);
}
}
private void recycleBitmap(String newKey, int type) { private void recycleBitmap(String newKey, int type) {
String key; String key;
Drawable image; Drawable image;
@ -1816,6 +1892,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
} }
} }
public void setCrossfadeDuration(int duration) {
crossfadeDuration = duration;
}
@Override @Override
public void didReceivedNotification(int id, int account, Object... args) { public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.didReplacedPhotoInMemCache) { if (id == NotificationCenter.didReplacedPhotoInMemCache) {
@ -1861,7 +1941,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
currentOpenedLayerFlags &=~ layer; currentOpenedLayerFlags &=~ layer;
if (currentOpenedLayerFlags == 0) { if (currentOpenedLayerFlags == 0) {
RLottieDrawable lottieDrawable = getLottieAnimation(); RLottieDrawable lottieDrawable = getLottieAnimation();
if (lottieDrawable != null) { if (allowStartLottieAnimation && lottieDrawable != null) {
lottieDrawable.start(); lottieDrawable.start();
} }
} }

View File

@ -63,6 +63,7 @@ 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.BaseFragment; import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ChatActivity; import org.telegram.ui.ChatActivity;
import org.telegram.ui.Components.EmbedBottomSheet; import org.telegram.ui.Components.EmbedBottomSheet;
import org.telegram.ui.Components.PhotoFilterView; import org.telegram.ui.Components.PhotoFilterView;
@ -101,7 +102,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
public native byte[] getWaveform2(short[] array, int length); public native byte[] getWaveform2(short[] array, int length);
private class AudioBuffer { private static class AudioBuffer {
public AudioBuffer(int capacity) { public AudioBuffer(int capacity) {
buffer = ByteBuffer.allocateDirect(capacity); buffer = ByteBuffer.allocateDirect(capacity);
bufferBytes = new byte[capacity]; bufferBytes = new byte[capacity];
@ -190,7 +191,52 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
public float blurAngle; public float blurAngle;
} }
public static class PhotoEntry { public static class MediaEditState {
public CharSequence caption;
public String thumbPath;
public String imagePath;
public String filterPath;
public String paintPath;
public String fullPaintPath;
public String croppedPath;
public ArrayList<TLRPC.MessageEntity> entities;
public SavedFilterState savedFilterState;
public ArrayList<VideoEditedInfo.MediaEntity> mediaEntities;
public ArrayList<TLRPC.InputDocument> stickers;
public VideoEditedInfo editedInfo;
public long averageDuration;
public boolean isFiltered;
public boolean isPainted;
public boolean isCropped;
public int ttl;
public String getPath() {
return null;
}
public void reset() {
caption = null;
thumbPath = null;
filterPath = null;
imagePath = null;
paintPath = null;
isFiltered = false;
isPainted = false;
isCropped = false;
ttl = 0;
mediaEntities = null;
editedInfo = null;
entities = null;
savedFilterState = null;
croppedPath = null;
stickers = null;
}
}
public static class PhotoEntry extends MediaEditState {
public int bucketId; public int bucketId;
public int imageId; public int imageId;
public long dateTaken; public long dateTaken;
@ -200,20 +246,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
public long size; public long size;
public String path; public String path;
public int orientation; public int orientation;
public String thumbPath;
public String imagePath;
public VideoEditedInfo editedInfo;
public boolean isVideo; public boolean isVideo;
public CharSequence caption;
public ArrayList<TLRPC.MessageEntity> entities;
public boolean isFiltered;
public boolean isPainted;
public boolean isCropped;
public boolean isMuted; public boolean isMuted;
public int ttl;
public boolean canDeleteAfter; public boolean canDeleteAfter;
public SavedFilterState savedFilterState;
public ArrayList<TLRPC.InputDocument> stickers = new ArrayList<>();
public PhotoEntry(int bucketId, int imageId, long dateTaken, String path, int orientation, boolean isVideo, int width, int height, long size) { public PhotoEntry(int bucketId, int imageId, long dateTaken, String path, int orientation, boolean isVideo, int width, int height, long size) {
this.bucketId = bucketId; this.bucketId = bucketId;
@ -231,24 +266,24 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
this.isVideo = isVideo; this.isVideo = isVideo;
} }
@Override
public String getPath() {
return path;
}
@Override
public void reset() { public void reset() {
isFiltered = false; if (isVideo) {
isPainted = false; if (filterPath != null) {
isCropped = false; new File(filterPath).delete();
ttl = 0; filterPath = null;
imagePath = null; }
if (!isVideo) {
thumbPath = null;
} }
editedInfo = null; super.reset();
caption = null;
entities = null;
savedFilterState = null;
stickers.clear();
} }
} }
public static class SearchImage { public static class SearchImage extends MediaEditState {
public String id; public String id;
public String imageUrl; public String imageUrl;
public String thumbUrl; public String thumbUrl;
@ -257,34 +292,28 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
public int size; public int size;
public int type; public int type;
public int date; public int date;
public String thumbPath;
public String imagePath;
public CharSequence caption; public CharSequence caption;
public ArrayList<TLRPC.MessageEntity> entities;
public TLRPC.Document document; public TLRPC.Document document;
public TLRPC.Photo photo; public TLRPC.Photo photo;
public TLRPC.PhotoSize photoSize; public TLRPC.PhotoSize photoSize;
public TLRPC.PhotoSize thumbPhotoSize; public TLRPC.PhotoSize thumbPhotoSize;
public boolean isFiltered;
public boolean isPainted;
public boolean isCropped;
public int ttl;
public TLRPC.BotInlineResult inlineResult; public TLRPC.BotInlineResult inlineResult;
public HashMap<String, String> params; public HashMap<String, String> params;
public SavedFilterState savedFilterState;
public ArrayList<TLRPC.InputDocument> stickers = new ArrayList<>();
@Override
public String getPath() {
if (photoSize != null) {
return FileLoader.getPathToAttach(photoSize, true).getAbsolutePath();
} else if (document != null) {
return FileLoader.getPathToAttach(document, true).getAbsolutePath();
} else {
return ImageLoader.getHttpFilePath(imageUrl, "jpg").getAbsolutePath();
}
}
@Override
public void reset() { public void reset() {
isFiltered = false; super.reset();
isPainted = false;
isCropped = false;
ttl = 0;
imagePath = null;
thumbPath = null;
caption = null;
entities = null;
savedFilterState = null;
stickers.clear();
} }
public String getAttachName() { public String getAttachName() {
@ -1619,6 +1648,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
FileLog.e(e); FileLog.e(e);
} }
audioPlayer = null; audioPlayer = null;
Theme.unrefAudioVisualizeDrawable(playingMessageObject);
} else if (videoPlayer != null) { } else if (videoPlayer != null) {
currentAspectRatioFrameLayout = null; currentAspectRatioFrameLayout = null;
currentTextureViewContainer = null; currentTextureViewContainer = null;
@ -1877,6 +1907,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
FileLog.e(e); FileLog.e(e);
} }
audioPlayer = null; audioPlayer = null;
Theme.unrefAudioVisualizeDrawable(playingMessageObject);
} else if (videoPlayer != null) { } else if (videoPlayer != null) {
currentAspectRatioFrameLayout = null; currentAspectRatioFrameLayout = null;
currentTextureViewContainer = null; currentTextureViewContainer = null;
@ -2213,7 +2244,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
} }
@Override @Override
public void onError(Exception e) { public void onError(VideoPlayer player, Exception e) {
FileLog.e(e); FileLog.e(e);
} }
@ -2425,7 +2456,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
} }
@Override @Override
public void onError(Exception e) { public void onError(VideoPlayer player, Exception e) {
FileLog.e(e); FileLog.e(e);
} }
@ -2585,7 +2616,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
} }
@Override @Override
public void onError(Exception e) { public void onError(VideoPlayer player, Exception e) {
} }
@ -2609,6 +2640,17 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
return false; return false;
} }
}); });
audioPlayer.setAudioVisualizerDelegate(new VideoPlayer.AudioVisualizerDelegate() {
@Override
public void onVisualizerUpdate(boolean playing, boolean animate, float[] values) {
Theme.getCurrentAudiVisualizerDrawable().setWaveform(playing, animate, values);
}
@Override
public boolean needUpdate() {
return Theme.getCurrentAudiVisualizerDrawable().getParentView() != null;
}
});
if (exists) { if (exists) {
if (!messageObject.mediaExists && cacheFile != file) { if (!messageObject.mediaExists && cacheFile != file) {
AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, FileLoader.getAttachFileName(messageObject.getDocument()), cacheFile)); AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(messageObject.currentAccount).postNotificationName(NotificationCenter.fileDidLoad, FileLoader.getAttachFileName(messageObject.getDocument()), cacheFile));
@ -2667,6 +2709,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
if (audioPlayer != null) { if (audioPlayer != null) {
audioPlayer.releasePlayer(true); audioPlayer.releasePlayer(true);
audioPlayer = null; audioPlayer = null;
Theme.unrefAudioVisualizeDrawable(playingMessageObject);
isPaused = false; isPaused = false;
playingMessageObject = null; playingMessageObject = null;
downloadingCurrentMessage = false; downloadingCurrentMessage = false;
@ -3798,7 +3841,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
rotateRender = 90; rotateRender = 90;
} }
boolean needCompress = resultWidth != originalWidth || resultHeight != originalHeight || rotateRender != 0 boolean needCompress = info.mediaEntities != null || info.paintPath != null || info.filterState != null || resultWidth != originalWidth || resultHeight != originalHeight || rotateRender != 0
|| info.roundVideo || Build.VERSION.SDK_INT >= 18 && startTime != -1; || info.roundVideo || Build.VERSION.SDK_INT >= 18 && startTime != -1;
@ -3842,6 +3885,10 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
framerate, bitrate, framerate, bitrate,
startTime, endTime, startTime, endTime,
needCompress, duration, needCompress, duration,
info.filterState,
info.paintPath,
info.mediaEntities,
info.isPhoto,
callback); callback);
@ -3900,10 +3947,13 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
int remeasuredBitrate = (int) (originalBitrate / (Math.min(originalHeight / (float) (height), originalWidth / (float) (width)))); int remeasuredBitrate = (int) (originalBitrate / (Math.min(originalHeight / (float) (height), originalWidth / (float) (width))));
remeasuredBitrate *= compressFactor; remeasuredBitrate *= compressFactor;
int minBitrate = (int) (getVideoBitrateWithFactor(minCompressFactor) / (1280f * 720f / (width * height))); int minBitrate = (int) (getVideoBitrateWithFactor(minCompressFactor) / (1280f * 720f / (width * height)));
if (originalBitrate < minBitrate) return remeasuredBitrate; if (originalBitrate < minBitrate) {
if (remeasuredBitrate > maxBitrate) return maxBitrate; return remeasuredBitrate;
if (remeasuredBitrate < minBitrate) return minBitrate; }
return remeasuredBitrate; if (remeasuredBitrate > maxBitrate) {
return maxBitrate;
}
return Math.max(remeasuredBitrate, minBitrate);
} }
private static int getVideoBitrateWithFactor(float f) { private static int getVideoBitrateWithFactor(float f) {

View File

@ -66,6 +66,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import tw.nekomimi.nekogram.NekoConfig; import tw.nekomimi.nekogram.NekoConfig;
@ -132,7 +133,7 @@ public class MediaDataController extends BaseController {
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 ConcurrentHashMap<String, TLRPC.TL_messages_stickerSet> stickerSetsByName = new ConcurrentHashMap<>(100, 1.0f, 1);
private HashMap<String, TLRPC.TL_messages_stickerSet> diceStickerSetsByEmoji = new HashMap<>(); private HashMap<String, TLRPC.TL_messages_stickerSet> diceStickerSetsByEmoji = new HashMap<>();
private LongSparseArray<String> diceEmojiStickerSetsById = new LongSparseArray<>(); private LongSparseArray<String> diceEmojiStickerSetsById = new LongSparseArray<>();
private HashSet<String> loadingDiceStickerSets = new HashSet<>(); private HashSet<String> loadingDiceStickerSets = new HashSet<>();
@ -143,6 +144,8 @@ public class MediaDataController extends BaseController {
private int[] loadHash = new int[5]; private int[] loadHash = new int[5];
private int[] loadDate = new int[5]; private int[] loadDate = new int[5];
private HashMap<String, ArrayList<TLRPC.Message>> verifyingMessages = new HashMap<>();
private int[] archivedStickersCount = new int[2]; private int[] archivedStickersCount = new int[2];
private LongSparseArray<String> stickersByEmoji = new LongSparseArray<>(); private LongSparseArray<String> stickersByEmoji = new LongSparseArray<>();
@ -211,6 +214,7 @@ public class MediaDataController extends BaseController {
} }
}); });
} }
verifyingMessages.clear();
loading = false; loading = false;
loaded = false; loaded = false;
@ -358,7 +362,12 @@ public class MediaDataController extends BaseController {
} }
public void removeRecentGif(final TLRPC.Document document) { public void removeRecentGif(final TLRPC.Document document) {
recentGifs.remove(document); for (int i = 0, N = recentGifs.size(); i < N; i++) {
if (recentGifs.get(i).id == document.id) {
recentGifs.remove(i);
break;
}
}
TLRPC.TL_messages_saveGif req = new TLRPC.TL_messages_saveGif(); TLRPC.TL_messages_saveGif req = new TLRPC.TL_messages_saveGif();
req.id = new TLRPC.TL_inputDocument(); req.id = new TLRPC.TL_inputDocument();
req.id.id = document.id; req.id.id = document.id;
@ -943,6 +952,11 @@ public class MediaDataController extends BaseController {
loadHash[type] = calcStickersHash(stickerSets[type]); loadHash[type] = calcStickersHash(stickerSets[type]);
} }
public void storeTempStickerSet(final TLRPC.TL_messages_stickerSet set) {
stickerSetsById.put(set.set.id, set);
stickerSetsByName.put(set.set.short_name, set);
}
public void addNewStickerSet(final TLRPC.TL_messages_stickerSet set) { public void addNewStickerSet(final TLRPC.TL_messages_stickerSet set) {
if (stickerSetsById.indexOfKey(set.set.id) >= 0 || stickerSetsByName.containsKey(set.set.short_name)) { if (stickerSetsById.indexOfKey(set.set.id) >= 0 || stickerSetsByName.containsKey(set.set.short_name)) {
return; return;
@ -1205,6 +1219,76 @@ public class MediaDataController extends BaseController {
return archivedStickersCount[type]; return archivedStickersCount[type];
} }
public void verifyAnimatedStickerMessage(TLRPC.Message message) {
verifyAnimatedStickerMessage(message, false);
}
public void verifyAnimatedStickerMessage(TLRPC.Message message, boolean safe) {
if (message == null) {
return;
}
TLRPC.Document document = MessageObject.getDocument(message);
String name = MessageObject.getStickerSetName(document);
if (TextUtils.isEmpty(name)) {
return;
}
TLRPC.TL_messages_stickerSet stickerSet = stickerSetsByName.get(name);
if (stickerSet != null) {
for (int a = 0, N = stickerSet.documents.size(); a < N; a++) {
TLRPC.Document sticker = stickerSet.documents.get(a);
if (sticker.id == document.id && sticker.dc_id == document.dc_id) {
message.stickerVerified = 1;
break;
}
}
return;
}
if (safe) {
AndroidUtilities.runOnUIThread(() -> verifyAnimatedStickerMessageInternal(message, name));
} else {
verifyAnimatedStickerMessageInternal(message, name);
}
}
private void verifyAnimatedStickerMessageInternal(TLRPC.Message message, String name) {
ArrayList<TLRPC.Message> messages = verifyingMessages.get(name);
if (messages == null) {
messages = new ArrayList<>();
verifyingMessages.put(name, messages);
}
messages.add(message);
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
req.stickerset = MessageObject.getInputStickerSet(message);
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
ArrayList<TLRPC.Message> arrayList = verifyingMessages.get(name);
if (response != null) {
TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response;
storeTempStickerSet(set);
for (int b = 0, N2 = arrayList.size(); b < N2; b++) {
TLRPC.Message m = arrayList.get(b);
TLRPC.Document d = MessageObject.getDocument(m);
for (int a = 0, N = set.documents.size(); a < N; a++) {
TLRPC.Document sticker = set.documents.get(a);
if (sticker.id == d.id && sticker.dc_id == d.dc_id) {
m.stickerVerified = 1;
break;
}
}
if (m.stickerVerified == 0) {
m.stickerVerified = 2;
}
}
} else {
for (int b = 0, N2 = arrayList.size(); b < N2; b++) {
arrayList.get(b).stickerVerified = 2;
}
}
getNotificationCenter().postNotificationName(NotificationCenter.didVerifyMessagesStickers, arrayList);
getMessagesStorage().updateMessageVerifyFlags(arrayList);
}));
}
public void loadArchivedStickersCount(final int type, boolean cache) { public void loadArchivedStickersCount(final int type, boolean cache) {
if (cache) { if (cache) {
SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount);
@ -1509,7 +1593,6 @@ public class MediaDataController extends BaseController {
TLRPC.TL_messages_stickerSet stickerSet = stickerSetsById.get(setId); TLRPC.TL_messages_stickerSet stickerSet = stickerSetsById.get(setId);
if (stickerSet != null) { if (stickerSet != null) {
return stickerSet.set.short_name; return stickerSet.set.short_name;
} }
TLRPC.StickerSetCovered stickerSetCovered = featuredStickerSetsById.get(setId); TLRPC.StickerSetCovered stickerSetCovered = featuredStickerSetsById.get(setId);
if (stickerSetCovered != null) { if (stickerSetCovered != null) {
@ -2398,7 +2481,7 @@ public class MediaDataController extends BaseController {
putMediaDatabase(uid, type, res.messages, max_id, topReached); putMediaDatabase(uid, type, res.messages, max_id, topReached);
} }
Utilities.globalQueue.postRunnable(() -> { Utilities.searchQueue.postRunnable(() -> {
final SparseArray<TLRPC.User> usersDict = new SparseArray<>(); final SparseArray<TLRPC.User> usersDict = new SparseArray<>();
for (int a = 0; a < res.users.size(); a++) { for (int a = 0; a < res.users.size(); a++) {
TLRPC.User u = res.users.get(a); TLRPC.User u = res.users.get(a);

View File

@ -32,6 +32,7 @@ import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLObject; 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.Cells.ChatMessageCell;
import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TextStyleSpan;
import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.TypefaceSpan;
import org.telegram.ui.Components.URLSpanBotCommand; import org.telegram.ui.Components.URLSpanBotCommand;
@ -106,6 +107,7 @@ public class MessageObject {
public ArrayList<TLRPC.PhotoSize> photoThumbs; public ArrayList<TLRPC.PhotoSize> photoThumbs;
public ArrayList<TLRPC.PhotoSize> photoThumbs2; public ArrayList<TLRPC.PhotoSize> photoThumbs2;
public VideoEditedInfo videoEditedInfo; public VideoEditedInfo videoEditedInfo;
public boolean shouldRemoveVideoEditedInfo;
public boolean viewsReloaded; public boolean viewsReloaded;
public boolean pollVisibleOnScreen; public boolean pollVisibleOnScreen;
public long pollLastCheckTime; public long pollLastCheckTime;
@ -119,6 +121,8 @@ public class MessageObject {
public boolean isRestrictedMessage; public boolean isRestrictedMessage;
public long loadedFileSize; public long loadedFileSize;
public int stableId;
public boolean wasUnread; public boolean wasUnread;
public boolean hadAnimationNotReadyLoading; public boolean hadAnimationNotReadyLoading;
@ -354,12 +358,14 @@ public class MessageObject {
public static class GroupedMessages { public static class GroupedMessages {
public long groupId; public long groupId;
public boolean hasSibling; public boolean hasSibling;
public boolean hasCaption;
public ArrayList<MessageObject> messages = new ArrayList<>(); public ArrayList<MessageObject> messages = new ArrayList<>();
public ArrayList<GroupedMessagePosition> posArray = new ArrayList<>(); public ArrayList<GroupedMessagePosition> posArray = new ArrayList<>();
public HashMap<MessageObject, GroupedMessagePosition> positions = new HashMap<>(); public HashMap<MessageObject, GroupedMessagePosition> positions = new HashMap<>();
private int maxSizeWidth = 800; private int maxSizeWidth = 800;
private int firstSpanAdditionalSize = 200;
public final TransitionParams transitionParams = new TransitionParams();
private static class MessageGroupedLayoutAttempt { private static class MessageGroupedLayoutAttempt {
@ -393,6 +399,10 @@ public class MessageObject {
public void calculate() { public void calculate() {
posArray.clear(); posArray.clear();
positions.clear(); positions.clear();
maxSizeWidth = 800;
int firstSpanAdditionalSize = 200;
int count = messages.size(); int count = messages.size();
if (count <= 1) { if (count <= 1) {
return; return;
@ -407,6 +417,8 @@ public class MessageObject {
boolean needShare = false; boolean needShare = false;
hasSibling = false; hasSibling = false;
hasCaption = false;
for (int a = 0; a < count; a++) { for (int a = 0; a < count; a++) {
MessageObject messageObject = messages.get(a); MessageObject messageObject = messages.get(a);
if (a == 0) { if (a == 0) {
@ -438,6 +450,10 @@ public class MessageObject {
positions.put(messageObject, position); positions.put(messageObject, position);
posArray.add(position); posArray.add(position);
if (messageObject.caption != null) {
hasCaption = true;
}
} }
if (needShare) { if (needShare) {
@ -750,6 +766,29 @@ public class MessageObject {
} }
return null; return null;
} }
public static class TransitionParams {
public int left;
public int top;
public int right;
public int bottom;
public float offsetLeft;
public float offsetTop;
public float offsetRight;
public float offsetBottom;
public boolean drawBackgroundForDeletedItems;
public boolean backgroundChangeBounds;
public boolean pinnedTop;
public boolean pinnedBotton;
public ChatMessageCell cell;
public float captionEnterProgress = 1f;
public boolean drawCaptionLayout;
public boolean isNewGroup;
}
} }
private static final int LINES_PER_BLOCK = 10; private static final int LINES_PER_BLOCK = 10;
@ -2494,8 +2533,8 @@ public class MessageObject {
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) { } else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) {
messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia).replace("https://telegram.org/update", "https://github.com/NekoX-Dev/NekoX/blob/master/Update.md"); messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia).replace("https://telegram.org/update", "https://github.com/NekoX-Dev/NekoX/blob/master/Update.md");
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { } else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
if (isSticker() || isAnimatedSticker()) { if (isSticker() || isAnimatedStickerDocument(getDocument(), true)) {
String sch = getStrickerChar(); String sch = getStickerChar();
if (sch != null && sch.length() > 0) { if (sch != null && sch.length() > 0) {
messageText = String.format("%s %s", sch, LocaleController.getString("AttachSticker", R.string.AttachSticker)); messageText = String.format("%s %s", sch, LocaleController.getString("AttachSticker", R.string.AttachSticker));
} else { } else {
@ -2526,6 +2565,7 @@ public class MessageObject {
public void setType() { public void setType() {
int oldType = type; int oldType = type;
type = 1000;
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 (isRestrictedMessage) { if (isRestrictedMessage) {
@ -4299,8 +4339,8 @@ public class MessageObject {
} }
for (int a = 0, N = document.attributes.size(); a < N; a++) { for (int a = 0, N = document.attributes.size(); a < N; a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a); TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeSticker && attribute.stickerset != null && !(attribute.stickerset instanceof TLRPC.TL_inputStickerSetEmpty)) { if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
return true; return attribute.stickerset instanceof TLRPC.TL_inputStickerSetShortName;
} }
} }
} }
@ -4367,34 +4407,41 @@ public class MessageObject {
return false; return false;
} }
public static boolean isVideoDocument(TLRPC.Document document) { public static TLRPC.TL_videoSize getDocumentVideoThumb(TLRPC.Document document) {
if (document != null) { if (document == null || document.video_thumbs.isEmpty()) {
boolean isAnimated = false; return null;
boolean isVideo = false;
int width = 0;
int height = 0;
for (int a = 0; a < document.attributes.size(); a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeVideo) {
if (attribute.round_message) {
return false;
}
isVideo = true;
width = attribute.w;
height = attribute.h;
} else if (attribute instanceof TLRPC.TL_documentAttributeAnimated) {
isAnimated = true;
}
}
if (isAnimated && (width > 1280 || height > 1280)) {
isAnimated = false;
}
if (SharedConfig.streamMkv && !isVideo && "video/x-matroska".equals(document.mime_type)) {
isVideo = true;
}
return isVideo && !isAnimated;
} }
return false; return document.video_thumbs.get(0);
}
public static boolean isVideoDocument(TLRPC.Document document) {
if (document == null) {
return false;
}
boolean isAnimated = false;
boolean isVideo = false;
int width = 0;
int height = 0;
for (int a = 0; a < document.attributes.size(); a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeVideo) {
if (attribute.round_message) {
return false;
}
isVideo = true;
width = attribute.w;
height = attribute.h;
} else if (attribute instanceof TLRPC.TL_documentAttributeAnimated) {
isAnimated = true;
}
}
if (isAnimated && (width > 1280 || height > 1280)) {
isAnimated = false;
}
if (SharedConfig.streamMkv && !isVideo && "video/x-matroska".equals(document.mime_type)) {
isVideo = true;
}
return isVideo && !isAnimated;
} }
public TLRPC.Document getDocument() { public TLRPC.Document getDocument() {
@ -4425,7 +4472,11 @@ public class MessageObject {
} }
public static boolean isAnimatedStickerMessage(TLRPC.Message message) { public static boolean isAnimatedStickerMessage(TLRPC.Message message) {
return message.media != null && isAnimatedStickerDocument(message.media.document, !DialogObject.isSecretDialogId(message.dialog_id)); boolean isSecretChat = DialogObject.isSecretDialogId(message.dialog_id);
if (isSecretChat && message.stickerVerified != 1) {
return false;
}
return message.media != null && isAnimatedStickerDocument(message.media.document, !isSecretChat || message.out);
} }
public static boolean isLocationMessage(TLRPC.Message message) { public static boolean isLocationMessage(TLRPC.Message message) {
@ -4536,7 +4587,23 @@ public class MessageObject {
return -1; return -1;
} }
public String getStrickerChar() { public static String getStickerSetName(TLRPC.Document document) {
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.stickerset instanceof TLRPC.TL_inputStickerSetEmpty) {
return null;
}
return attribute.stickerset.short_name;
}
}
return null;
}
public String getStickerChar() {
TLRPC.Document document = getDocument(); TLRPC.Document document = getDocument();
if (document != null) { if (document != null) {
for (TLRPC.DocumentAttribute attribute : document.attributes) { for (TLRPC.DocumentAttribute attribute : document.attributes) {
@ -4695,7 +4762,11 @@ public class MessageObject {
if (type != 1000) { if (type != 1000) {
return type == TYPE_ANIMATED_STICKER; return type == TYPE_ANIMATED_STICKER;
} }
return isAnimatedStickerDocument(getDocument(), !DialogObject.isSecretDialogId(getDialogId())); boolean isSecretChat = DialogObject.isSecretDialogId(getDialogId());
if (isSecretChat && messageOwner.stickerVerified != 1) {
return false;
}
return isAnimatedStickerDocument(getDocument(), emojiAnimatedSticker != null || !isSecretChat || isOut());
} }
public boolean isAnyKindOfSticker() { public boolean isAnyKindOfSticker() {
@ -4749,8 +4820,21 @@ public class MessageObject {
return isRoundVideoCached == 1; return isRoundVideoCached == 1;
} }
public boolean hasPhotoStickers() { public boolean hasAttachedStickers() {
return messageOwner.media != null && messageOwner.media.photo != null && messageOwner.media.photo.has_stickers; if (messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) {
return messageOwner.media.photo != null && messageOwner.media.photo.has_stickers;
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
TLRPC.Document document = messageOwner.media.document;
if (document != null) {
for (int a = 0; a < document.attributes.size(); a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeHasStickers) {
return true;
}
}
}
}
return false;
} }
public boolean isGif() { public boolean isGif() {
@ -4979,7 +5063,7 @@ public class MessageObject {
} }
public boolean canForwardMessage() { public boolean canForwardMessage() {
return !(messageOwner instanceof TLRPC.TL_message_secret) && !needDrawBluredPreview() && !isLiveLocation() && type != 16; return NekoXConfig.disableFlagSecure || !(messageOwner instanceof TLRPC.TL_message_secret) && !needDrawBluredPreview() && !isLiveLocation() && type != 16;
} }
public boolean canEditMedia() { public boolean canEditMedia() {
@ -5234,10 +5318,6 @@ public class MessageObject {
mediaExists = FileLoader.getPathToAttach(currentPhotoObject, true).exists(); mediaExists = FileLoader.getPathToAttach(currentPhotoObject, true).exists();
} }
} }
if (!mediaExists && document != null) {
loadedFileSize = FileLoader.getTempFileSize(document, MessageObject.isVideoDocument(document) && shouldEncryptPhotoOrVideo());
}
} }
} }

View File

@ -281,6 +281,7 @@ public class MessagesController extends BaseController implements NotificationCe
public String suggestedLangCode; public String suggestedLangCode;
public boolean qrLoginCamera; public boolean qrLoginCamera;
private String installReferer; private String installReferer;
public ArrayList<String> gifSearchEmojies = new ArrayList<>();
public HashSet<String> diceEmojies; public HashSet<String> diceEmojies;
public HashMap<String, DiceFrameSuccess> diceSuccess = new HashMap<>(); public HashMap<String, DiceFrameSuccess> diceSuccess = new HashMap<>();
@ -376,6 +377,66 @@ public class MessagesController extends BaseController implements NotificationCe
public LongSparseArray<Integer> pinnedDialogs = new LongSparseArray<>(); public LongSparseArray<Integer> pinnedDialogs = new LongSparseArray<>();
public ArrayList<TLRPC.Dialog> dialogs = new ArrayList<>(); public ArrayList<TLRPC.Dialog> dialogs = new ArrayList<>();
public String emoticon; public String emoticon;
public boolean includesDialog(AccountInstance accountInstance, int lowerId) {
MessagesController messagesController = accountInstance.getMessagesController();
TLRPC.Dialog dialog = messagesController.dialogs_dict.get(lowerId);
if (dialog == null) {
return false;
}
return includesDialog(accountInstance, lowerId, dialog);
}
public boolean includesDialog(AccountInstance accountInstance, int lowerId, TLRPC.Dialog d) {
if (alwaysShow.contains(lowerId)) {
return true;
}
if (d.folder_id != 0 && (flags & DIALOG_FILTER_FLAG_EXCLUDE_ARCHIVED) != 0) {
return false;
}
MessagesController messagesController = accountInstance.getMessagesController();
ContactsController contactsController = accountInstance.getContactsController();
boolean skip = false;
if ((flags & DIALOG_FILTER_FLAG_EXCLUDE_MUTED) != 0 && messagesController.isDialogMuted(d.id) && d.unread_mentions_count == 0 ||
(flags & DIALOG_FILTER_FLAG_EXCLUDE_READ) != 0 && d.unread_count == 0 && !d.unread_mark && d.unread_mentions_count == 0 ||
neverShow.contains(lowerId)) {
return false;
}
if (lowerId > 0) {
TLRPC.User user = messagesController.getUser(lowerId);
if (user != null) {
if (!user.bot) {
if (user.self || user.contact || contactsController.isContact(lowerId)) {
if ((flags & DIALOG_FILTER_FLAG_CONTACTS) != 0) {
return true;
}
} else {
if ((flags & DIALOG_FILTER_FLAG_NON_CONTACTS) != 0) {
return true;
}
}
} else {
if ((flags & DIALOG_FILTER_FLAG_BOTS) != 0) {
return true;
}
}
}
} else if (lowerId < 0) {
TLRPC.Chat chat = messagesController.getChat(-lowerId);
if (chat != null) {
if (ChatObject.isChannel(chat) && !chat.megagroup) {
if ((flags & DIALOG_FILTER_FLAG_CHANNELS) != 0) {
return true;
}
} else {
if ((flags & DIALOG_FILTER_FLAG_GROUPS) != 0) {
return true;
}
}
}
}
return false;
}
} }
private DialogFilter sortingDialogFilter; private DialogFilter sortingDialogFilter;
@ -659,12 +720,12 @@ public class MessagesController extends BaseController implements NotificationCe
} else { } else {
diceEmojies = new HashSet<>(emojies); diceEmojies = new HashSet<>(emojies);
} }
String success = mainPreferences.getString("diceSuccess", null); String text = mainPreferences.getString("diceSuccess", null);
if (success == null) { if (text == null) {
diceSuccess.put("\uD83C\uDFAF", new DiceFrameSuccess(62, 6)); diceSuccess.put("\uD83C\uDFAF", new DiceFrameSuccess(62, 6));
} else { } else {
try { try {
byte[] bytes = Base64.decode(success, Base64.DEFAULT); byte[] bytes = Base64.decode(text, Base64.DEFAULT);
if (bytes != null) { if (bytes != null) {
SerializedData data = new SerializedData(bytes); SerializedData data = new SerializedData(bytes);
int count = data.readInt32(true); int count = data.readInt32(true);
@ -677,9 +738,37 @@ public class MessagesController extends BaseController implements NotificationCe
FileLog.e(e); FileLog.e(e);
} }
} }
text = mainPreferences.getString("gifSearchEmojies", null);
if (text == null) {
gifSearchEmojies.add("👍");
gifSearchEmojies.add("👎");
gifSearchEmojies.add("😍");
gifSearchEmojies.add("😂");
gifSearchEmojies.add("😮");
gifSearchEmojies.add("🙄");
gifSearchEmojies.add("😥");
gifSearchEmojies.add("😡");
gifSearchEmojies.add("🥳");
gifSearchEmojies.add("😎");
} else {
try {
byte[] bytes = Base64.decode(text, Base64.DEFAULT);
if (bytes != null) {
SerializedData data = new SerializedData(bytes);
int count = data.readInt32(true);
for (int a = 0; a < count; a++) {
gifSearchEmojies.add(data.readString(true));
}
data.cleanup();
}
} catch (Exception e) {
FileLog.e(e);
}
}
} }
private void sendLoadPeersRequest(TLObject req, ArrayList<TLObject> requests, TLRPC.messages_Dialogs pinnedDialogs, TLRPC.messages_Dialogs pinnedRemoteDialogs, ArrayList<TLRPC.User> users, ArrayList<TLRPC.Chat> chats, ArrayList<MessagesController.DialogFilter> filtersToSave, SparseArray<MessagesController.DialogFilter> filtersToDelete, ArrayList<Integer> filtersOrder, HashMap<Integer, HashSet<Integer>> filterDialogRemovals, HashMap<Integer, HashSet<Integer>> filterUserRemovals, HashSet<Integer> filtersUnreadCounterReset) { private void sendLoadPeersRequest(TLObject req, ArrayList<TLObject> requests, TLRPC.messages_Dialogs pinnedDialogs, TLRPC.messages_Dialogs pinnedRemoteDialogs, ArrayList<TLRPC.User> users, ArrayList<TLRPC.Chat> chats, ArrayList<DialogFilter> filtersToSave, SparseArray<DialogFilter> filtersToDelete, ArrayList<Integer> filtersOrder, HashMap<Integer, HashSet<Integer>> filterDialogRemovals, HashMap<Integer, HashSet<Integer>> filterUserRemovals, HashSet<Integer> filtersUnreadCounterReset) {
getConnectionsManager().sendRequest(req, (response, error) -> { getConnectionsManager().sendRequest(req, (response, error) -> {
if (response instanceof TLRPC.TL_messages_chats) { if (response instanceof TLRPC.TL_messages_chats) {
TLRPC.TL_messages_chats res = (TLRPC.TL_messages_chats) response; TLRPC.TL_messages_chats res = (TLRPC.TL_messages_chats) response;
@ -706,7 +795,7 @@ public class MessagesController extends BaseController implements NotificationCe
}); });
} }
protected void loadFilterPeers(HashMap<Integer, TLRPC.InputPeer> dialogsToLoadMap, HashMap<Integer, TLRPC.InputPeer> usersToLoadMap, HashMap<Integer, TLRPC.InputPeer> chatsToLoadMap, TLRPC.messages_Dialogs pinnedDialogs, TLRPC.messages_Dialogs pinnedRemoteDialogs, ArrayList<TLRPC.User> users, ArrayList<TLRPC.Chat> chats, ArrayList<MessagesController.DialogFilter> filtersToSave, SparseArray<MessagesController.DialogFilter> filtersToDelete, ArrayList<Integer> filtersOrder, HashMap<Integer, HashSet<Integer>> filterDialogRemovals, HashMap<Integer, HashSet<Integer>> filterUserRemovals, HashSet<Integer> filtersUnreadCounterReset) { protected void loadFilterPeers(HashMap<Integer, TLRPC.InputPeer> dialogsToLoadMap, HashMap<Integer, TLRPC.InputPeer> usersToLoadMap, HashMap<Integer, TLRPC.InputPeer> chatsToLoadMap, TLRPC.messages_Dialogs pinnedDialogs, TLRPC.messages_Dialogs pinnedRemoteDialogs, ArrayList<TLRPC.User> users, ArrayList<TLRPC.Chat> chats, ArrayList<DialogFilter> filtersToSave, SparseArray<DialogFilter> filtersToDelete, ArrayList<Integer> filtersOrder, HashMap<Integer, HashSet<Integer>> filterDialogRemovals, HashMap<Integer, HashSet<Integer>> filterUserRemovals, HashSet<Integer> filtersUnreadCounterReset) {
Utilities.stageQueue.postRunnable(() -> { Utilities.stageQueue.postRunnable(() -> {
ArrayList<TLObject> requests = new ArrayList<>(); ArrayList<TLObject> requests = new ArrayList<>();
TLRPC.TL_users_getUsers req = null; TLRPC.TL_users_getUsers req = null;
@ -1255,6 +1344,31 @@ public class MessagesController extends BaseController implements NotificationCe
} }
break; break;
} }
case "gif_search_emojies": {
ArrayList<String> newEmojies = new ArrayList<>();
if (value.value instanceof TLRPC.TL_jsonArray) {
TLRPC.TL_jsonArray array = (TLRPC.TL_jsonArray) value.value;
for (int b = 0, N2 = array.value.size(); b < N2; b++) {
TLRPC.JSONValue val = array.value.get(b);
if (val instanceof TLRPC.TL_jsonString) {
TLRPC.TL_jsonString string = (TLRPC.TL_jsonString) val;
newEmojies.add(string.value.replace("\uFE0F", ""));
}
}
}
if (!gifSearchEmojies.equals(newEmojies)) {
gifSearchEmojies = newEmojies;
SerializedData serializedData = new SerializedData();
serializedData.writeInt32(gifSearchEmojies.size());
for (int b = 0, N2 = gifSearchEmojies.size(); b < N2; b++) {
serializedData.writeString(gifSearchEmojies.get(b));
}
editor.putString("gifSearchEmojies", Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT));
serializedData.cleanup();
changed = true;
}
break;
}
case "emojies_send_dice_success": { case "emojies_send_dice_success": {
try { try {
HashMap<String, DiceFrameSuccess> newEmojies = new HashMap<>(); HashMap<String, DiceFrameSuccess> newEmojies = new HashMap<>();
@ -1293,6 +1407,7 @@ public class MessagesController extends BaseController implements NotificationCe
serializedData.writeInt32(frameSuccess.num); serializedData.writeInt32(frameSuccess.num);
} }
editor.putString("diceSuccess", Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT)); editor.putString("diceSuccess", Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT));
serializedData.cleanup();
changed = true; changed = true;
} }
} catch (Exception e) { } catch (Exception e) {
@ -3939,6 +4054,9 @@ public class MessagesController extends BaseController implements NotificationCe
if (onlyHistory == 0 || onlyHistory == 3) { if (onlyHistory == 0 || onlyHistory == 3) {
getNotificationsController().deleteNotificationChannel(did); getNotificationsController().deleteNotificationChannel(did);
} }
if (onlyHistory == 0) {
getMediaDataController().cleanDraft(did, false);
}
if (dialog != null) { if (dialog != null) {
if (emptyMax) { if (emptyMax) {
max_id_delete = Math.max(0, dialog.top_message); max_id_delete = Math.max(0, dialog.top_message);
@ -5046,21 +5164,21 @@ public class MessagesController extends BaseController implements NotificationCe
} }
} }
public void loadMessages(final long dialog_id, final int count, final int max_id, final int offset_date, boolean fromCache, int midDate, final int classGuid, final int load_type, final int last_message_id, final boolean isChannel, boolean scheduled, final int loadIndex) { public void loadMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int midDate, int classGuid, int load_type, int last_message_id, boolean isChannel, boolean scheduled, int loadIndex) {
loadMessages(dialog_id, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, scheduled, loadIndex, 0, 0, 0, false, 0); loadMessages(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, scheduled, loadIndex, 0, 0, 0, false, 0);
} }
public void loadMessages(final long dialog_id, final int count, final int max_id, final int offset_date, final boolean fromCache, final int midDate, final int classGuid, final int load_type, final int last_message_id, final boolean isChannel, boolean scheduled, final int loadIndex, final int first_unread, final int unread_count, final int last_date, final boolean queryFromServer, final int mentionsCount) { public void loadMessages(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int midDate, int classGuid, int load_type, int last_message_id, boolean isChannel, boolean scheduled, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount) {
loadMessagesInternal(dialog_id, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, scheduled, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount, true); loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, fromCache, midDate, classGuid, load_type, last_message_id, isChannel, scheduled, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount, true);
} }
private void loadMessagesInternal(final long dialog_id, final int count, final int max_id, final int offset_date, final boolean fromCache, final int minDate, final int classGuid, final int load_type, final int last_message_id, final boolean isChannel, boolean scheduled, final int loadIndex, final int first_unread, final int unread_count, final int last_date, final boolean queryFromServer, final int mentionsCount, boolean loadDialog) { private void loadMessagesInternal(long dialogId, long mergeDialogId, boolean loadInfo, int count, int max_id, int offset_date, boolean fromCache, int minDate, int classGuid, int load_type, int last_message_id, boolean isChannel, boolean scheduled, int loadIndex, int first_unread, int unread_count, int last_date, boolean queryFromServer, int mentionsCount, boolean loadDialog) {
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
FileLog.d("load messages in chat " + dialog_id + " count " + count + " max_id " + max_id + " cache " + fromCache + " mindate = " + minDate + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " scheduled " + scheduled + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer); FileLog.d("load messages in chat " + dialogId + " count " + count + " max_id " + max_id + " cache " + fromCache + " mindate = " + minDate + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " scheduled " + scheduled + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer);
} }
int lower_part = (int) dialog_id; int lower_part = (int) dialogId;
if (fromCache || lower_part == 0) { if (fromCache || lower_part == 0) {
getMessagesStorage().getMessages(dialog_id, count, max_id, offset_date, minDate, classGuid, load_type, isChannel, scheduled, loadIndex); getMessagesStorage().getMessages(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, minDate, classGuid, load_type, isChannel, scheduled, loadIndex);
} else { } else {
if (scheduled) { if (scheduled) {
TLRPC.TL_messages_getScheduledHistory req = new TLRPC.TL_messages_getScheduledHistory(); TLRPC.TL_messages_getScheduledHistory req = new TLRPC.TL_messages_getScheduledHistory();
@ -5083,14 +5201,14 @@ public class MessagesController extends BaseController implements NotificationCe
} }
} }
} }
processLoadedMessages(res, dialog_id, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, true, loadIndex, queryFromServer, mentionsCount); processLoadedMessages(res, dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, true, loadIndex, queryFromServer, mentionsCount);
} }
}); });
getConnectionsManager().bindRequestToGuid(reqId, classGuid); getConnectionsManager().bindRequestToGuid(reqId, classGuid);
} else { } else {
if (loadDialog && (load_type == 3 || load_type == 2) && last_message_id == 0) { if (loadDialog && (load_type == 3 || load_type == 2) && last_message_id == 0) {
TLRPC.TL_messages_getPeerDialogs req = new TLRPC.TL_messages_getPeerDialogs(); TLRPC.TL_messages_getPeerDialogs req = new TLRPC.TL_messages_getPeerDialogs();
TLRPC.InputPeer inputPeer = getInputPeer((int) dialog_id); TLRPC.InputPeer inputPeer = getInputPeer((int) dialogId);
TLRPC.TL_inputDialogPeer inputDialogPeer = new TLRPC.TL_inputDialogPeer(); TLRPC.TL_inputDialogPeer inputDialogPeer = new TLRPC.TL_inputDialogPeer();
inputDialogPeer.peer = inputPeer; inputDialogPeer.peer = inputPeer;
req.peers.add(inputDialogPeer); req.peers.add(inputDialogPeer);
@ -5110,8 +5228,12 @@ public class MessagesController extends BaseController implements NotificationCe
getMessagesStorage().putDialogs(dialogs, 0); getMessagesStorage().putDialogs(dialogs, 0);
} }
loadMessagesInternal(dialog_id, count, max_id, offset_date, false, minDate, classGuid, load_type, dialog.top_message, isChannel, false, loadIndex, first_unread, dialog.unread_count, last_date, queryFromServer, dialog.unread_mentions_count, false); loadMessagesInternal(dialogId, mergeDialogId, loadInfo, count, max_id, offset_date, false, minDate, classGuid, load_type, dialog.top_message, isChannel, false, loadIndex, first_unread, dialog.unread_count, last_date, queryFromServer, dialog.unread_mentions_count, false);
} }
} else {
AndroidUtilities.runOnUIThread(() -> {
getNotificationCenter().postNotificationName(NotificationCenter.loadingMessagesFailed, classGuid, req, error);
});
} }
}); });
return; return;
@ -5141,7 +5263,7 @@ public class MessagesController extends BaseController implements NotificationCe
int reqId = getConnectionsManager().sendRequest(req, (response, error) -> { int reqId = getConnectionsManager().sendRequest(req, (response, error) -> {
if (response != null) { if (response != null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response; final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
removeDeletedMessagesFromArray(dialog_id, res.messages); removeDeletedMessagesFromArray(dialogId, res.messages);
if (res.messages.size() > count) { if (res.messages.size() > count) {
res.messages.remove(0); res.messages.remove(0);
} }
@ -5156,7 +5278,11 @@ public class MessagesController extends BaseController implements NotificationCe
} }
} }
} }
processLoadedMessages(res, dialog_id, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, false, loadIndex, queryFromServer, mentionsCount); processLoadedMessages(res, dialogId, mergeDialogId, count, mid, offset_date, false, classGuid, first_unread, last_message_id, unread_count, last_date, load_type, isChannel, false, false, loadIndex, queryFromServer, mentionsCount);
} else {
AndroidUtilities.runOnUIThread(() -> {
getNotificationCenter().postNotificationName(NotificationCenter.loadingMessagesFailed, classGuid, req, error);
});
} }
}); });
getConnectionsManager().bindRequestToGuid(reqId, classGuid); getConnectionsManager().bindRequestToGuid(reqId, classGuid);
@ -5212,187 +5338,185 @@ public class MessagesController extends BaseController implements NotificationCe
} }
} }
public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, final long dialog_id, final int count, final int max_id, final int offset_date, final boolean isCache, final int classGuid, public void processLoadedMessages(TLRPC.messages_Messages messagesRes, long dialogId, long mergeDialogId, int count, int max_id, int offset_date, boolean isCache, int classGuid,
final int first_unread, final int last_message_id, final int unread_count, final int last_date, final int load_type, final boolean isChannel, final boolean isEnd, final boolean scheduled, final int loadIndex, final boolean queryFromServer, final int mentionsCount) { int first_unread, int last_message_id, int unread_count, int last_date, int load_type, boolean isChannel, boolean isEnd, boolean scheduled, int loadIndex, boolean queryFromServer, int mentionsCount) {
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
FileLog.d("processLoadedMessages size " + messagesRes.messages.size() + " in chat " + dialog_id + " count " + count + " max_id " + max_id + " cache " + isCache + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " isChannel " + isChannel + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer); FileLog.d("processLoadedMessages size " + messagesRes.messages.size() + " in chat " + dialogId + " count " + count + " max_id " + max_id + " cache " + isCache + " guid " + classGuid + " load_type " + load_type + " last_message_id " + last_message_id + " isChannel " + isChannel + " index " + loadIndex + " firstUnread " + first_unread + " unread_count " + unread_count + " last_date " + last_date + " queryFromServer " + queryFromServer);
} }
Utilities.stageQueue.postRunnable(() -> { boolean createDialog = false;
boolean createDialog = false; boolean isMegagroup = false;
boolean isMegagroup = false; if (messagesRes instanceof TLRPC.TL_messages_channelMessages) {
if (messagesRes instanceof TLRPC.TL_messages_channelMessages) { int channelId = -(int) dialogId;
int channelId = -(int) dialog_id; if (!scheduled) {
if (!scheduled) { int channelPts = channelsPts.get(channelId);
int channelPts = channelsPts.get(channelId); if (channelPts == 0) {
channelPts = getMessagesStorage().getChannelPtsSync(channelId);
if (channelPts == 0) { if (channelPts == 0) {
channelPts = getMessagesStorage().getChannelPtsSync(channelId); channelsPts.put(channelId, messagesRes.pts);
if (channelPts == 0) { createDialog = true;
channelsPts.put(channelId, messagesRes.pts); if (needShortPollChannels.indexOfKey(channelId) >= 0 && shortPollChannels.indexOfKey(channelId) < 0) {
createDialog = true; getChannelDifference(channelId, 2, 0, null);
if (needShortPollChannels.indexOfKey(channelId) >= 0 && shortPollChannels.indexOfKey(channelId) < 0) { } else {
getChannelDifference(channelId, 2, 0, null); getChannelDifference(channelId);
} else {
getChannelDifference(channelId);
}
} }
} }
} }
for (int a = 0; a < messagesRes.chats.size(); a++) {
TLRPC.Chat chat = messagesRes.chats.get(a);
if (chat.id == channelId) {
isMegagroup = chat.megagroup;
break;
}
}
}
int lower_id = (int) dialog_id;
int high_id = (int) (dialog_id >> 32);
if (!isCache) {
ImageLoader.saveMessagesThumbs(messagesRes.messages);
}
if (high_id != 1 && lower_id != 0 && isCache && (messagesRes.messages.size() == 0 || scheduled && (SystemClock.elapsedRealtime() - lastScheduledServerQueryTime.get(dialog_id, 0L)) > 60 * 1000)) {
int hash;
if (scheduled) {
lastScheduledServerQueryTime.put(dialog_id, SystemClock.elapsedRealtime());
long h = 0;
for (int a = 0, N = messagesRes.messages.size(); a < N; a++) {
TLRPC.Message message = messagesRes.messages.get(a);
if (message.id < 0) {
continue;
}
h = ((h * 20261) + 0x80000000L + message.id) % 0x80000000L;
h = ((h * 20261) + 0x80000000L + message.edit_date) % 0x80000000L;
h = ((h * 20261) + 0x80000000L + message.date) % 0x80000000L;
}
hash = (int) h - 1;
} else {
hash = 0;
}
AndroidUtilities.runOnUIThread(() -> loadMessages(dialog_id, count, load_type == 2 && queryFromServer ? first_unread : max_id, offset_date, false, hash, classGuid, load_type, last_message_id, isChannel, scheduled, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount));
if (messagesRes.messages.isEmpty()) {
return;
}
}
final SparseArray<TLRPC.User> usersDict = new SparseArray<>();
final SparseArray<TLRPC.Chat> chatsDict = new SparseArray<>();
for (int a = 0; a < messagesRes.users.size(); a++) {
TLRPC.User u = messagesRes.users.get(a);
usersDict.put(u.id, u);
} }
for (int a = 0; a < messagesRes.chats.size(); a++) { for (int a = 0; a < messagesRes.chats.size(); a++) {
TLRPC.Chat c = messagesRes.chats.get(a); TLRPC.Chat chat = messagesRes.chats.get(a);
chatsDict.put(c.id, c); if (chat.id == channelId) {
isMegagroup = chat.megagroup;
break;
}
} }
int size = messagesRes.messages.size(); }
if (!isCache) { int lower_id = (int) dialogId;
Integer inboxValue = dialogs_read_inbox_max.get(dialog_id); int high_id = (int) (dialogId >> 32);
if (inboxValue == null) { if (!isCache) {
inboxValue = getMessagesStorage().getDialogReadMax(false, dialog_id); ImageLoader.saveMessagesThumbs(messagesRes.messages);
dialogs_read_inbox_max.put(dialog_id, inboxValue); }
} if (high_id != 1 && lower_id != 0 && isCache && (messagesRes.messages.size() == 0 || scheduled && (SystemClock.elapsedRealtime() - lastScheduledServerQueryTime.get(dialogId, 0L)) > 60 * 1000)) {
int hash;
Integer outboxValue = dialogs_read_outbox_max.get(dialog_id); if (scheduled) {
if (outboxValue == null) { lastScheduledServerQueryTime.put(dialogId, SystemClock.elapsedRealtime());
outboxValue = getMessagesStorage().getDialogReadMax(true, dialog_id); long h = 0;
dialogs_read_outbox_max.put(dialog_id, outboxValue); for (int a = 0, N = messagesRes.messages.size(); a < N; a++) {
}
for (int a = 0; a < size; a++) {
TLRPC.Message message = messagesRes.messages.get(a); TLRPC.Message message = messagesRes.messages.get(a);
if (isMegagroup) { if (message.id < 0) {
message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP; continue;
}
if (!scheduled) {
if (message.action instanceof TLRPC.TL_messageActionChatDeleteUser) {
TLRPC.User user = usersDict.get(message.action.user_id);
if (user != null && user.bot) {
message.reply_markup = new TLRPC.TL_replyKeyboardHide();
message.flags |= 64;
}
}
if (message.action instanceof TLRPC.TL_messageActionChatMigrateTo || message.action instanceof TLRPC.TL_messageActionChannelCreate) {
message.unread = false;
message.media_unread = false;
} else {
message.unread = (message.out ? outboxValue : inboxValue) < message.id;
}
} }
h = ((h * 20261) + 0x80000000L + message.id) % 0x80000000L;
h = ((h * 20261) + 0x80000000L + message.edit_date) % 0x80000000L;
h = ((h * 20261) + 0x80000000L + message.date) % 0x80000000L;
} }
getMessagesStorage().putMessages(messagesRes, dialog_id, load_type, max_id, createDialog, scheduled); hash = (int) h - 1;
} else {
hash = 0;
}
AndroidUtilities.runOnUIThread(() -> loadMessages(dialogId, mergeDialogId, false, count, load_type == 2 && queryFromServer ? first_unread : max_id, offset_date, false, hash, classGuid, load_type, last_message_id, isChannel, scheduled, loadIndex, first_unread, unread_count, last_date, queryFromServer, mentionsCount));
if (messagesRes.messages.isEmpty()) {
return;
}
}
final SparseArray<TLRPC.User> usersDict = new SparseArray<>();
final SparseArray<TLRPC.Chat> chatsDict = new SparseArray<>();
for (int a = 0; a < messagesRes.users.size(); a++) {
TLRPC.User u = messagesRes.users.get(a);
usersDict.put(u.id, u);
}
for (int a = 0; a < messagesRes.chats.size(); a++) {
TLRPC.Chat c = messagesRes.chats.get(a);
chatsDict.put(c.id, c);
}
int size = messagesRes.messages.size();
if (!isCache) {
Integer inboxValue = dialogs_read_inbox_max.get(dialogId);
if (inboxValue == null) {
inboxValue = getMessagesStorage().getDialogReadMax(false, dialogId);
dialogs_read_inbox_max.put(dialogId, inboxValue);
}
Integer outboxValue = dialogs_read_outbox_max.get(dialogId);
if (outboxValue == null) {
outboxValue = getMessagesStorage().getDialogReadMax(true, dialogId);
dialogs_read_outbox_max.put(dialogId, outboxValue);
} }
final ArrayList<MessageObject> objects = new ArrayList<>();
final ArrayList<Integer> messagesToReload = new ArrayList<>();
final HashMap<String, ArrayList<MessageObject>> webpagesToReload = new HashMap<>();
TLRPC.InputChannel inputChannel = null;
for (int a = 0; a < size; a++) { for (int a = 0; a < size; a++) {
TLRPC.Message message = messagesRes.messages.get(a); TLRPC.Message message = messagesRes.messages.get(a);
message.dialog_id = dialog_id; if (isMegagroup) {
MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, true); message.flags |= TLRPC.MESSAGE_FLAG_MEGAGROUP;
messageObject.scheduled = scheduled; }
objects.add(messageObject);
if (isCache) { if (!scheduled) {
if (message.legacy && message.layer < TLRPC.LAYER) { if (message.action instanceof TLRPC.TL_messageActionChatDeleteUser) {
messagesToReload.add(message.id); TLRPC.User user = usersDict.get(message.action.user_id);
} else if (message.media instanceof TLRPC.TL_messageMediaUnsupported) { if (user != null && user.bot) {
if (message.media.bytes != null && (message.media.bytes.length == 0 || message.media.bytes.length == 1 && message.media.bytes[0] < TLRPC.LAYER)) { message.reply_markup = new TLRPC.TL_replyKeyboardHide();
messagesToReload.add(message.id); message.flags |= 64;
} }
} }
if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage instanceof TLRPC.TL_webPagePending && message.media.webpage.date <= getConnectionsManager().getCurrentTime()) { if (message.action instanceof TLRPC.TL_messageActionChatMigrateTo || message.action instanceof TLRPC.TL_messageActionChannelCreate) {
messagesToReload.add(message.id); message.unread = false;
} else if (message.media.webpage instanceof TLRPC.TL_webPageUrlPending) { message.media_unread = false;
ArrayList<MessageObject> arrayList = webpagesToReload.get(message.media.webpage.url); } else {
if (arrayList == null) { message.unread = (message.out ? outboxValue : inboxValue) < message.id;
arrayList = new ArrayList<>();
webpagesToReload.put(message.media.webpage.url, arrayList);
}
arrayList.add(messageObject);
}
} }
} }
} }
AndroidUtilities.runOnUIThread(() -> { getMessagesStorage().putMessages(messagesRes, dialogId, load_type, max_id, createDialog, scheduled);
putUsers(messagesRes.users, isCache); }
putChats(messagesRes.chats, isCache);
int first_unread_final; final ArrayList<MessageObject> objects = new ArrayList<>();
if (scheduled) { final ArrayList<Integer> messagesToReload = new ArrayList<>();
first_unread_final = 0; final HashMap<String, ArrayList<MessageObject>> webpagesToReload = new HashMap<>();
} else { TLRPC.InputChannel inputChannel = null;
first_unread_final = Integer.MAX_VALUE; for (int a = 0; a < size; a++) {
if (queryFromServer && load_type == 2) { TLRPC.Message message = messagesRes.messages.get(a);
for (int a = 0; a < messagesRes.messages.size(); a++) { message.dialog_id = dialogId;
TLRPC.Message message = messagesRes.messages.get(a); MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, true);
if ((!message.out || message.from_scheduled) && message.id > first_unread && message.id < first_unread_final) { messageObject.scheduled = scheduled;
first_unread_final = message.id; objects.add(messageObject);
} if (isCache) {
if (message.legacy && message.layer < TLRPC.LAYER) {
messagesToReload.add(message.id);
} else if (message.media instanceof TLRPC.TL_messageMediaUnsupported) {
if (message.media.bytes != null && (message.media.bytes.length == 0 || message.media.bytes.length == 1 && message.media.bytes[0] < TLRPC.LAYER)) {
messagesToReload.add(message.id);
}
}
if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage instanceof TLRPC.TL_webPagePending && message.media.webpage.date <= getConnectionsManager().getCurrentTime()) {
messagesToReload.add(message.id);
} else if (message.media.webpage instanceof TLRPC.TL_webPageUrlPending) {
ArrayList<MessageObject> arrayList = webpagesToReload.get(message.media.webpage.url);
if (arrayList == null) {
arrayList = new ArrayList<>();
webpagesToReload.put(message.media.webpage.url, arrayList);
}
arrayList.add(messageObject);
}
}
}
}
AndroidUtilities.runOnUIThread(() -> {
putUsers(messagesRes.users, isCache);
putChats(messagesRes.chats, isCache);
int first_unread_final;
if (scheduled) {
first_unread_final = 0;
} else {
first_unread_final = Integer.MAX_VALUE;
if (queryFromServer && load_type == 2) {
for (int a = 0; a < messagesRes.messages.size(); a++) {
TLRPC.Message message = messagesRes.messages.get(a);
if ((!message.out || message.from_scheduled) && message.id > first_unread && message.id < first_unread_final) {
first_unread_final = message.id;
} }
} }
if (first_unread_final == Integer.MAX_VALUE) {
first_unread_final = first_unread;
}
} }
if (scheduled && count == 1) { if (first_unread_final == Integer.MAX_VALUE) {
getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, dialog_id, objects.size()); first_unread_final = first_unread;
} }
}
if (scheduled && count == 1) {
getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, dialogId, objects.size());
}
if ((int) dialog_id != 0) { if ((int) dialogId != 0) {
int finalFirst_unread_final = first_unread_final; int finalFirst_unread_final = first_unread_final;
getMediaDataController().loadReplyMessagesForMessages(objects, dialog_id, scheduled, () -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialog_id, count, objects, isCache, finalFirst_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, scheduled)); getMediaDataController().loadReplyMessagesForMessages(objects, dialogId, scheduled, () -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialogId, count, objects, isCache, finalFirst_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, scheduled));
} else { } else {
getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialog_id, count, objects, isCache, first_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, scheduled); getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoad, dialogId, count, objects, isCache, first_unread_final, last_message_id, unread_count, last_date, load_type, isEnd, classGuid, loadIndex, max_id, mentionsCount, scheduled);
} }
if (!messagesToReload.isEmpty()) { if (!messagesToReload.isEmpty()) {
reloadMessages(messagesToReload, dialog_id, scheduled); reloadMessages(messagesToReload, dialogId, scheduled);
} }
if (!webpagesToReload.isEmpty()) { if (!webpagesToReload.isEmpty()) {
reloadWebPages(dialog_id, webpagesToReload, scheduled); reloadWebPages(dialogId, webpagesToReload, scheduled);
} }
});
}); });
} }
@ -12309,62 +12433,17 @@ public class MessagesController extends BaseController implements NotificationCe
for (int a = 0, N = allDialogs.size(); a < N; a++) { for (int a = 0, N = allDialogs.size(); a < N; a++) {
TLRPC.Dialog d = allDialogs.get(a); TLRPC.Dialog d = allDialogs.get(a);
int high_id = (int) (d.id >> 32);
int lower_id = (int) d.id;
if (lower_id == 0 && high_id != 0) {
TLRPC.EncryptedChat encryptedChat = getEncryptedChat(high_id);
if (encryptedChat != null) {
lower_id = encryptedChat.user_id;
}
}
if (d instanceof TLRPC.TL_dialog) { if (d instanceof TLRPC.TL_dialog) {
if (selectedDialogFilter[b].alwaysShow.contains(lower_id)) { int high_id = (int) (d.id >> 32);
int lower_id = (int) d.id;
if (lower_id == 0 && high_id != 0) {
TLRPC.EncryptedChat encryptedChat = getEncryptedChat(high_id);
if (encryptedChat != null) {
lower_id = encryptedChat.user_id;
}
}
if (selectedDialogFilter[b].includesDialog(getAccountInstance(), lower_id, d)) {
dialogsByFilter.add(d); dialogsByFilter.add(d);
} else {
if (d.folder_id != 0 && (selectedDialogFilter[b].flags & DIALOG_FILTER_FLAG_EXCLUDE_ARCHIVED) != 0) {
continue;
}
boolean skip = false;
if ((selectedDialogFilter[b].flags & DIALOG_FILTER_FLAG_EXCLUDE_MUTED) != 0 && isDialogMuted(d.id) && d.unread_mentions_count == 0 ||
(selectedDialogFilter[b].flags & DIALOG_FILTER_FLAG_EXCLUDE_READ) != 0 && d.unread_count == 0 && !d.unread_mark && d.unread_mentions_count == 0 ||
selectedDialogFilter[b].neverShow.contains(lower_id)) {
skip = true;
}
if (!skip) {
if (lower_id > 0) {
TLRPC.User user = getUser(lower_id);
if (user != null) {
if (!user.bot) {
if (user.self || user.contact || getContactsController().isContact(lower_id)) {
if ((selectedDialogFilter[b].flags & DIALOG_FILTER_FLAG_CONTACTS) != 0) {
dialogsByFilter.add(d);
}
} else {
if ((selectedDialogFilter[b].flags & DIALOG_FILTER_FLAG_NON_CONTACTS) != 0) {
dialogsByFilter.add(d);
}
}
} else {
if ((selectedDialogFilter[b].flags & DIALOG_FILTER_FLAG_BOTS) != 0) {
dialogsByFilter.add(d);
}
}
}
} else if (lower_id < 0) {
TLRPC.Chat chat = getChat(-lower_id);
if (chat != null) {
if (ChatObject.isChannel(chat) && !chat.megagroup) {
if ((selectedDialogFilter[b].flags & DIALOG_FILTER_FLAG_CHANNELS) != 0) {
dialogsByFilter.add(d);
}
} else {
if ((selectedDialogFilter[b].flags & DIALOG_FILTER_FLAG_GROUPS) != 0) {
dialogsByFilter.add(d);
}
}
}
}
}
} }
} }
} }
@ -12713,7 +12792,7 @@ public class MessagesController extends BaseController implements NotificationCe
} }
} }
public void ensureMessagesLoaded(long dialog_id, boolean isChannel, int messageId, Runnable callback) { public void ensureMessagesLoaded(long dialog_id, boolean isChannel, int messageId, Runnable callback, Runnable doOnError) {
SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount);
if (messageId == 0) { if (messageId == 0) {
messageId = sharedPreferences.getInt("diditem" + dialog_id, 0); messageId = sharedPreferences.getInt("diditem" + dialog_id, 0);
@ -12724,7 +12803,7 @@ public class MessagesController extends BaseController implements NotificationCe
} }
int finalMessageId = messageId; int finalMessageId = messageId;
final int classGuid = ConnectionsManager.generateClassGuid(); final int classGuid = ConnectionsManager.generateClassGuid();
getNotificationCenter().addObserver(new NotificationCenter.NotificationCenterDelegate() { NotificationCenter.NotificationCenterDelegate delegate = new NotificationCenter.NotificationCenterDelegate() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void didReceivedNotification(int id, int account, Object... args) { public void didReceivedNotification(int id, int account, Object... args) {
@ -12732,14 +12811,27 @@ public class MessagesController extends BaseController implements NotificationCe
ArrayList<MessageObject> messArr = (ArrayList<MessageObject>) args[2]; ArrayList<MessageObject> messArr = (ArrayList<MessageObject>) args[2];
boolean isCache = (Boolean) args[3]; boolean isCache = (Boolean) args[3];
if (messArr.isEmpty() && isCache) { if (messArr.isEmpty() && isCache) {
loadMessages(dialog_id, 20, 3, 0, false, 0, classGuid, 3, 0, false, false, 0); loadMessages(dialog_id, 0, false, 20, 3, 0, false, 0, classGuid, 3, 0, false, false, 0);
} else { } else {
getNotificationCenter().removeObserver(this, NotificationCenter.didReceiveNewMessages); getNotificationCenter().removeObserver(this, NotificationCenter.didReceiveNewMessages);
getNotificationCenter().removeObserver(this, NotificationCenter.loadingMessagesFailed);
callback.run(); callback.run();
} }
} }
if (id == NotificationCenter.loadingMessagesFailed && (Integer) args[0] == classGuid) {
getNotificationCenter().removeObserver(this, NotificationCenter.didReceiveNewMessages);
getNotificationCenter().removeObserver(this, NotificationCenter.loadingMessagesFailed);
if (doOnError != null) {
doOnError.run();
}
}
} }
}, NotificationCenter.messagesDidLoad); };
loadMessages(dialog_id, 1, finalMessageId, 0, true, 0, classGuid, 3, 0, false, false, 0);
getNotificationCenter().addObserver(delegate, NotificationCenter.messagesDidLoad);
getNotificationCenter().addObserver(delegate, NotificationCenter.loadingMessagesFailed);
loadMessages(dialog_id, 0, false, 1, finalMessageId, 0, true, 0, classGuid, 3, 0, false, false, 0);
} }
} }

View File

@ -13,6 +13,7 @@ import android.util.SparseArray;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
public class NotificationCenter { public class NotificationCenter {
@ -26,6 +27,7 @@ public class NotificationCenter {
public static final int historyCleared = totalEvents++; public static final int historyCleared = totalEvents++;
public static final int messagesRead = totalEvents++; public static final int messagesRead = totalEvents++;
public static final int messagesDidLoad = totalEvents++; public static final int messagesDidLoad = totalEvents++;
public static final int loadingMessagesFailed = totalEvents++;
public static final int messageReceivedByAck = totalEvents++; public static final int messageReceivedByAck = totalEvents++;
public static final int messageReceivedByServer = totalEvents++; public static final int messageReceivedByServer = totalEvents++;
public static final int messageSendError = totalEvents++; public static final int messageSendError = totalEvents++;
@ -54,7 +56,8 @@ public class NotificationCenter {
public static final int updateMessageMedia = totalEvents++; public static final int updateMessageMedia = totalEvents++;
public static final int replaceMessagesObjects = totalEvents++; public static final int replaceMessagesObjects = totalEvents++;
public static final int didSetPasscode = totalEvents++; public static final int didSetPasscode = totalEvents++;
public static final int didSetTwoStepPassword = totalEvents++; public static final int twoStepPasswordChanged = totalEvents++;
public static final int didSetOrRemoveTwoStepPassword = totalEvents++;
public static final int didRemoveTwoStepPassword = totalEvents++; public static final int didRemoveTwoStepPassword = totalEvents++;
public static final int replyMessagesDidLoad = totalEvents++; public static final int replyMessagesDidLoad = totalEvents++;
public static final int pinnedMessageDidLoad = totalEvents++; public static final int pinnedMessageDidLoad = totalEvents++;
@ -96,6 +99,7 @@ public class NotificationCenter {
public static final int startAllHeavyOperations = totalEvents++; public static final int startAllHeavyOperations = totalEvents++;
public static final int sendingMessagesChanged = totalEvents++; public static final int sendingMessagesChanged = totalEvents++;
public static final int didUpdateReactions = totalEvents++; public static final int didUpdateReactions = totalEvents++;
public static final int didVerifyMessagesStickers = totalEvents++;
public static final int scheduledMessagesUpdated = totalEvents++; public static final int scheduledMessagesUpdated = totalEvents++;
public static final int walletPendingTransactionsChanged = totalEvents++; public static final int walletPendingTransactionsChanged = totalEvents++;
@ -193,15 +197,17 @@ public class NotificationCenter {
private ArrayList<DelayedPost> delayedPosts = new ArrayList<>(10); private ArrayList<DelayedPost> delayedPosts = new ArrayList<>(10);
private int broadcasting = 0; private int broadcasting = 0;
private boolean animationInProgress;
private int[] allowedNotifications; private int animationInProgressCount;
private int animationInProgressPointer = 1;
private final HashMap<Integer, int[]> allowedNotifications = new HashMap<>();
public interface NotificationCenterDelegate { public interface NotificationCenterDelegate {
void didReceivedNotification(int id, int account, Object... args); void didReceivedNotification(int id, int account, Object... args);
} }
private class DelayedPost { private static class DelayedPost {
private DelayedPost(int id, Object[] args) { private DelayedPost(int id, Object[] args) {
this.id = id; this.id = id;
@ -249,28 +255,52 @@ public class NotificationCenter {
currentAccount = account; currentAccount = account;
} }
public void setAllowedNotificationsDutingAnimation(int[] notifications) { public int setAnimationInProgress(int oldIndex, int[] allowedNotifications) {
allowedNotifications = notifications; onAnimationFinish(oldIndex);
if (animationInProgressCount == 0) {
NotificationCenter.getGlobalInstance().postNotificationName(stopAllHeavyOperations, 512);
}
animationInProgressCount++;
animationInProgressPointer++;
if (allowedNotifications == null) {
allowedNotifications = new int[0];
}
this.allowedNotifications.put(animationInProgressPointer, allowedNotifications);
return animationInProgressPointer;
} }
public void setAnimationInProgress(boolean value) { public void updateAllowedNotifications(int transitionAnimationIndex, int[] allowedNotifications) {
if (value) { if (this.allowedNotifications.containsKey(transitionAnimationIndex)) {
NotificationCenter.getGlobalInstance().postNotificationName(stopAllHeavyOperations, 512); if (allowedNotifications == null) {
} else { allowedNotifications = new int[0];
NotificationCenter.getGlobalInstance().postNotificationName(startAllHeavyOperations, 512); }
} this.allowedNotifications.put(transitionAnimationIndex, allowedNotifications);
animationInProgress = value; }
if (!animationInProgress && !delayedPosts.isEmpty()) { }
for (int a = 0; a < delayedPosts.size(); a++) {
DelayedPost delayedPost = delayedPosts.get(a); public void onAnimationFinish(int index) {
postNotificationNameInternal(delayedPost.id, true, delayedPost.args); int[] notifications = allowedNotifications.remove(index);
if (notifications != null) {
animationInProgressCount--;
if (animationInProgressCount == 0) {
NotificationCenter.getGlobalInstance().postNotificationName(startAllHeavyOperations, 512);
if (!delayedPosts.isEmpty()) {
for (int a = 0; a < delayedPosts.size(); a++) {
DelayedPost delayedPost = delayedPosts.get(a);
postNotificationNameInternal(delayedPost.id, true, delayedPost.args);
}
delayedPosts.clear();
}
} }
delayedPosts.clear();
} }
} }
public boolean isAnimationInProgress() { public boolean isAnimationInProgress() {
return animationInProgress; return animationInProgressCount > 0;
} }
public int getCurrentHeavyOperationFlags() { public int getCurrentHeavyOperationFlags() {
@ -279,13 +309,23 @@ public class NotificationCenter {
public void postNotificationName(int id, Object... args) { public void postNotificationName(int id, Object... args) {
boolean allowDuringAnimation = id == startAllHeavyOperations || id == stopAllHeavyOperations; boolean allowDuringAnimation = id == startAllHeavyOperations || id == stopAllHeavyOperations;
if (!allowDuringAnimation && allowedNotifications != null) { if (!allowDuringAnimation && !allowedNotifications.isEmpty()) {
for (int a = 0; a < allowedNotifications.length; a++) { int size = allowedNotifications.size();
if (allowedNotifications[a] == id) { int allowedCount = 0;
allowDuringAnimation = true; for(Integer key : allowedNotifications.keySet()) {
int[] allowed = allowedNotifications.get(key);
if (allowed != null) {
for (int a = 0; a < allowed.length; a++) {
if (allowed[a] == id) {
allowedCount++;
break;
}
}
} else {
break; break;
} }
} }
allowDuringAnimation = size == allowedCount;
} }
if (id == startAllHeavyOperations) { if (id == startAllHeavyOperations) {
Integer flags = (Integer) args[0]; Integer flags = (Integer) args[0];
@ -304,7 +344,7 @@ public class NotificationCenter {
throw new RuntimeException("postNotificationName allowed only from MAIN thread"); throw new RuntimeException("postNotificationName allowed only from MAIN thread");
} }
} }
if (!allowDuringAnimation && animationInProgress) { if (!allowDuringAnimation && isAnimationInProgress()) {
DelayedPost delayedPost = new DelayedPost(id, args); DelayedPost delayedPost = new DelayedPost(id, args);
delayedPosts.add(delayedPost); delayedPosts.add(delayedPost);
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
@ -316,7 +356,7 @@ public class NotificationCenter {
ArrayList<NotificationCenterDelegate> objects = observers.get(id); ArrayList<NotificationCenterDelegate> objects = observers.get(id);
if (objects != null && !objects.isEmpty()) { if (objects != null && !objects.isEmpty()) {
for (int a = 0; a < objects.size(); a++) { for (int a = 0; a < objects.size(); a++) {
NotificationCenterDelegate obj = objects.get(a); NotificationCenterDelegate obj = objects.get(a);;
obj.didReceivedNotification(id, currentAccount, args); obj.didReceivedNotification(id, currentAccount, args);
} }
} }

View File

@ -982,6 +982,7 @@ public class SecretChatHelper extends BaseController {
newMessage.media.document.id = file.id; newMessage.media.document.id = file.id;
newMessage.media.document.access_hash = file.access_hash; newMessage.media.document.access_hash = file.access_hash;
newMessage.media.document.date = date; newMessage.media.document.date = date;
newMessage.media.document.mime_type = decryptedMessage.media.mime_type;
if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaDocument_layer8) { if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaDocument_layer8) {
TLRPC.TL_documentAttributeFilename fileName = new TLRPC.TL_documentAttributeFilename(); TLRPC.TL_documentAttributeFilename fileName = new TLRPC.TL_documentAttributeFilename();
fileName.file_name = decryptedMessage.media.file_name; fileName.file_name = decryptedMessage.media.file_name;
@ -989,12 +990,13 @@ public class SecretChatHelper extends BaseController {
} else { } else {
newMessage.media.document.attributes = decryptedMessage.media.attributes; newMessage.media.document.attributes = decryptedMessage.media.attributes;
} }
newMessage.media.document.mime_type = decryptedMessage.media.mime_type;
newMessage.media.document.size = decryptedMessage.media.size != 0 ? Math.min(decryptedMessage.media.size, file.size) : file.size; newMessage.media.document.size = decryptedMessage.media.size != 0 ? Math.min(decryptedMessage.media.size, file.size) : file.size;
newMessage.media.document.key = decryptedMessage.media.key; newMessage.media.document.key = decryptedMessage.media.key;
newMessage.media.document.iv = decryptedMessage.media.iv; newMessage.media.document.iv = decryptedMessage.media.iv;
if (newMessage.media.document.mime_type == null) { if (newMessage.media.document.mime_type == null) {
newMessage.media.document.mime_type = ""; newMessage.media.document.mime_type = "";
} else if (MessageObject.isAnimatedStickerDocument(newMessage.media.document, true)) {
newMessage.media.document.mime_type = "application/x-bad_tgsticker";
} }
byte[] thumb = ((TLRPC.TL_decryptedMessageMediaDocument) decryptedMessage.media).thumb; byte[] thumb = ((TLRPC.TL_decryptedMessageMediaDocument) decryptedMessage.media).thumb;
TLRPC.PhotoSize photoSize; TLRPC.PhotoSize photoSize;
@ -1033,6 +1035,10 @@ public class SecretChatHelper extends BaseController {
if (newMessage.media.document.mime_type == null) { if (newMessage.media.document.mime_type == null) {
newMessage.media.document.mime_type = ""; newMessage.media.document.mime_type = "";
} }
if (MessageObject.isAnimatedStickerMessage(newMessage)) {
newMessage.stickerVerified = 0;
getMediaDataController().verifyAnimatedStickerMessage(newMessage, true);
}
} else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaAudio) { } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaAudio) {
if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) {
return null; return null;

View File

@ -8,6 +8,7 @@
package org.telegram.messenger; package org.telegram.messenger;
import android.content.ClipDescription;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -53,6 +54,8 @@ import org.telegram.ui.Components.Point;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
@ -116,6 +119,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
public Uri uri; public Uri uri;
public String path; public String path;
public String caption; public String caption;
public String thumbPath;
public String paintPath;
public int ttl; public int ttl;
public ArrayList<TLRPC.MessageEntity> entities; public ArrayList<TLRPC.MessageEntity> entities;
public ArrayList<TLRPC.InputDocument> masks; public ArrayList<TLRPC.InputDocument> masks;
@ -614,7 +619,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
for (int b = 0; b < message.messageObjects.size(); b++) { for (int b = 0; b < message.messageObjects.size(); b++) {
MessageObject obj = message.messageObjects.get(b); MessageObject obj = message.messageObjects.get(b);
if (obj == messageObject) { if (obj == messageObject) {
obj.videoEditedInfo = null; message.obj.shouldRemoveVideoEditedInfo = true;
obj.messageOwner.params.remove("ve"); obj.messageOwner.params.remove("ve");
obj.messageOwner.media.document.size = (int) finalSize; obj.messageOwner.media.document.size = (int) finalSize;
@ -625,7 +630,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
} }
} else if (message.obj == messageObject) { } else if (message.obj == messageObject) {
message.obj.videoEditedInfo = null; message.obj.shouldRemoveVideoEditedInfo = true;
message.obj.messageOwner.params.remove("ve"); message.obj.messageOwner.params.remove("ve");
message.obj.messageOwner.media.document.size = (int) finalSize; message.obj.messageOwner.media.document.size = (int) finalSize;
@ -1819,6 +1824,18 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
} else if (type == 3) { } else if (type == 3) {
TLRPC.TL_inputMediaUploadedDocument uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument(); TLRPC.TL_inputMediaUploadedDocument uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument();
if (params != null) {
String masks = params.get("masks");
if (masks != null) {
SerializedData serializedData = new SerializedData(Utilities.hexToBytes(masks));
int count = serializedData.readInt32(false);
for (int a = 0; a < count; a++) {
uploadedDocument.stickers.add(TLRPC.InputDocument.TLdeserialize(serializedData, serializedData.readInt32(false), false));
}
uploadedDocument.flags |= 1;
serializedData.cleanup();
}
}
uploadedDocument.mime_type = document.mime_type; uploadedDocument.mime_type = document.mime_type;
uploadedDocument.attributes = document.attributes; uploadedDocument.attributes = document.attributes;
if (!messageObject.isGif() && (videoEditedInfo == null || !videoEditedInfo.muted)) { if (!messageObject.isGif() && (videoEditedInfo == null || !videoEditedInfo.muted)) {
@ -2170,10 +2187,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
parentFragment.showRequestUrlAlert(res, (TLRPC.TL_messages_requestUrlAuth) request[0], button.url); parentFragment.showRequestUrlAlert(res, (TLRPC.TL_messages_requestUrlAuth) request[0], button.url);
} else if (response instanceof TLRPC.TL_urlAuthResultAccepted) { } else if (response instanceof TLRPC.TL_urlAuthResultAccepted) {
TLRPC.TL_urlAuthResultAccepted res = (TLRPC.TL_urlAuthResultAccepted) response; TLRPC.TL_urlAuthResultAccepted res = (TLRPC.TL_urlAuthResultAccepted) response;
parentFragment.showOpenUrlAlert(res.url, false, false); AlertsCreator.showOpenUrlAlert(parentFragment, res.url, false, false);
} else if (response instanceof TLRPC.TL_urlAuthResultDefault) { } else if (response instanceof TLRPC.TL_urlAuthResultDefault) {
TLRPC.TL_urlAuthResultDefault res = (TLRPC.TL_urlAuthResultDefault) response; TLRPC.TL_urlAuthResultDefault res = (TLRPC.TL_urlAuthResultDefault) response;
parentFragment.showOpenUrlAlert(button.url, false, true); AlertsCreator.showOpenUrlAlert(parentFragment, button.url, false, true);
} }
} else { } else {
TLRPC.TL_messages_botCallbackAnswer res = (TLRPC.TL_messages_botCallbackAnswer) response; TLRPC.TL_messages_botCallbackAnswer res = (TLRPC.TL_messages_botCallbackAnswer) response;
@ -2229,7 +2246,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
parentFragment.showOpenGameAlert(game, messageObject, res.url, !verified && MessagesController.getNotificationsSettings(currentAccount).getBoolean("askgame_" + uid, true), uid); parentFragment.showOpenGameAlert(game, messageObject, res.url, !verified && MessagesController.getNotificationsSettings(currentAccount).getBoolean("askgame_" + uid, true), uid);
} else { } else {
parentFragment.showOpenUrlAlert(res.url, false, false); AlertsCreator.showOpenUrlAlert(parentFragment, res.url, false, false);
} }
} }
} }
@ -2384,6 +2401,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
int lower_id = (int) peer; int lower_id = (int) peer;
int high_id = (int) (peer >> 32); int high_id = (int) (peer >> 32);
boolean isChannel = false; boolean isChannel = false;
boolean forceNoSoundVideo = false;
TLRPC.EncryptedChat encryptedChat = null; TLRPC.EncryptedChat encryptedChat = null;
TLRPC.InputPeer sendToPeer = lower_id != 0 ? getMessagesController().getInputPeer(lower_id) : null; TLRPC.InputPeer sendToPeer = lower_id != 0 ? getMessagesController().getInputPeer(lower_id) : null;
if (lower_id == 0) { if (lower_id == 0) {
@ -2428,7 +2446,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} else if (retryMessageObject.type == 1) { } else if (retryMessageObject.type == 1) {
photo = (TLRPC.TL_photo) newMsg.media.photo; photo = (TLRPC.TL_photo) newMsg.media.photo;
type = 2; type = 2;
} else if (retryMessageObject.type == 3 || retryMessageObject.type == 5 || videoEditedInfo != null) { } else if (retryMessageObject.type == 3 || retryMessageObject.type == 5 || retryMessageObject.videoEditedInfo != null) {
type = 3; type = 3;
document = (TLRPC.TL_document) newMsg.media.document; document = (TLRPC.TL_document) newMsg.media.document;
} else if (retryMessageObject.type == 12) { } else if (retryMessageObject.type == 12) {
@ -2584,6 +2602,18 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} else { } else {
newMsg = new TLRPC.TL_message(); newMsg = new TLRPC.TL_message();
} }
if (lower_id < 0) {
TLRPC.Chat chat = getMessagesController().getChat(-lower_id);
if (chat != null && !ChatObject.canSendStickers(chat)) {
for (int a = 0, N = document.attributes.size(); a < N; a++) {
if (document.attributes.get(a) instanceof TLRPC.TL_documentAttributeAnimated) {
document.attributes.remove(a);
forceNoSoundVideo = true;
break;
}
}
}
}
newMsg.media = new TLRPC.TL_messageMediaDocument(); newMsg.media = new TLRPC.TL_messageMediaDocument();
newMsg.media.flags |= 3; newMsg.media.flags |= 3;
if (ttl != 0) { if (ttl != 0) {
@ -2607,12 +2637,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
params.put("ve", ve); params.put("ve", ve);
} }
if (encryptedChat != null && document.dc_id > 0 && !MessageObject.isStickerDocument(document)) { if (encryptedChat != null && document.dc_id > 0 && !MessageObject.isStickerDocument(document) && !MessageObject.isAnimatedStickerDocument(document, true)) {
newMsg.attachPath = FileLoader.getPathToAttach(document).toString(); newMsg.attachPath = FileLoader.getPathToAttach(document).toString();
} else { } else {
newMsg.attachPath = path; newMsg.attachPath = path;
} }
if (encryptedChat != null && (MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, false))) { if (encryptedChat != null && (MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true))) {
for (int a = 0; a < document.attributes.size(); a++) { for (int a = 0; a < document.attributes.size(); a++) {
TLRPC.DocumentAttribute attribute = document.attributes.get(a); TLRPC.DocumentAttribute attribute = document.attributes.get(a);
if (attribute instanceof TLRPC.TL_documentAttributeSticker) { if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
@ -2631,6 +2661,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
attributeSticker.stickerset = new TLRPC.TL_inputStickerSetShortName(); attributeSticker.stickerset = new TLRPC.TL_inputStickerSetShortName();
attributeSticker.stickerset.short_name = name; attributeSticker.stickerset.short_name = name;
} else { } else {
if (attribute.stickerset instanceof TLRPC.TL_inputStickerSetID) {
delayedMessage = new DelayedMessage(peer);
delayedMessage.encryptedChat = encryptedChat;
delayedMessage.locationParent = attributeSticker;
delayedMessage.type = 5;
delayedMessage.parentObject = attribute.stickerset;
}
attributeSticker.stickerset = new TLRPC.TL_inputStickerSetEmpty(); attributeSticker.stickerset = new TLRPC.TL_inputStickerSetEmpty();
} }
} else { } else {
@ -2966,7 +3003,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
TLRPC.TL_inputMediaUploadedDocument uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument(); TLRPC.TL_inputMediaUploadedDocument uploadedDocument = new TLRPC.TL_inputMediaUploadedDocument();
uploadedDocument.mime_type = document.mime_type; uploadedDocument.mime_type = document.mime_type;
uploadedDocument.attributes = document.attributes; uploadedDocument.attributes = document.attributes;
if (!MessageObject.isRoundVideoDocument(document) && (videoEditedInfo == null || !videoEditedInfo.muted && !videoEditedInfo.roundVideo)) { if (forceNoSoundVideo || !MessageObject.isRoundVideoDocument(document) && (videoEditedInfo == null || !videoEditedInfo.muted && !videoEditedInfo.roundVideo)) {
uploadedDocument.nosound_video = true; uploadedDocument.nosound_video = true;
if (BuildVars.DEBUG_VERSION) { if (BuildVars.DEBUG_VERSION) {
FileLog.d("nosound_video = true"); FileLog.d("nosound_video = true");
@ -2976,6 +3013,18 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
newMsg.ttl = uploadedDocument.ttl_seconds = ttl; newMsg.ttl = uploadedDocument.ttl_seconds = ttl;
uploadedDocument.flags |= 2; uploadedDocument.flags |= 2;
} }
if (params != null) {
String masks = params.get("masks");
if (masks != null) {
SerializedData serializedData = new SerializedData(Utilities.hexToBytes(masks));
int count = serializedData.readInt32(false);
for (int a = 0; a < count; a++) {
uploadedDocument.stickers.add(TLRPC.InputDocument.TLdeserialize(serializedData, serializedData.readInt32(false), false));
}
uploadedDocument.flags |= 1;
serializedData.cleanup();
}
}
if (document.access_hash == 0) { if (document.access_hash == 0) {
inputMedia = uploadedDocument; inputMedia = uploadedDocument;
performMediaUpload = true; performMediaUpload = true;
@ -3024,7 +3073,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
newMsg.ttl = uploadedMedia.ttl_seconds = ttl; newMsg.ttl = uploadedMedia.ttl_seconds = ttl;
uploadedMedia.flags |= 2; uploadedMedia.flags |= 2;
} }
if (!TextUtils.isEmpty(path) && path.toLowerCase().endsWith("mp4") && (params == null || params.containsKey("forceDocument"))) { if (forceNoSoundVideo || !TextUtils.isEmpty(path) && path.toLowerCase().endsWith("mp4") && (params == null || params.containsKey("forceDocument"))) {
uploadedMedia.nosound_video = true; uploadedMedia.nosound_video = true;
} }
uploadedMedia.mime_type = document.mime_type; uploadedMedia.mime_type = document.mime_type;
@ -3369,7 +3418,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
reqSend.media.user_id = user.id; reqSend.media.user_id = user.id;
getSecretChatHelper().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null, newMsgObj); getSecretChatHelper().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null, newMsgObj);
} else if (type == 7 || type == 9 && document != null) { } else if (type == 7 || type == 9 && document != null) {
if (MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, false)) { if (document.access_hash != 0 && (MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true))) {
reqSend.media = new TLRPC.TL_decryptedMessageMediaExternalDocument(); reqSend.media = new TLRPC.TL_decryptedMessageMediaExternalDocument();
reqSend.media.id = document.id; reqSend.media.id = document.id;
reqSend.media.date = document.date; reqSend.media.date = document.date;
@ -3385,7 +3434,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
((TLRPC.TL_decryptedMessageMediaExternalDocument) reqSend.media).thumb = new TLRPC.TL_photoSizeEmpty(); ((TLRPC.TL_decryptedMessageMediaExternalDocument) reqSend.media).thumb = new TLRPC.TL_photoSizeEmpty();
((TLRPC.TL_decryptedMessageMediaExternalDocument) reqSend.media).thumb.type = "s"; ((TLRPC.TL_decryptedMessageMediaExternalDocument) reqSend.media).thumb.type = "s";
} }
getSecretChatHelper().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null, newMsgObj); if (delayedMessage != null && delayedMessage.type == 5) {
delayedMessage.sendEncryptedRequest = reqSend;
delayedMessage.obj = newMsgObj;
performSendDelayedMessage(delayedMessage);
} else {
getSecretChatHelper().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null, newMsgObj);
}
} else { } else {
reqSend.media = new TLRPC.TL_decryptedMessageMediaDocument(); reqSend.media = new TLRPC.TL_decryptedMessageMediaDocument();
reqSend.media.attributes = document.attributes; reqSend.media.attributes = document.attributes;
@ -3835,6 +3890,31 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
putToSendingMessages(message.messageObjects.get(message.messageObjects.size() - 1).messageOwner, message.finalGroupMessage != 0); putToSendingMessages(message.messageObjects.get(message.messageObjects.size() - 1).messageOwner, message.finalGroupMessage != 0);
} }
sendReadyToSendGroup(message, add, true); sendReadyToSendGroup(message, add, true);
} else if (message.type == 5) {
String key = "stickerset_" + message.obj.getId();
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
req.stickerset = (TLRPC.InputStickerSet) message.parentObject;
getConnectionsManager().sendRequest(req, (response, error) -> {
AndroidUtilities.runOnUIThread(() -> {
boolean found = false;
if (response != null) {
TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) response;
getMediaDataController().storeTempStickerSet(set);
TLRPC.TL_documentAttributeSticker_layer55 attributeSticker = (TLRPC.TL_documentAttributeSticker_layer55) message.locationParent;
attributeSticker.stickerset = new TLRPC.TL_inputStickerSetShortName();
attributeSticker.stickerset.short_name = set.set.short_name;
found = true;
}
ArrayList<DelayedMessage> arrayList = delayedMessages.remove(key);
if (arrayList != null && !arrayList.isEmpty()) {
if (found) {
getMessagesStorage().replaceMessageIfExists(arrayList.get(0).obj.messageOwner, null, null, false);
}
getSecretChatHelper().performSendEncryptedRequest((TLRPC.DecryptedMessage) message.sendEncryptedRequest, message.obj.messageOwner, message.encryptedChat, null, null, message.obj);
}
});
});
putToDelayedMessages(key, message);
} }
} }
@ -4622,7 +4702,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
newMsg.media.photo.id = sentMessage.media.photo.id; newMsg.media.photo.id = sentMessage.media.photo.id;
newMsg.media.photo.access_hash = sentMessage.media.photo.access_hash; newMsg.media.photo.access_hash = sentMessage.media.photo.access_hash;
} else if (sentMessage.media instanceof TLRPC.TL_messageMediaDocument && sentMessage.media.document != null && newMsg.media instanceof TLRPC.TL_messageMediaDocument && newMsg.media.document != null) { } else if (sentMessage.media instanceof TLRPC.TL_messageMediaDocument && sentMessage.media.document != null && newMsg.media instanceof TLRPC.TL_messageMediaDocument && newMsg.media.document != null) {
if (sentMessage.media.ttl_seconds == 0) { if (sentMessage.media.ttl_seconds == 0 && (newMsgObj.videoEditedInfo == null || newMsgObj.videoEditedInfo.mediaEntities == null && TextUtils.isEmpty(newMsgObj.videoEditedInfo.paintPath))) {
boolean isVideo = MessageObject.isVideoMessage(sentMessage); boolean isVideo = MessageObject.isVideoMessage(sentMessage);
if ((isVideo || MessageObject.isGifMessage(sentMessage)) && MessageObject.isGifDocument(sentMessage.media.document) == MessageObject.isGifDocument(newMsg.media.document)) { if ((isVideo || MessageObject.isGifMessage(sentMessage)) && MessageObject.isGifDocument(sentMessage.media.document) == MessageObject.isGifDocument(newMsg.media.document)) {
if (!newMsgObj.scheduled) { if (!newMsgObj.scheduled) {
@ -4842,7 +4922,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
boolean isEncrypted = (int) dialog_id == 0; boolean isEncrypted = (int) dialog_id == 0;
boolean allowSticker = !isEncrypted;
String name = f.getName(); String name = f.getName();
String ext = ""; String ext = "";
@ -5002,7 +5081,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
FileLog.e(e); FileLog.e(e);
} }
} }
if (document.mime_type.equals("image/webp") && allowSticker && editingMessageObject == null) { if (document.mime_type.equals("image/webp") && editingMessageObject == null) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options(); BitmapFactory.Options bmOptions = new BitmapFactory.Options();
try { try {
bmOptions.inJustDecodeBounds = true; bmOptions.inJustDecodeBounds = true;
@ -5202,7 +5281,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
info.entities = entities; info.entities = entities;
info.ttl = ttl; info.ttl = ttl;
if (stickers != null && !stickers.isEmpty()) { if (stickers != null) {
info.masks = new ArrayList<>(stickers); info.masks = new ArrayList<>(stickers);
} }
ArrayList<SendingMediaInfo> infos = new ArrayList<>(); ArrayList<SendingMediaInfo> infos = new ArrayList<>();
@ -5249,7 +5328,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
} }
} else if (result.content != null) { } else if (result.content != null) {
File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.content.url) + "." + ImageLoader.getHttpUrlExtension(result.content.url, "file")); String ext = ImageLoader.getHttpUrlExtension(result.content.url, null);
if (TextUtils.isEmpty(ext)) {
ext = FileLoader.getExtensionByMimeType(result.content.mime_type);
} else {
ext = "." + ext;
}
File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.content.url) + ext);
if (f.exists()) { if (f.exists()) {
finalPath = f.getAbsolutePath(); finalPath = f.getAbsolutePath();
} else { } else {
@ -5285,7 +5370,17 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
int side = isEncrypted ? 90 : 320; int side = isEncrypted ? 90 : 320;
Bitmap bitmap; Bitmap bitmap;
if (finalPath.endsWith("mp4")) { if (finalPath.endsWith("mp4")) {
bitmap = ThumbnailUtils.createVideoThumbnail(finalPath, MediaStore.Video.Thumbnails.MINI_KIND); bitmap = createVideoThumbnail(finalPath, MediaStore.Video.Thumbnails.MINI_KIND);
if (bitmap == null && result.thumb instanceof TLRPC.TL_webDocument && "video/mp4".equals(result.thumb.mime_type)) {
ext = ImageLoader.getHttpUrlExtension(result.thumb.url, null);
if (TextUtils.isEmpty(ext)) {
ext = FileLoader.getExtensionByMimeType(result.thumb.mime_type);
} else {
ext = "." + ext;
}
f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(result.thumb.url) + ext);
bitmap = createVideoThumbnail(f.getAbsolutePath(), MediaStore.Video.Thumbnails.MINI_KIND);
}
} else { } else {
bitmap = ImageLoader.loadBitmap(finalPath, null, side, side, true); bitmap = ImageLoader.loadBitmap(finalPath, null, side, side, true);
} }
@ -5562,7 +5657,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
bitmap = ImageLoader.loadBitmap(path, uri, 800, 800, true); bitmap = ImageLoader.loadBitmap(path, uri, 800, 800, true);
} }
if (!bigExists) { if (!bigExists) {
TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bigSize, bitmap, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 80, false, 101, 101,false); TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bigSize, bitmap, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 80, false, 101, 101,false);
if (size != bigSize) { if (size != bigSize) {
photo.sizes.add(0, size); photo.sizes.add(0, size);
} }
@ -5586,9 +5681,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
File smallFile = FileLoader.getPathToAttach(photoSize, true); File smallFile = FileLoader.getPathToAttach(photoSize, true);
if (!smallFile.exists()) { if (!smallFile.exists()) {
Bitmap thumb = createVideoThumbnail(path, startTime); Bitmap thumb = createVideoThumbnailAtTime(path, startTime);
if (thumb == null) { if (thumb == null) {
thumb = ThumbnailUtils.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MINI_KIND); thumb = SendMessagesHelper.createVideoThumbnail(path, MediaStore.Video.Thumbnails.MINI_KIND);
} }
int side = isEncrypted ? 90 : 320; int side = isEncrypted ? 90 : 320;
document.thumbs.set(0, ImageLoader.scaleAndSaveImage(photoSize, thumb, side, side, side > 90 ? 80 : 55, false, true)); document.thumbs.set(0, ImageLoader.scaleAndSaveImage(photoSize, thumb, side, side, side > 90 ? 80 : 55, false, true));
@ -5675,7 +5770,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
workers = new HashMap<>(); workers = new HashMap<>();
for (int a = 0; a < count; a++) { for (int a = 0; a < count; a++) {
final SendingMediaInfo info = media.get(a); final SendingMediaInfo info = media.get(a);
if (info.searchImage == null && !info.isVideo) { if (info.searchImage == null && !info.isVideo && info.videoEditedInfo == null) {
String originalPath = info.path; String originalPath = info.path;
String tempPath = info.path; String tempPath = info.path;
if (tempPath == null && info.uri != null) { if (tempPath == null && info.uri != null) {
@ -5754,7 +5849,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
lastGroupId = groupId = Utilities.random.nextLong(); lastGroupId = groupId = Utilities.random.nextLong();
photosCount = 0; photosCount = 0;
} }
if (info.searchImage != null) { if (info.searchImage != null && info.videoEditedInfo == null) {
if (info.searchImage.type == 1) { if (info.searchImage.type == 1) {
final HashMap<String, String> params = new HashMap<>(); final HashMap<String, String> params = new HashMap<>();
TLRPC.TL_document document = null; TLRPC.TL_document document = null;
@ -5808,7 +5903,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
int side = isEncrypted || info.ttl != 0 ? 90 : 320; int side = isEncrypted || info.ttl != 0 ? 90 : 320;
Bitmap bitmap; Bitmap bitmap;
if (thumbFile.getAbsolutePath().endsWith("mp4")) { if (thumbFile.getAbsolutePath().endsWith("mp4")) {
bitmap = ThumbnailUtils.createVideoThumbnail(thumbFile.getAbsolutePath(), MediaStore.Video.Thumbnails.MINI_KIND); bitmap = SendMessagesHelper.createVideoThumbnail(thumbFile.getAbsolutePath(), MediaStore.Video.Thumbnails.MINI_KIND);
} else { } else {
bitmap = ImageLoader.loadBitmap(thumbFile.getAbsolutePath(), null, side, side, true); bitmap = ImageLoader.loadBitmap(thumbFile.getAbsolutePath(), null, side, side, true);
} }
@ -5926,7 +6021,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
} }
} else { } else {
if (info.isVideo) { if (info.isVideo || info.videoEditedInfo != null) {
Bitmap thumb = null; Bitmap thumb = null;
String thumbKey = null; String thumbKey = null;
@ -5938,6 +6033,14 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
if (!forceDocument && (videoEditedInfo != null || info.path.endsWith("mp4"))) { if (!forceDocument && (videoEditedInfo != null || info.path.endsWith("mp4"))) {
if (info.path == null && info.searchImage != null) {
if (info.searchImage.photo instanceof TLRPC.TL_photo) {
info.path = FileLoader.getPathToAttach(info.searchImage.photo, true).getAbsolutePath();
} else {
String md5 = Utilities.MD5(info.searchImage.imageUrl) + "." + ImageLoader.getHttpUrlExtension(info.searchImage.imageUrl, "jpg");
info.path = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), md5).getAbsolutePath();
}
}
String path = info.path; String path = info.path;
String originalPath = info.path; String originalPath = info.path;
File temp = new File(originalPath); File temp = new File(originalPath);
@ -5955,7 +6058,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
TLRPC.TL_document document = null; TLRPC.TL_document document = null;
String parentObject = null; String parentObject = null;
if (!isEncrypted && info.ttl == 0) { if (!isEncrypted && info.ttl == 0 && (videoEditedInfo == null || videoEditedInfo.filterState == null && videoEditedInfo.paintPath == null && videoEditedInfo.mediaEntities == null)) {
Object[] sentData = accountInstance.getMessagesStorage().getSentFile(originalPath, !isEncrypted ? 2 : 5); Object[] sentData = accountInstance.getMessagesStorage().getSentFile(originalPath, !isEncrypted ? 2 : 5);
if (sentData != null) { if (sentData != null) {
document = (TLRPC.TL_document) sentData[0]; document = (TLRPC.TL_document) sentData[0];
@ -5964,10 +6067,16 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
} }
if (document == null) { if (document == null) {
thumb = createVideoThumbnail(info.path, startTime); if (info.thumbPath != null) {
if (thumb == null) { thumb = BitmapFactory.decodeFile(info.thumbPath);
thumb = ThumbnailUtils.createVideoThumbnail(info.path, MediaStore.Video.Thumbnails.MINI_KIND);
} }
if (thumb == null) {
thumb = createVideoThumbnailAtTime(info.path, startTime);
if (thumb == null) {
thumb = createVideoThumbnail(info.path, MediaStore.Video.Thumbnails.MINI_KIND);
}
}
TLRPC.PhotoSize size = null; TLRPC.PhotoSize size = null;
if (thumb != null) { if (thumb != null) {
int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight()); int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight());
@ -5994,8 +6103,8 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
attributeVideo.supports_streaming = true; attributeVideo.supports_streaming = true;
} }
document.attributes.add(attributeVideo); document.attributes.add(attributeVideo);
if (videoEditedInfo != null && videoEditedInfo.needConvert()) { if (videoEditedInfo != null && (videoEditedInfo.needConvert() || !info.isVideo)) {
if (videoEditedInfo.muted) { if (info.isVideo && videoEditedInfo.muted) {
fillVideoAttribute(info.path, attributeVideo, videoEditedInfo); fillVideoAttribute(info.path, attributeVideo, videoEditedInfo);
videoEditedInfo.originalWidth = attributeVideo.w; videoEditedInfo.originalWidth = attributeVideo.w;
videoEditedInfo.originalHeight = attributeVideo.h; videoEditedInfo.originalHeight = attributeVideo.h;
@ -6029,7 +6138,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
document.attributes.add(new TLRPC.TL_documentAttributeAnimated()); document.attributes.add(new TLRPC.TL_documentAttributeAnimated());
} }
} }
if (videoEditedInfo != null && videoEditedInfo.needConvert()) { if (videoEditedInfo != null && (videoEditedInfo.needConvert() || !info.isVideo)) {
String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".mp4"; String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".mp4";
File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
SharedConfig.saveConfig(); SharedConfig.saveConfig();
@ -6056,6 +6165,16 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
lastGroupId = 0; lastGroupId = 0;
} }
} }
if (!isEncrypted && info.masks != null && !info.masks.isEmpty()) {
document.attributes.add(new TLRPC.TL_documentAttributeHasStickers());
SerializedData serializedData = new SerializedData(4 + info.masks.size() * 20);
serializedData.writeInt32(info.masks.size());
for (int b = 0; b < info.masks.size(); b++) {
info.masks.get(b).serializeToStream(serializedData);
}
params.put("masks", Utilities.bytesToHex(serializedData.toByteArray()));
serializedData.cleanup();
}
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
if (thumbFinal != null && thumbKeyFinal != null) { if (thumbFinal != null && thumbKeyFinal != null) {
ImageLoader.getInstance().putImageToCache(new BitmapDrawable(thumbFinal), thumbKeyFinal); ImageLoader.getInstance().putImageToCache(new BitmapDrawable(thumbFinal), thumbKeyFinal);
@ -6078,6 +6197,42 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
boolean isDocument = false; boolean isDocument = false;
if (inputContent != null && info.uri != null) {
ClipDescription description = inputContent.getDescription();
if (description.hasMimeType("image/png")) {
InputStream inputStream = null;
FileOutputStream stream = null;
try {
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(info.uri);
Bitmap b = BitmapFactory.decodeStream(inputStream, null, bmOptions);
String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".webp";
File fileDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE);
final File cacheFile = new File(fileDir, fileName);
stream = new FileOutputStream(cacheFile);
b.compress(Bitmap.CompressFormat.WEBP, 100, stream);
SharedConfig.saveConfig();
info.uri = Uri.fromFile(cacheFile);
} catch (Throwable e) {
FileLog.e(e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (Exception ignore) {
}
try {
if (stream != null) {
stream.close();
}
} catch (Exception ignore) {
}
}
}
}
if (forceDocument || ImageLoader.shouldSendImageAsDocument(info.path, info.uri)) { if (forceDocument || ImageLoader.shouldSendImageAsDocument(info.path, info.uri)) {
isDocument = true; isDocument = true;
extension = tempPath != null ? FileLoader.getFileExtension(new File(tempPath)) : ""; extension = tempPath != null ? FileLoader.getFileExtension(new File(tempPath)) : "";
@ -6322,7 +6477,30 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
} }
private static Bitmap createVideoThumbnail(String filePath, long time) { public static Bitmap createVideoThumbnail(String filePath, int kind) {
float size;
if (kind == MediaStore.Video.Thumbnails.FULL_SCREEN_KIND) {
size = 1920;
} else if (kind == MediaStore.Video.Thumbnails.MICRO_KIND) {
size = 96;
} else {
size = 512;
}
Bitmap bitmap = createVideoThumbnailAtTime(filePath, 0);
if (bitmap != null) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
if (w > size || h > size) {
float scale = Math.max(w, h) / size;
w /= scale;
h /= scale;
bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
}
}
return bitmap;
}
public static Bitmap createVideoThumbnailAtTime(String filePath, long time) {
Bitmap bitmap = null; Bitmap bitmap = null;
MediaMetadataRetriever retriever = new MediaMetadataRetriever(); MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try { try {
@ -6515,9 +6693,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
} }
} }
if (document == null) { if (document == null) {
thumb = createVideoThumbnail(videoPath, startTime); thumb = createVideoThumbnailAtTime(videoPath, startTime);
if (thumb == null) { if (thumb == null) {
thumb = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND); thumb = createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND);
} }
int side = isEncrypted || ttl != 0 ? 90 : 320; int side = isEncrypted || ttl != 0 ? 90 : 320;
TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted); TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted);

View File

@ -20,8 +20,6 @@ import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Locale;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -54,7 +52,7 @@ public class Utilities {
public native static void unpinBitmap(Bitmap bitmap); public native static void unpinBitmap(Bitmap bitmap);
public native static void blurBitmap(Object bitmap, int radius, int unpin, int width, int height, int stride); public native static void blurBitmap(Object bitmap, int radius, int unpin, int width, int height, int stride);
public native static int needInvert(Object bitmap, int unpin, int width, int height, int stride); public native static int needInvert(Object bitmap, int unpin, int width, int height, int stride);
public native static void calcCDT(ByteBuffer hsvBuffer, int width, int height, ByteBuffer buffer); public native static void calcCDT(ByteBuffer hsvBuffer, int width, int height, ByteBuffer buffer, ByteBuffer calcBuffer);
public native static boolean loadWebpImage(Bitmap bitmap, ByteBuffer buffer, int len, BitmapFactory.Options options, boolean unpin); public native static boolean loadWebpImage(Bitmap bitmap, ByteBuffer buffer, int len, BitmapFactory.Options options, boolean unpin);
public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap); public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap);
private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length); private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length);

View File

@ -8,11 +8,19 @@
package org.telegram.messenger; package org.telegram.messenger;
import org.telegram.tgnet.TLRPC; import android.graphics.Bitmap;
import android.view.View;
import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.PhotoFilterView;
import org.telegram.ui.Components.Point;
import java.util.ArrayList;
import java.util.Locale; 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 start;
@ -34,14 +42,166 @@ public class VideoEditedInfo {
public TLRPC.InputEncryptedFile encryptedFile; public TLRPC.InputEncryptedFile encryptedFile;
public byte[] key; public byte[] key;
public byte[] iv; public byte[] iv;
public MediaController.SavedFilterState filterState;
public String paintPath;
public ArrayList<MediaEntity> mediaEntities;
public boolean isPhoto;
public boolean canceled; public boolean canceled;
public boolean videoConvertFirstWrite; public boolean videoConvertFirstWrite;
public boolean needUpdateProgress = false; public boolean needUpdateProgress = false;
public static class MediaEntity {
public byte type;
public byte subType;
public float x;
public float y;
public float rotation;
public float width;
public float height;
public String text;
public int color;
public int fontSize;
public int viewWidth;
public int viewHeight;
public float scale;
public float textViewWidth;
public float textViewHeight;
public float textViewX;
public float textViewY;
public TLRPC.Document document;
public Object parentObject;
public int[] metadata;
public long ptr;
public float currentFrame;
public float framesPerDraw;
public Bitmap bitmap;
public View view;
public MediaEntity() {
}
private MediaEntity(SerializedData data) {
type = data.readByte(false);
subType = data.readByte(false);
x = data.readFloat(false);
y = data.readFloat(false);
rotation = data.readFloat(false);
width = data.readFloat(false);
height = data.readFloat(false);
text = data.readString(false);
color = data.readInt32(false);
fontSize = data.readInt32(false);
viewWidth = data.readInt32(false);
viewHeight = data.readInt32(false);
}
private void serializeTo(SerializedData data) {
data.writeByte(type);
data.writeByte(subType);
data.writeFloat(x);
data.writeFloat(y);
data.writeFloat(rotation);
data.writeFloat(width);
data.writeFloat(height);
data.writeString(text);
data.writeInt32(color);
data.writeInt32(fontSize);
data.writeInt32(viewWidth);
data.writeInt32(viewHeight);
}
}
public String getString() { public String getString() {
return String.format(Locale.US, "-1_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%s", startTime, endTime, rotationValue, originalWidth, originalHeight, bitrate, resultWidth, resultHeight, originalDuration, framerate, originalPath); String filters;
if (filterState != null || paintPath != null || mediaEntities != null && !mediaEntities.isEmpty()) {
int len = 2;
if (filterState != null) {
len += 160;
}
byte[] paintPathBytes;
if (paintPath != null) {
paintPathBytes = paintPath.getBytes();
len += paintPathBytes.length;
} else {
paintPathBytes = null;
}
SerializedData serializedData = new SerializedData(len);
serializedData.writeInt32(1);
if (filterState != null) {
serializedData.writeByte(1);
serializedData.writeFloat(filterState.enhanceValue);
serializedData.writeFloat(filterState.exposureValue);
serializedData.writeFloat(filterState.contrastValue);
serializedData.writeFloat(filterState.warmthValue);
serializedData.writeFloat(filterState.saturationValue);
serializedData.writeFloat(filterState.fadeValue);
serializedData.writeInt32(filterState.tintShadowsColor);
serializedData.writeInt32(filterState.tintHighlightsColor);
serializedData.writeFloat(filterState.highlightsValue);
serializedData.writeFloat(filterState.shadowsValue);
serializedData.writeFloat(filterState.vignetteValue);
serializedData.writeFloat(filterState.grainValue);
serializedData.writeInt32(filterState.blurType);
serializedData.writeFloat(filterState.sharpenValue);
serializedData.writeFloat(filterState.blurExcludeSize);
if (filterState.blurExcludePoint != null) {
serializedData.writeFloat(filterState.blurExcludePoint.x);
serializedData.writeFloat(filterState.blurExcludePoint.y);
} else {
serializedData.writeFloat(0);
serializedData.writeFloat(0);
}
serializedData.writeFloat(filterState.blurExcludeBlurSize);
serializedData.writeFloat(filterState.blurAngle);
for (int a = 0; a < 4; a++) {
PhotoFilterView.CurvesValue curvesValue;
if (a == 0) {
curvesValue = filterState.curvesToolValue.luminanceCurve;
} else if (a == 1) {
curvesValue = filterState.curvesToolValue.redCurve;
} else if (a == 2) {
curvesValue = filterState.curvesToolValue.greenCurve;
} else {
curvesValue = filterState.curvesToolValue.blueCurve;
}
serializedData.writeFloat(curvesValue.blacksLevel);
serializedData.writeFloat(curvesValue.shadowsLevel);
serializedData.writeFloat(curvesValue.midtonesLevel);
serializedData.writeFloat(curvesValue.highlightsLevel);
serializedData.writeFloat(curvesValue.whitesLevel);
}
} else {
serializedData.writeByte(0);
}
if (paintPathBytes != null) {
serializedData.writeByte(1);
serializedData.writeByteArray(paintPathBytes);
} else {
serializedData.writeByte(0);
}
if (mediaEntities != null && !mediaEntities.isEmpty()) {
serializedData.writeByte(1);
serializedData.writeInt32(mediaEntities.size());
for (int a = 0, N = mediaEntities.size(); a < N; a++) {
mediaEntities.get(a).serializeTo(serializedData);
}
serializedData.writeByte(isPhoto ? 1 : 0);
} else {
serializedData.writeByte(0);
}
filters = Utilities.bytesToHex(serializedData.toByteArray());
serializedData.cleanup();
} else {
filters = "";
}
return String.format(Locale.US, "-1_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_-%s_%s", startTime, endTime, rotationValue, originalWidth, originalHeight, bitrate, resultWidth, resultHeight, originalDuration, framerate, filters, originalPath);
} }
public boolean parseString(String string) { public boolean parseString(String string) {
@ -49,7 +209,7 @@ public class VideoEditedInfo {
return false; return false;
} }
try { try {
String args[] = string.split("_"); String[] args = string.split("_");
if (args.length >= 11) { if (args.length >= 11) {
startTime = Long.parseLong(args[1]); startTime = Long.parseLong(args[1]);
endTime = Long.parseLong(args[2]); endTime = Long.parseLong(args[2]);
@ -61,8 +221,76 @@ public class VideoEditedInfo {
resultHeight = Integer.parseInt(args[8]); resultHeight = Integer.parseInt(args[8]);
originalDuration = Long.parseLong(args[9]); originalDuration = Long.parseLong(args[9]);
framerate = Integer.parseInt(args[10]); framerate = Integer.parseInt(args[10]);
muted = bitrate == -1;
int start;
if (args[11].startsWith("-")) {
start = 12;
String s = args[11].substring(1);
if (s.length() > 0) {
SerializedData serializedData = new SerializedData(Utilities.hexToBytes(s));
int version = serializedData.readInt32(false);
byte has = serializedData.readByte(false);
if (has != 0) {
filterState = new MediaController.SavedFilterState();
filterState.enhanceValue = serializedData.readFloat(false);
filterState.exposureValue = serializedData.readFloat(false);
filterState.contrastValue = serializedData.readFloat(false);
filterState.warmthValue = serializedData.readFloat(false);
filterState.saturationValue = serializedData.readFloat(false);
filterState.fadeValue = serializedData.readFloat(false);
filterState.tintShadowsColor = serializedData.readInt32(false);
filterState.tintHighlightsColor = serializedData.readInt32(false);
filterState.highlightsValue = serializedData.readFloat(false);
filterState.shadowsValue = serializedData.readFloat(false);
filterState.vignetteValue = serializedData.readFloat(false);
filterState.grainValue = serializedData.readFloat(false);
filterState.blurType = serializedData.readInt32(false);
filterState.sharpenValue = serializedData.readFloat(false);
filterState.blurExcludeSize = serializedData.readFloat(false);
filterState.blurExcludePoint = new Point(serializedData.readFloat(false), serializedData.readFloat(false));
filterState.blurExcludeBlurSize = serializedData.readFloat(false);
filterState.blurAngle = serializedData.readFloat(false);
for (int a = 11; a < args.length; a++) { for (int a = 0; a < 4; a++) {
PhotoFilterView.CurvesValue curvesValue;
if (a == 0) {
curvesValue = filterState.curvesToolValue.luminanceCurve;
} else if (a == 1) {
curvesValue = filterState.curvesToolValue.redCurve;
} else if (a == 2) {
curvesValue = filterState.curvesToolValue.greenCurve;
} else {
curvesValue = filterState.curvesToolValue.blueCurve;
}
curvesValue.blacksLevel = serializedData.readFloat(false);
curvesValue.shadowsLevel = serializedData.readFloat(false);
curvesValue.midtonesLevel = serializedData.readFloat(false);
curvesValue.highlightsLevel = serializedData.readFloat(false);
curvesValue.whitesLevel = serializedData.readFloat(false);
}
}
has = serializedData.readByte(false);
if (has != 0) {
byte[] bytes = serializedData.readByteArray(false);
paintPath = new String(bytes);
}
has = serializedData.readByte(false);
if (has != 0) {
int count = serializedData.readInt32(false);
mediaEntities = new ArrayList<>(count);
for (int a = 0; a < count; a++) {
mediaEntities.add(new MediaEntity(serializedData));
}
isPhoto = serializedData.readByte(false) == 1;
}
serializedData.cleanup();
}
} else {
start = 11;
}
for (int a = start; a < args.length; a++) {
if (originalPath == null) { if (originalPath == null) {
originalPath = args[a]; originalPath = args[a];
} else { } else {
@ -80,4 +308,8 @@ public class VideoEditedInfo {
public boolean needConvert() { public boolean needConvert() {
return !roundVideo || roundVideo && (startTime > 0 || endTime != -1 && endTime != estimatedDuration); return !roundVideo || roundVideo && (startTime > 0 || endTime != -1 && endTime != estimatedDuration);
} }
public boolean canAutoPlaySourceVideo() {
return roundVideo;// || (Math.max(originalHeight,originalWidth) <= 1920 && filterState == null) ;
}
} }

View File

@ -17,7 +17,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.hardware.Camera; import android.hardware.Camera;
import android.media.MediaMetadataRetriever; import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder; import android.media.MediaRecorder;
import android.media.ThumbnailUtils;
import android.os.Build; import android.os.Build;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.util.Base64; import android.util.Base64;
@ -31,6 +30,7 @@ import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLoader;
import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.SendMessagesHelper;
import org.telegram.messenger.SharedConfig; import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.Utilities; import org.telegram.messenger.Utilities;
import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.SerializedData;
@ -671,7 +671,7 @@ public class CameraController implements MediaRecorder.OnInfoListener {
FileLog.e(e); FileLog.e(e);
} }
} }
final Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(recordedFile, MediaStore.Video.Thumbnails.MINI_KIND); final Bitmap bitmap = SendMessagesHelper.createVideoThumbnail(recordedFile, MediaStore.Video.Thumbnails.MINI_KIND);
String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".jpg"; String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".jpg";
final File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); final File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
try { try {

View File

@ -20,8 +20,12 @@ import android.graphics.SurfaceTexture;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.view.Surface; import android.view.Surface;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.VideoEditedInfo;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.ArrayList;
import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLConfig;
@ -58,15 +62,15 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
mPixelBuf.order(ByteOrder.LITTLE_ENDIAN); mPixelBuf.order(ByteOrder.LITTLE_ENDIAN);
eglSetup(width, height); eglSetup(width, height);
makeCurrent(); makeCurrent();
setup(); setup(null, null, null, null, 0, 0, 0, false);
} }
public OutputSurface() { public OutputSurface(MediaController.SavedFilterState savedFilterState, String imagePath, String paintPath, ArrayList<VideoEditedInfo.MediaEntity> mediaEntities, int w, int h, float fps, boolean photo) {
setup(); setup(savedFilterState, imagePath, paintPath, mediaEntities, w, h, fps, photo);
} }
private void setup() { private void setup(MediaController.SavedFilterState savedFilterState, String imagePath, String paintPath, ArrayList<VideoEditedInfo.MediaEntity> mediaEntities, int w, int h, float fps, boolean photo) {
mTextureRender = new TextureRenderer(rotateRender); mTextureRender = new TextureRenderer(rotateRender, savedFilterState, imagePath, paintPath, mediaEntities, w, h, fps, photo);
mTextureRender.surfaceCreated(); mTextureRender.surfaceCreated();
mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId()); mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
mSurfaceTexture.setOnFrameAvailableListener(this); mSurfaceTexture.setOnFrameAvailableListener(this);
@ -129,6 +133,9 @@ public class OutputSurface implements SurfaceTexture.OnFrameAvailableListener {
mEGL.eglDestroySurface(mEGLDisplay, mEGLSurface); mEGL.eglDestroySurface(mEGLDisplay, mEGLSurface);
mEGL.eglDestroyContext(mEGLDisplay, mEGLContext); mEGL.eglDestroyContext(mEGLDisplay, mEGLContext);
} }
if (mTextureRender != null) {
mTextureRender.release();
}
mSurface.release(); mSurface.release();
mEGLDisplay = null; mEGLDisplay = null;
mEGLContext = null; mEGLContext = null;

View File

@ -1,37 +1,75 @@
/* /*
* Copyright (C) 2013 The Android Open Source Project * 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).
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Copyright Nikolai Kudashov, 2013-2020.
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.telegram.messenger.video; package org.telegram.messenger.video;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.graphics.Typeface;
import android.opengl.GLES11Ext; import android.opengl.GLES11Ext;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix; import android.opengl.Matrix;
import android.os.Build;
import android.text.Layout;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.Bitmaps;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.Utilities;
import org.telegram.messenger.VideoEditedInfo;
import org.telegram.ui.Components.FilterShaders;
import org.telegram.ui.Components.Paint.Views.EditTextOutline;
import org.telegram.ui.Components.RLottieDrawable;
import javax.microedition.khronos.opengles.GL10;
import androidx.annotation.RequiresApi;
import androidx.exifinterface.media.ExifInterface;
public class TextureRenderer { public class TextureRenderer {
private static final int FLOAT_SIZE_BYTES = 4; private FloatBuffer verticesBuffer;
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; private FloatBuffer textureBuffer;
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; private FloatBuffer bitmapVerticesBuffer;
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
private FloatBuffer mTriangleVertices; float[] bitmapData = {
-1.0f, 1.0f,
1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, -1.0f,
};
private FilterShaders filterShaders;
private String paintPath;
private String imagePath;
private ArrayList<VideoEditedInfo.MediaEntity> mediaEntities;
private int videoWidth;
private int videoHeight;
private static final String VERTEX_SHADER = private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" + "uniform mat4 uMVPMatrix;\n" +
@ -62,19 +100,64 @@ public class TextureRenderer {
private int maPositionHandle; private int maPositionHandle;
private int maTextureHandle; private int maTextureHandle;
private int simpleShaderProgram;
private int simplePositionHandle;
private int simpleInputTexCoordHandle;
private int simpleSourceImageHandle;
private int rotationAngle; private int rotationAngle;
public TextureRenderer(int rotation) { private int[] paintTexture;
private int[] stickerTexture;
private Bitmap stickerBitmap;
private float videoFps;
private int imageOrientation;
private boolean blendEnabled;
private boolean isPhoto;
public TextureRenderer(int rotation, MediaController.SavedFilterState savedFilterState, String image, String paint, ArrayList<VideoEditedInfo.MediaEntity> entities, int w, int h, float fps, boolean photo) {
rotationAngle = rotation; rotationAngle = rotation;
float[] mTriangleVerticesData = { isPhoto = photo;
-1.0f, -1.0f, 0, 0.f, 0.f, float[] verticesData = {
1.0f, -1.0f, 0, 1.f, 0.f, -1.0f, -1.0f,
-1.0f, 1.0f, 0, 0.f, 1.f, 1.0f, -1.0f,
1.0f, 1.0f, 0, 1.f, 1.f, -1.0f, 1.0f,
1.0f, 1.0f,
}; };
mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); float[] texData = {
mTriangleVertices.put(mTriangleVerticesData).position(0); 0.f, 0.f,
1.f, 0.f,
0.f, 1.f,
1.f, 1.f,
};
verticesBuffer = ByteBuffer.allocateDirect(verticesData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
verticesBuffer.put(verticesData).position(0);
textureBuffer = ByteBuffer.allocateDirect(texData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
textureBuffer.put(texData).position(0);
verticesBuffer = ByteBuffer.allocateDirect(verticesData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
verticesBuffer.put(verticesData).position(0);
bitmapVerticesBuffer = ByteBuffer.allocateDirect(bitmapData.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
bitmapVerticesBuffer.put(bitmapData).position(0);
Matrix.setIdentityM(mSTMatrix, 0); Matrix.setIdentityM(mSTMatrix, 0);
if (savedFilterState != null) {
filterShaders = new FilterShaders(true);
filterShaders.setDelegate(FilterShaders.getFilterShadersDelegate(savedFilterState));
}
videoWidth = w;
videoHeight = h;
imagePath = image;
paintPath = paint;
mediaEntities = entities;
videoFps = fps == 0 ? 30 : fps;
} }
public int getTextureId() { public int getTextureId() {
@ -83,35 +166,173 @@ public class TextureRenderer {
public void drawFrame(SurfaceTexture st, boolean invert) { public void drawFrame(SurfaceTexture st, boolean invert) {
checkGlError("onDrawFrame start"); checkGlError("onDrawFrame start");
st.getTransformMatrix(mSTMatrix); if (isPhoto) {
GLES20.glUseProgram(simpleShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
if (invert) { GLES20.glUniform1i(simpleSourceImageHandle, 0);
mSTMatrix[5] = -mSTMatrix[5]; GLES20.glEnableVertexAttribArray(simpleInputTexCoordHandle);
mSTMatrix[13] = 1.0f - mSTMatrix[13]; GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(simplePositionHandle);
} else {
st.getTransformMatrix(mSTMatrix);
if (blendEnabled) {
GLES20.glDisable(GLES20.GL_BLEND);
blendEnabled = false;
}
if (filterShaders != null) {
filterShaders.onVideoFrameUpdate(mSTMatrix);
GLES20.glViewport(0, 0, videoWidth, videoHeight);
filterShaders.drawEnhancePass();
filterShaders.drawSharpenPass();
filterShaders.drawCustomParamsPass();
boolean blurred = filterShaders.drawBlurPass();
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glUseProgram(simpleShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, filterShaders.getRenderTexture(blurred ? 0 : 1));
GLES20.glUniform1i(simpleSourceImageHandle, 0);
GLES20.glEnableVertexAttribArray(simpleInputTexCoordHandle);
GLES20.glVertexAttribPointer(simpleInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, filterShaders.getTextureBuffer());
GLES20.glEnableVertexAttribArray(simplePositionHandle);
GLES20.glVertexAttribPointer(simplePositionHandle, 2, GLES20.GL_FLOAT, false, 8, filterShaders.getVertexBuffer());
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
} else {
if (invert) {
mSTMatrix[5] = -mSTMatrix[5];
mSTMatrix[13] = 1.0f - mSTMatrix[13];
}
GLES20.glUseProgram(mProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
GLES20.glVertexAttribPointer(maPositionHandle, 2, GLES20.GL_FLOAT, false, 8, verticesBuffer);
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(maTextureHandle);
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
if (paintTexture != null || stickerTexture != null) {
GLES20.glUseProgram(simpleShaderProgram);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glUniform1i(simpleSourceImageHandle, 0);
GLES20.glEnableVertexAttribArray(simpleInputTexCoordHandle);
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glEnableVertexAttribArray(simplePositionHandle);
}
}
}
if (paintTexture != null) {
for (int a = 0; a < paintTexture.length; a++) {
drawTexture(true, paintTexture[a]);
}
}
if (stickerTexture != null) {
for (int a = 0, N = mediaEntities.size(); a < N; a++) {
VideoEditedInfo.MediaEntity entity = mediaEntities.get(a);
if (entity.ptr != 0) {
RLottieDrawable.getFrame(entity.ptr, (int) entity.currentFrame, stickerBitmap, 512, 512, stickerBitmap.getRowBytes());
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, stickerTexture[0]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, stickerBitmap, 0);
entity.currentFrame += entity.framesPerDraw;
if (entity.currentFrame >= entity.metadata[0]) {
entity.currentFrame = 0;
}
drawTexture(false, stickerTexture[0], entity.x, entity.y, entity.width, entity.height, entity.rotation, (entity.subType & 2) != 0);
} else if (entity.bitmap != null) {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, stickerTexture[0]);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, entity.bitmap, 0);
drawTexture(false, stickerTexture[0], entity.x, entity.y, entity.width, entity.height, entity.rotation, (entity.subType & 2) != 0);
}
}
} }
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maPosition");
GLES20.glEnableVertexAttribArray(maPositionHandle);
checkGlError("glEnableVertexAttribArray maPositionHandle");
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
checkGlError("glVertexAttribPointer maTextureHandle");
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
checkGlError("glDrawArrays");
GLES20.glFinish(); GLES20.glFinish();
} }
private void drawTexture(boolean bind, int texture) {
drawTexture(bind, texture, -10000, -10000, -10000, -10000, 0, false);
}
private void drawTexture(boolean bind, int texture, float x, float y, float w, float h, float rotation, boolean mirror) {
if (!blendEnabled) {
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
blendEnabled = true;
}
if (x <= -10000) {
bitmapData[0] = -1.0f;
bitmapData[1] = 1.0f;
bitmapData[2] = 1.0f;
bitmapData[3] = 1.0f;
bitmapData[4] = -1.0f;
bitmapData[5] = -1.0f;
bitmapData[6] = 1.0f;
bitmapData[7] = -1.0f;
} else {
x = x * 2 - 1.0f;
y = (1.0f - y) * 2 - 1.0f;
w = w * 2;
h = h * 2;
bitmapData[0] = x;
bitmapData[1] = y;
bitmapData[2] = x + w;
bitmapData[3] = y;
bitmapData[4] = x;
bitmapData[5] = y - h;
bitmapData[6] = x + w;
bitmapData[7] = y - h;
}
float mx = (bitmapData[0] + bitmapData[2]) / 2;
if (mirror) {
float temp = bitmapData[2];
bitmapData[2] = bitmapData[0];
bitmapData[0] = temp;
temp = bitmapData[6];
bitmapData[6] = bitmapData[4];
bitmapData[4] = temp;
}
if (rotation != 0) {
float ratio = videoWidth / (float) videoHeight;
float my = (bitmapData[5] + bitmapData[1]) / 2;
for (int a = 0; a < 4; a++) {
float x1 = bitmapData[a * 2 ] - mx;
float y1 = (bitmapData[a * 2 + 1] - my) / ratio;
bitmapData[a * 2 ] = (float) (x1 * Math.cos(rotation) - y1 * Math.sin(rotation)) + mx;
bitmapData[a * 2 + 1] = (float) (x1 * Math.sin(rotation) + y1 * Math.cos(rotation)) * ratio + my;
}
}
bitmapVerticesBuffer.put(bitmapData).position(0);
GLES20.glVertexAttribPointer(maPositionHandle, 2, GLES20.GL_FLOAT, false, 8, bitmapVerticesBuffer);
if (bind) {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
}
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
@RequiresApi(api = Build.VERSION_CODES.M)
public void setBreakStrategy(EditTextOutline editText) {
editText.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
}
@SuppressLint("WrongConstant")
public void surfaceCreated() { public void surfaceCreated() {
mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER); mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
if (mProgram == 0) { if (mProgram == 0) {
@ -152,28 +373,194 @@ public class TextureRenderer {
if (rotationAngle != 0) { if (rotationAngle != 0) {
Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1); Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1);
} }
}
private int loadShader(int shaderType, String source) { if (filterShaders != null || imagePath != null || paintPath != null || mediaEntities != null) {
int shader = GLES20.glCreateShader(shaderType); int vertexShader = FilterShaders.loadShader(GLES20.GL_VERTEX_SHADER, FilterShaders.simpleVertexShaderCode);
checkGlError("glCreateShader type=" + shaderType); int fragmentShader = FilterShaders.loadShader(GLES20.GL_FRAGMENT_SHADER, FilterShaders.simpleFragmentShaderCode);
GLES20.glShaderSource(shader, source); if (vertexShader != 0 && fragmentShader != 0) {
GLES20.glCompileShader(shader); simpleShaderProgram = GLES20.glCreateProgram();
int[] compiled = new int[1]; GLES20.glAttachShader(simpleShaderProgram, vertexShader);
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); GLES20.glAttachShader(simpleShaderProgram, fragmentShader);
if (compiled[0] == 0) { GLES20.glBindAttribLocation(simpleShaderProgram, 0, "position");
GLES20.glDeleteShader(shader); GLES20.glBindAttribLocation(simpleShaderProgram, 1, "inputTexCoord");
shader = 0;
GLES20.glLinkProgram(simpleShaderProgram);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(simpleShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] == 0) {
GLES20.glDeleteProgram(simpleShaderProgram);
simpleShaderProgram = 0;
} else {
simplePositionHandle = GLES20.glGetAttribLocation(simpleShaderProgram, "position");
simpleInputTexCoordHandle = GLES20.glGetAttribLocation(simpleShaderProgram, "inputTexCoord");
simpleSourceImageHandle = GLES20.glGetUniformLocation(simpleShaderProgram, "sourceImage");
}
}
}
if (filterShaders != null) {
filterShaders.create();
filterShaders.setRenderData(null, 0, mTextureID, videoWidth, videoHeight);
}
if (imagePath != null || paintPath != null) {
paintTexture = new int[(imagePath != null ? 1 : 0) + (paintPath != null ? 1 : 0)];
GLES20.glGenTextures(paintTexture.length, paintTexture, 0);
try {
for (int a = 0; a < paintTexture.length; a++) {
String path;
int angle = 0;
if (a == 0 && imagePath != null) {
path = imagePath;
try {
ExifInterface exif = new ExifInterface(path);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
angle = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
angle = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
angle = 270;
break;
}
} catch (Throwable ignore) {
}
} else {
path = paintPath;
}
Bitmap bitmap = BitmapFactory.decodeFile(path);
if (bitmap != null) {
if (a == 0 && imagePath != null) {
Bitmap newBitmap = Bitmap.createBitmap(videoWidth, videoHeight, Bitmap.Config.ARGB_8888);
newBitmap.eraseColor(0xff000000);
Canvas canvas = new Canvas(newBitmap);
float scale;
if (angle == 90 || angle == 270) {
scale = Math.max(bitmap.getHeight() / (float) videoWidth, bitmap.getWidth() / (float) videoHeight);
} else {
scale = Math.max(bitmap.getWidth() / (float) videoWidth, bitmap.getHeight() / (float) videoHeight);
}
android.graphics.Matrix matrix = new android.graphics.Matrix();
matrix.postTranslate(-bitmap.getWidth() / 2, -bitmap.getHeight() / 2);
matrix.postScale(1.0f / scale, 1.0f / scale);
matrix.postRotate(angle);
matrix.postTranslate(newBitmap.getWidth() / 2, newBitmap.getHeight() / 2);
canvas.drawBitmap(bitmap, matrix, new Paint(Paint.FILTER_BITMAP_FLAG));
bitmap = newBitmap;
}
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, paintTexture[a]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
}
}
} catch (Throwable e) {
FileLog.e(e);
}
}
if (mediaEntities != null) {
try {
stickerBitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
stickerTexture = new int[1];
GLES20.glGenTextures(1, stickerTexture, 0);
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, stickerTexture[0]);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
for (int a = 0, N = mediaEntities.size(); a < N; a++) {
VideoEditedInfo.MediaEntity entity = mediaEntities.get(a);
if (entity.type == 0) {
if ((entity.subType & 1) != 0) {
entity.metadata = new int[3];
entity.ptr = RLottieDrawable.create(entity.text, 512, 512, entity.metadata, false, null, false);
entity.framesPerDraw = entity.metadata[1] / videoFps;
} else {
if (Build.VERSION.SDK_INT >= 19) {
entity.bitmap = BitmapFactory.decodeFile(entity.text);
} else {
File path = new File(entity.text);
RandomAccessFile file = new RandomAccessFile(path, "r");
ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, path.length());
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
Utilities.loadWebpImage(null, buffer, buffer.limit(), bmOptions, true);
entity.bitmap = Bitmaps.createBitmap(bmOptions.outWidth, bmOptions.outHeight, Bitmap.Config.ARGB_8888);
Utilities.loadWebpImage(entity.bitmap, buffer, buffer.limit(), null, true);
file.close();
}
if (entity.bitmap != null) {
float aspect = entity.bitmap.getWidth() / (float) entity.bitmap.getHeight();
if (aspect > 1) {
float h = entity.height / aspect;
entity.y += (entity.height - h) / 2;
entity.height = h;
} else if (aspect < 1) {
float w = entity.width * aspect;
entity.x += (entity.width - w) / 2;
entity.width = w;
}
}
}
} else if (entity.type == 1) {
EditTextOutline editText = new EditTextOutline(ApplicationLoader.applicationContext);
editText.setBackgroundColor(Color.TRANSPARENT);
editText.setPadding(AndroidUtilities.dp(7), AndroidUtilities.dp(7), AndroidUtilities.dp(7), AndroidUtilities.dp(7));
editText.setTextSize(TypedValue.COMPLEX_UNIT_PX, entity.fontSize);
editText.setText(entity.text);
editText.setTextColor(entity.color);
editText.setTypeface(null, Typeface.BOLD);
editText.setGravity(Gravity.CENTER);
editText.setHorizontallyScrolling(false);
editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
editText.setFocusableInTouchMode(true);
editText.setInputType(editText.getInputType() | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES);
if (Build.VERSION.SDK_INT >= 23) {
setBreakStrategy(editText);
}
if ((entity.subType & 1) != 0) {
editText.setTextColor(0xffffffff);
editText.setStrokeColor(entity.color);
editText.setFrameColor(0);
editText.setShadowLayer(0, 0, 0, 0);
} else if ((entity.subType & 4) != 0) {
editText.setTextColor(0xff000000);
editText.setStrokeColor(0);
editText.setFrameColor(entity.color);
editText.setShadowLayer(0, 0, 0, 0);
} else {
editText.setTextColor(entity.color);
editText.setStrokeColor(0);
editText.setFrameColor(0);
editText.setShadowLayer(5, 0, 1, 0x66000000);
}
editText.measure(View.MeasureSpec.makeMeasureSpec(entity.viewWidth, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(entity.viewHeight, View.MeasureSpec.EXACTLY));
editText.layout(0, 0, entity.viewWidth, entity.viewHeight);
entity.bitmap = Bitmap.createBitmap(entity.viewWidth, entity.viewHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(entity.bitmap);
editText.draw(canvas);
}
}
} catch (Throwable e) {
FileLog.e(e);
}
} }
return shader;
} }
private int createProgram(String vertexSource, String fragmentSource) { private int createProgram(String vertexSource, String fragmentSource) {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); int vertexShader = FilterShaders.loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) { if (vertexShader == 0) {
return 0; return 0;
} }
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); int pixelShader = FilterShaders.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
if (pixelShader == 0) { if (pixelShader == 0) {
return 0; return 0;
} }
@ -202,4 +589,15 @@ public class TextureRenderer {
throw new RuntimeException(op + ": glError " + error); throw new RuntimeException(op + ": glError " + error);
} }
} }
public void release() {
if (mediaEntities != null) {
for (int a = 0, N = mediaEntities.size(); a < N; a++) {
VideoEditedInfo.MediaEntity entity = mediaEntities.get(a);
if (entity.ptr != 0) {
RLottieDrawable.destroy(entity.ptr);
}
}
}
}
} }

View File

@ -614,6 +614,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
if(!USE_CONNECTION_SERVICE){ if(!USE_CONNECTION_SERVICE){
if(isBtHeadsetConnected && !playingSound){ if(isBtHeadsetConnected && !playingSound){
am.stopBluetoothSco(); am.stopBluetoothSco();
am.setBluetoothScoOn(false);
am.setSpeakerphoneOn(false); am.setSpeakerphoneOn(false);
} }
try{ try{

View File

@ -315,6 +315,17 @@ public class SerializedData extends AbstractSerializedData {
} }
} }
public void writeFloat(float d) {
try {
writeInt32(Float.floatToIntBits(d));
} catch (Exception e) {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("write float error");
FileLog.e(e);
}
}
}
public int length() { public int length() {
if (!justCalc) { if (!justCalc) {
return isOut ? outbuf.size() : inbuf.available(); return isOut ? outbuf.size() : inbuf.available();
@ -370,6 +381,24 @@ public class SerializedData extends AbstractSerializedData {
return false; return false;
} }
public byte readByte(boolean exception) {
try {
byte result = in.readByte();
len += 1;
return result;
} catch (Exception e) {
if (exception) {
throw new RuntimeException("read byte error", e);
} else {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("read byte error");
FileLog.e(e);
}
}
}
return 0;
}
public void readBytes(byte[] b, boolean exception) { public void readBytes(byte[] b, boolean exception) {
try { try {
in.read(b); in.read(b);
@ -474,6 +503,22 @@ public class SerializedData extends AbstractSerializedData {
return 0; return 0;
} }
public float readFloat(boolean exception) {
try {
return Float.intBitsToFloat(readInt32(exception));
} catch (Exception e) {
if (exception) {
throw new RuntimeException("read float error", e);
} else {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("read float error");
FileLog.e(e);
}
}
}
return 0;
}
public int readInt32(boolean exception) { public int readInt32(boolean exception) {
try { try {
int i = 0; int i = 0;

View File

@ -61,7 +61,7 @@ public class TLRPC {
public static final int MESSAGE_FLAG_EDITED = 0x00008000; public static final int MESSAGE_FLAG_EDITED = 0x00008000;
public static final int MESSAGE_FLAG_MEGAGROUP = 0x80000000; public static final int MESSAGE_FLAG_MEGAGROUP = 0x80000000;
public static final int LAYER = 113; public static final int LAYER = 114;
public static class TL_chatBannedRights extends TLObject { public static class TL_chatBannedRights extends TLObject {
public static int constructor = 0x9f120418; public static int constructor = 0x9f120418;
@ -5213,78 +5213,6 @@ public class TLRPC {
} }
} }
public static abstract class FoundGif extends TLObject {
public String url;
public Photo photo;
public Document document;
public String thumb_url;
public String content_url;
public String content_type;
public int w;
public int h;
public static FoundGif TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
FoundGif result = null;
switch (constructor) {
case 0x9c750409:
result = new TL_foundGifCached();
break;
case 0x162ecc1f:
result = new TL_foundGif();
break;
}
if (result == null && exception) {
throw new RuntimeException(String.format("can't parse magic %x in FoundGif", constructor));
}
if (result != null) {
result.readParams(stream, exception);
}
return result;
}
}
public static class TL_foundGifCached extends FoundGif {
public static int constructor = 0x9c750409;
public void readParams(AbstractSerializedData stream, boolean exception) {
url = stream.readString(exception);
photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception);
document = Document.TLdeserialize(stream, stream.readInt32(exception), exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(url);
photo.serializeToStream(stream);
document.serializeToStream(stream);
}
}
public static class TL_foundGif extends FoundGif {
public static int constructor = 0x162ecc1f;
public void readParams(AbstractSerializedData stream, boolean exception) {
url = stream.readString(exception);
thumb_url = stream.readString(exception);
content_url = stream.readString(exception);
content_type = stream.readString(exception);
w = stream.readInt32(exception);
h = stream.readInt32(exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(url);
stream.writeString(thumb_url);
stream.writeString(content_url);
stream.writeString(content_type);
stream.writeInt32(w);
stream.writeInt32(h);
}
}
public static abstract class payments_PaymentResult extends TLObject { public static abstract class payments_PaymentResult extends TLObject {
public static payments_PaymentResult TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { public static payments_PaymentResult TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
@ -5981,7 +5909,7 @@ public class TLRPC {
if ((flags & 1) != 0) { if ((flags & 1) != 0) {
document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); document = Document.TLdeserialize(stream, stream.readInt32(exception), exception);
} else { } else {
document = new TLRPC.TL_documentEmpty(); document = new TL_documentEmpty();
} }
if ((flags & 4) != 0) { if ((flags & 4) != 0) {
ttl_seconds = stream.readInt32(exception); ttl_seconds = stream.readInt32(exception);
@ -6009,7 +5937,7 @@ public class TLRPC {
if ((flags & 1) != 0) { if ((flags & 1) != 0) {
document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); document = Document.TLdeserialize(stream, stream.readInt32(exception), exception);
} else { } else {
document = new TLRPC.TL_documentEmpty(); document = new TL_documentEmpty();
} }
if ((flags & 2) != 0) { if ((flags & 2) != 0) {
captionLegacy = stream.readString(exception); captionLegacy = stream.readString(exception);
@ -6072,7 +6000,7 @@ public class TLRPC {
if ((flags & 1) != 0) { if ((flags & 1) != 0) {
photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception);
} else { } else {
photo = new TLRPC.TL_photoEmpty(); photo = new TL_photoEmpty();
} }
if ((flags & 4) != 0) { if ((flags & 4) != 0) {
ttl_seconds = stream.readInt32(exception); ttl_seconds = stream.readInt32(exception);
@ -6117,7 +6045,7 @@ public class TLRPC {
if ((flags & 1) != 0) { if ((flags & 1) != 0) {
photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception);
} else { } else {
photo = new TLRPC.TL_photoEmpty(); photo = new TL_photoEmpty();
} }
if ((flags & 2) != 0) { if ((flags & 2) != 0) {
captionLegacy = stream.readString(exception); captionLegacy = stream.readString(exception);
@ -11561,6 +11489,46 @@ public class TLRPC {
} }
} }
public static class TL_videoSize extends TLObject {
public static int constructor = 0x435bb987;
public String type;
public FileLocation location;
public int w;
public int h;
public int size;
public static TL_videoSize TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (TL_videoSize.constructor != constructor) {
if (exception) {
throw new RuntimeException(String.format("can't parse magic %x in TL_videoSize", constructor));
} else {
return null;
}
}
TL_videoSize result = new TL_videoSize();
result.readParams(stream, exception);
return result;
}
public void readParams(AbstractSerializedData stream, boolean exception) {
type = stream.readString(exception);
location = FileLocation.TLdeserialize(stream, stream.readInt32(exception), exception);
w = stream.readInt32(exception);
h = stream.readInt32(exception);
size = stream.readInt32(exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(type);
location.serializeToStream(stream);
stream.writeInt32(w);
stream.writeInt32(h);
stream.writeInt32(size);
}
}
public static abstract class BotInlineMessage extends TLObject { public static abstract class BotInlineMessage extends TLObject {
public int flags; public int flags;
public GeoPoint geo; public GeoPoint geo;
@ -17805,6 +17773,7 @@ public class TLRPC {
public String mime_type; public String mime_type;
public int size; public int size;
public ArrayList<PhotoSize> thumbs = new ArrayList<>(); public ArrayList<PhotoSize> thumbs = new ArrayList<>();
public ArrayList<TL_videoSize> video_thumbs = new ArrayList<>();
public int version; public int version;
public int dc_id; public int dc_id;
public byte[] key; public byte[] key;
@ -17815,7 +17784,7 @@ public class TLRPC {
Document result = null; Document result = null;
switch (constructor) { switch (constructor) {
case 0x9ba29cc1: case 0x9ba29cc1:
result = new TL_document(); result = new TL_document_layer113();
break; break;
case 0x59534e4c: case 0x59534e4c:
result = new TL_document_layer92(); result = new TL_document_layer92();
@ -17826,6 +17795,9 @@ public class TLRPC {
case 0x55555556: case 0x55555556:
result = new TL_documentEncrypted_old(); result = new TL_documentEncrypted_old();
break; break;
case 0x1e87342b:
result = new TL_document();
break;
case 0x9efc6326: case 0x9efc6326:
result = new TL_document_old(); result = new TL_document_old();
break; break;
@ -17849,7 +17821,7 @@ public class TLRPC {
} }
} }
public static class TL_document_layer92 extends TLRPC.TL_document { public static class TL_document_layer92 extends TL_document {
public static int constructor = 0x59534e4c; public static int constructor = 0x59534e4c;
@ -17982,6 +17954,105 @@ public class TLRPC {
} }
public static class TL_document extends Document { public static class TL_document extends Document {
public static int constructor = 0x1e87342b;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
id = stream.readInt64(exception);
access_hash = stream.readInt64(exception);
file_reference = stream.readByteArray(exception);
date = stream.readInt32(exception);
mime_type = stream.readString(exception);
size = stream.readInt32(exception);
if ((flags & 1) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
PhotoSize object = PhotoSize.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
thumbs.add(object);
}
}
if ((flags & 2) != 0) {
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
TL_videoSize object = TL_videoSize.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
video_thumbs.add(object);
}
}
dc_id = stream.readInt32(exception);
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
DocumentAttribute object = DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
attributes.add(object);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
stream.writeInt64(id);
stream.writeInt64(access_hash);
stream.writeByteArray(file_reference);
stream.writeInt32(date);
stream.writeString(mime_type);
stream.writeInt32(size);
if ((flags & 1) != 0) {
stream.writeInt32(0x1cb5c415);
int count = thumbs.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
thumbs.get(a).serializeToStream(stream);
}
}
if ((flags & 2) != 0) {
stream.writeInt32(0x1cb5c415);
int count = video_thumbs.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
video_thumbs.get(a).serializeToStream(stream);
}
}
stream.writeInt32(dc_id);
stream.writeInt32(0x1cb5c415);
int count = attributes.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
attributes.get(a).serializeToStream(stream);
}
}
}
public static class TL_document_layer113 extends TL_document {
public static int constructor = 0x9ba29cc1; public static int constructor = 0x9ba29cc1;
@ -19527,8 +19598,6 @@ public class TLRPC {
public String vcard; public String vcard;
public int flags; public int flags;
public int ttl_seconds; public int ttl_seconds;
public String url;
public String q;
public InputGeoPoint geo_point; public InputGeoPoint geo_point;
public InputFile file; public InputFile file;
public ArrayList<InputDocument> stickers = new ArrayList<>(); public ArrayList<InputDocument> stickers = new ArrayList<>();
@ -19559,9 +19628,6 @@ public class TLRPC {
case 0xe66fbf7b: case 0xe66fbf7b:
result = new TL_inputMediaDice(); result = new TL_inputMediaDice();
break; break;
case 0x4843b0fd:
result = new TL_inputMediaGifExternal();
break;
case 0xf9c44144: case 0xf9c44144:
result = new TL_inputMediaGeoPoint(); result = new TL_inputMediaGeoPoint();
break; break;
@ -19675,22 +19741,6 @@ public class TLRPC {
} }
} }
public static class TL_inputMediaGifExternal extends InputMedia {
public static int constructor = 0x4843b0fd;
public void readParams(AbstractSerializedData stream, boolean exception) {
url = stream.readString(exception);
q = stream.readString(exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(url);
stream.writeString(q);
}
}
public static class TL_inputMediaGeoPoint extends InputMedia { public static class TL_inputMediaGeoPoint extends InputMedia {
public static int constructor = 0xf9c44144; public static int constructor = 0xf9c44144;
@ -19708,6 +19758,7 @@ public class TLRPC {
public static class TL_inputMediaDocumentExternal extends InputMedia { public static class TL_inputMediaDocumentExternal extends InputMedia {
public static int constructor = 0xfb52dc99; public static int constructor = 0xfb52dc99;
public String url;
public void readParams(AbstractSerializedData stream, boolean exception) { public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception); flags = stream.readInt32(exception);
@ -19984,6 +20035,7 @@ public class TLRPC {
public static class TL_inputMediaPhotoExternal extends InputMedia { public static class TL_inputMediaPhotoExternal extends InputMedia {
public static int constructor = 0xe5bbfe1a; public static int constructor = 0xe5bbfe1a;
public String url;
public void readParams(AbstractSerializedData stream, boolean exception) { public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception); flags = stream.readInt32(exception);
@ -25572,56 +25624,6 @@ public class TLRPC {
} }
} }
public static class TL_messages_foundGifs extends TLObject {
public static int constructor = 0x450a1c0a;
public int next_offset;
public ArrayList<FoundGif> results = new ArrayList<>();
public static TL_messages_foundGifs TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
if (TL_messages_foundGifs.constructor != constructor) {
if (exception) {
throw new RuntimeException(String.format("can't parse magic %x in TL_messages_foundGifs", constructor));
} else {
return null;
}
}
TL_messages_foundGifs result = new TL_messages_foundGifs();
result.readParams(stream, exception);
return result;
}
public void readParams(AbstractSerializedData stream, boolean exception) {
next_offset = stream.readInt32(exception);
int magic = stream.readInt32(exception);
if (magic != 0x1cb5c415) {
if (exception) {
throw new RuntimeException(String.format("wrong Vector magic, got %x", magic));
}
return;
}
int count = stream.readInt32(exception);
for (int a = 0; a < count; a++) {
FoundGif object = FoundGif.TLdeserialize(stream, stream.readInt32(exception), exception);
if (object == null) {
return;
}
results.add(object);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(next_offset);
stream.writeInt32(0x1cb5c415);
int count = results.size();
stream.writeInt32(count);
for (int a = 0; a < count; a++) {
results.get(a).serializeToStream(stream);
}
}
}
public static abstract class Theme extends TLObject { public static abstract class Theme extends TLObject {
public static Theme TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { public static Theme TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
@ -37721,23 +37723,6 @@ public class TLRPC {
} }
} }
public static class TL_messages_searchGifs extends TLObject {
public static int constructor = 0xbf9a776b;
public String q;
public int offset;
public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) {
return TL_messages_foundGifs.TLdeserialize(stream, constructor, exception);
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeString(q);
stream.writeInt32(offset);
}
}
public static class TL_messages_getSavedGifs extends TLObject { public static class TL_messages_getSavedGifs extends TLObject {
public static int constructor = 0x83bf3d52; public static int constructor = 0x83bf3d52;
@ -40850,7 +40835,7 @@ public class TLRPC {
if (object == null) { if (object == null) {
return; return;
} }
TLRPC.TL_pageListItemText item = new TL_pageListItemText(); TL_pageListItemText item = new TL_pageListItemText();
item.text = object; item.text = object;
items.add(item); items.add(item);
} }
@ -40863,7 +40848,7 @@ public class TLRPC {
int count = items.size(); int count = items.size();
stream.writeInt32(count); stream.writeInt32(count);
for (int a = 0; a < count; a++) { for (int a = 0; a < count; a++) {
TLRPC.TL_pageListItemText item = (TLRPC.TL_pageListItemText) items.get(a); TL_pageListItemText item = (TL_pageListItemText) items.get(a);
item.text.serializeToStream(stream); item.text.serializeToStream(stream);
} }
} }
@ -40991,12 +40976,12 @@ public class TLRPC {
result.readParams(stream, exception); result.readParams(stream, exception);
if (result.video_unused != null) { if (result.video_unused != null) {
TL_messageMediaDocument mediaDocument = new TL_messageMediaDocument(); TL_messageMediaDocument mediaDocument = new TL_messageMediaDocument();
if (result.video_unused instanceof TLRPC.TL_videoEncrypted) { if (result.video_unused instanceof TL_videoEncrypted) {
mediaDocument.document = new TLRPC.TL_documentEncrypted(); mediaDocument.document = new TL_documentEncrypted();
mediaDocument.document.key = result.video_unused.key; mediaDocument.document.key = result.video_unused.key;
mediaDocument.document.iv = result.video_unused.iv; mediaDocument.document.iv = result.video_unused.iv;
} else { } else {
mediaDocument.document = new TLRPC.TL_document(); mediaDocument.document = new TL_document();
} }
mediaDocument.flags = 3; mediaDocument.flags = 3;
mediaDocument.document.file_reference = new byte[0]; mediaDocument.document.file_reference = new byte[0];
@ -41012,7 +40997,7 @@ public class TLRPC {
mediaDocument.document.thumbs.add(result.video_unused.thumb); mediaDocument.document.thumbs.add(result.video_unused.thumb);
mediaDocument.document.dc_id = result.video_unused.dc_id; mediaDocument.document.dc_id = result.video_unused.dc_id;
mediaDocument.captionLegacy = result.captionLegacy; mediaDocument.captionLegacy = result.captionLegacy;
TLRPC.TL_documentAttributeVideo attributeVideo = new TLRPC.TL_documentAttributeVideo(); TL_documentAttributeVideo attributeVideo = new TL_documentAttributeVideo();
attributeVideo.w = result.video_unused.w; attributeVideo.w = result.video_unused.w;
attributeVideo.h = result.video_unused.h; attributeVideo.h = result.video_unused.h;
attributeVideo.duration = result.video_unused.duration; attributeVideo.duration = result.video_unused.duration;
@ -41023,12 +41008,12 @@ public class TLRPC {
} }
} else if (result.audio_unused != null) { } else if (result.audio_unused != null) {
TL_messageMediaDocument mediaDocument = new TL_messageMediaDocument(); TL_messageMediaDocument mediaDocument = new TL_messageMediaDocument();
if (result.audio_unused instanceof TLRPC.TL_audioEncrypted) { if (result.audio_unused instanceof TL_audioEncrypted) {
mediaDocument.document = new TLRPC.TL_documentEncrypted(); mediaDocument.document = new TL_documentEncrypted();
mediaDocument.document.key = result.audio_unused.key; mediaDocument.document.key = result.audio_unused.key;
mediaDocument.document.iv = result.audio_unused.iv; mediaDocument.document.iv = result.audio_unused.iv;
} else { } else {
mediaDocument.document = new TLRPC.TL_document(); mediaDocument.document = new TL_document();
} }
mediaDocument.flags = 3; mediaDocument.flags = 3;
mediaDocument.document.file_reference = new byte[0]; mediaDocument.document.file_reference = new byte[0];
@ -41041,12 +41026,12 @@ public class TLRPC {
mediaDocument.document.mime_type = "audio/ogg"; mediaDocument.document.mime_type = "audio/ogg";
} }
mediaDocument.document.size = result.audio_unused.size; mediaDocument.document.size = result.audio_unused.size;
TLRPC.TL_photoSizeEmpty thumb = new TL_photoSizeEmpty(); TL_photoSizeEmpty thumb = new TL_photoSizeEmpty();
thumb.type = "s"; thumb.type = "s";
mediaDocument.document.thumbs.add(thumb); mediaDocument.document.thumbs.add(thumb);
mediaDocument.document.dc_id = result.audio_unused.dc_id; mediaDocument.document.dc_id = result.audio_unused.dc_id;
mediaDocument.captionLegacy = result.captionLegacy; mediaDocument.captionLegacy = result.captionLegacy;
TLRPC.TL_documentAttributeAudio attributeAudio = new TLRPC.TL_documentAttributeAudio(); TL_documentAttributeAudio attributeAudio = new TL_documentAttributeAudio();
attributeAudio.duration = result.audio_unused.duration; attributeAudio.duration = result.audio_unused.duration;
attributeAudio.voice = true; attributeAudio.voice = true;
mediaDocument.document.attributes.add(attributeAudio); mediaDocument.document.attributes.add(attributeAudio);
@ -41107,7 +41092,7 @@ public class TLRPC {
} }
caption = new TL_pageCaption(); caption = new TL_pageCaption();
caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception); caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception);
caption.credit = new TLRPC.TL_textEmpty(); caption.credit = new TL_textEmpty();
} }
public void serializeToStream(AbstractSerializedData stream) { public void serializeToStream(AbstractSerializedData stream) {
@ -41148,7 +41133,7 @@ public class TLRPC {
h = stream.readInt32(exception); h = stream.readInt32(exception);
caption = new TL_pageCaption(); caption = new TL_pageCaption();
caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception); caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception);
caption.credit = new TLRPC.TL_textEmpty(); caption.credit = new TL_textEmpty();
} }
public void serializeToStream(AbstractSerializedData stream) { public void serializeToStream(AbstractSerializedData stream) {
@ -41182,7 +41167,7 @@ public class TLRPC {
video_id = stream.readInt64(exception); video_id = stream.readInt64(exception);
caption = new TL_pageCaption(); caption = new TL_pageCaption();
caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception); caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception);
caption.credit = new TLRPC.TL_textEmpty(); caption.credit = new TL_textEmpty();
} }
public void serializeToStream(AbstractSerializedData stream) { public void serializeToStream(AbstractSerializedData stream) {
@ -41217,7 +41202,7 @@ public class TLRPC {
} }
caption = new TL_pageCaption(); caption = new TL_pageCaption();
caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception); caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception);
caption.credit = new TLRPC.TL_textEmpty(); caption.credit = new TL_textEmpty();
} }
public void serializeToStream(AbstractSerializedData stream) { public void serializeToStream(AbstractSerializedData stream) {
@ -41240,7 +41225,7 @@ public class TLRPC {
photo_id = stream.readInt64(exception); photo_id = stream.readInt64(exception);
caption = new TL_pageCaption(); caption = new TL_pageCaption();
caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception); caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception);
caption.credit = new TLRPC.TL_textEmpty(); caption.credit = new TL_textEmpty();
} }
public void serializeToStream(AbstractSerializedData stream) { public void serializeToStream(AbstractSerializedData stream) {
@ -41272,7 +41257,7 @@ public class TLRPC {
} }
caption = new TL_pageCaption(); caption = new TL_pageCaption();
caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception); caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception);
caption.credit = new TLRPC.TL_textEmpty(); caption.credit = new TL_textEmpty();
} }
public void serializeToStream(AbstractSerializedData stream) { public void serializeToStream(AbstractSerializedData stream) {
@ -41295,7 +41280,7 @@ public class TLRPC {
audio_id = stream.readInt64(exception); audio_id = stream.readInt64(exception);
caption = new TL_pageCaption(); caption = new TL_pageCaption();
caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception); caption.text = RichText.TLdeserialize(stream, stream.readInt32(exception), exception);
caption.credit = new TLRPC.TL_textEmpty(); caption.credit = new TL_textEmpty();
} }
public void serializeToStream(AbstractSerializedData stream) { public void serializeToStream(AbstractSerializedData stream) {
@ -41415,9 +41400,10 @@ public class TLRPC {
public int seq_in; //custom public int seq_in; //custom
public int seq_out; //custom public int seq_out; //custom
public boolean with_my_score; public boolean with_my_score;
public TLRPC.Message replyMessage; //custom public Message replyMessage; //custom
public int reqId; //custom public int reqId; //custom
public int realId; //custom public int realId; //custom
public int stickerVerified = 1; //custom
public static Message TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { public static Message TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
@ -41508,12 +41494,12 @@ public class TLRPC {
public void readAttachPath(AbstractSerializedData stream, int currentUserId) { public void readAttachPath(AbstractSerializedData stream, int currentUserId) {
boolean hasMedia = media != null && !(media instanceof TL_messageMediaEmpty) && !(media instanceof TL_messageMediaWebPage); boolean hasMedia = media != null && !(media instanceof TL_messageMediaEmpty) && !(media instanceof TL_messageMediaWebPage);
boolean fixCaption = !TextUtils.isEmpty(message) && boolean fixCaption = !TextUtils.isEmpty(message) &&
(media instanceof TLRPC.TL_messageMediaPhoto_old || (media instanceof TL_messageMediaPhoto_old ||
media instanceof TLRPC.TL_messageMediaPhoto_layer68 || media instanceof TL_messageMediaPhoto_layer68 ||
media instanceof TLRPC.TL_messageMediaPhoto_layer74 || media instanceof TL_messageMediaPhoto_layer74 ||
media instanceof TLRPC.TL_messageMediaDocument_old || media instanceof TL_messageMediaDocument_old ||
media instanceof TLRPC.TL_messageMediaDocument_layer68 || media instanceof TL_messageMediaDocument_layer68 ||
media instanceof TLRPC.TL_messageMediaDocument_layer74) media instanceof TL_messageMediaDocument_layer74)
&& message.startsWith("-1"); && message.startsWith("-1");
if ((out || to_id != null && to_id.user_id != 0 && to_id.user_id == from_id && from_id == currentUserId) && (id < 0 || hasMedia || send_state == 3) || legacy) { if ((out || to_id != null && to_id.user_id != 0 && to_id.user_id == from_id && from_id == currentUserId) && (id < 0 || hasMedia || send_state == 3) || legacy) {
if (hasMedia && fixCaption) { if (hasMedia && fixCaption) {
@ -41899,10 +41885,10 @@ public class TLRPC {
if ((flags & 4) != 0) { if ((flags & 4) != 0) {
fwd_from = new TL_messageFwdHeader(); fwd_from = new TL_messageFwdHeader();
Peer peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); Peer peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
if (peer instanceof TLRPC.TL_peerChannel) { if (peer instanceof TL_peerChannel) {
fwd_from.channel_id = peer.channel_id; fwd_from.channel_id = peer.channel_id;
fwd_from.flags |= 2; fwd_from.flags |= 2;
} else if (peer instanceof TLRPC.TL_peerUser) { } else if (peer instanceof TL_peerUser) {
fwd_from.from_id = peer.user_id; fwd_from.from_id = peer.user_id;
fwd_from.flags |= 1; fwd_from.flags |= 1;
} }
@ -41963,11 +41949,11 @@ public class TLRPC {
to_id.serializeToStream(stream); to_id.serializeToStream(stream);
if ((flags & 4) != 0) { if ((flags & 4) != 0) {
if (fwd_from.from_id != 0) { if (fwd_from.from_id != 0) {
TLRPC.TL_peerUser peer = new TL_peerUser(); TL_peerUser peer = new TL_peerUser();
peer.user_id = fwd_from.from_id; peer.user_id = fwd_from.from_id;
peer.serializeToStream(stream); peer.serializeToStream(stream);
} else { } else {
TLRPC.TL_peerChannel peer = new TL_peerChannel(); TL_peerChannel peer = new TL_peerChannel();
peer.channel_id = fwd_from.channel_id; peer.channel_id = fwd_from.channel_id;
peer.serializeToStream(stream); peer.serializeToStream(stream);
} }
@ -42026,10 +42012,10 @@ public class TLRPC {
if ((flags & 4) != 0) { if ((flags & 4) != 0) {
fwd_from = new TL_messageFwdHeader(); fwd_from = new TL_messageFwdHeader();
Peer peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); Peer peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception);
if (peer instanceof TLRPC.TL_peerChannel) { if (peer instanceof TL_peerChannel) {
fwd_from.channel_id = peer.channel_id; fwd_from.channel_id = peer.channel_id;
fwd_from.flags |= 2; fwd_from.flags |= 2;
} else if (peer instanceof TLRPC.TL_peerUser) { } else if (peer instanceof TL_peerUser) {
fwd_from.from_id = peer.user_id; fwd_from.from_id = peer.user_id;
fwd_from.flags |= 1; fwd_from.flags |= 1;
} }
@ -42087,11 +42073,11 @@ public class TLRPC {
to_id.serializeToStream(stream); to_id.serializeToStream(stream);
if ((flags & 4) != 0) { if ((flags & 4) != 0) {
if (fwd_from.from_id != 0) { if (fwd_from.from_id != 0) {
TLRPC.TL_peerUser peer = new TL_peerUser(); TL_peerUser peer = new TL_peerUser();
peer.user_id = fwd_from.from_id; peer.user_id = fwd_from.from_id;
peer.serializeToStream(stream); peer.serializeToStream(stream);
} else { } else {
TLRPC.TL_peerChannel peer = new TL_peerChannel(); TL_peerChannel peer = new TL_peerChannel();
peer.channel_id = fwd_from.channel_id; peer.channel_id = fwd_from.channel_id;
peer.serializeToStream(stream); peer.serializeToStream(stream);
} }

View File

@ -233,6 +233,9 @@ public class ActionBarLayout extends FrameLayout {
private DrawerLayoutContainer drawerLayoutContainer; private DrawerLayoutContainer drawerLayoutContainer;
private ActionBar currentActionBar; private ActionBar currentActionBar;
private BaseFragment newFragment;
private BaseFragment oldFragment;
private AnimatorSet currentAnimation; private AnimatorSet currentAnimation;
private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(1.5f); private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(1.5f);
private AccelerateDecelerateInterpolator accelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator(); private AccelerateDecelerateInterpolator accelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
@ -810,13 +813,19 @@ public class ActionBarLayout extends FrameLayout {
if (animationProgress > 1.0f) { if (animationProgress > 1.0f) {
animationProgress = 1.0f; animationProgress = 1.0f;
} }
if (newFragment != null) {
newFragment.onTransitionAnimationProgress(true, animationProgress);
}
if (oldFragment != null) {
oldFragment.onTransitionAnimationProgress(false, animationProgress);
}
float interpolated = decelerateInterpolator.getInterpolation(animationProgress); float interpolated = decelerateInterpolator.getInterpolation(animationProgress);
if (open) { if (open) {
containerView.setAlpha(interpolated); containerView.setAlpha(interpolated);
if (preview) { if (preview) {
containerView.setScaleX(0.9f + 0.1f * interpolated); containerView.setScaleX(0.9f + 0.1f * interpolated);
containerView.setScaleY(0.9f + 0.1f * interpolated); containerView.setScaleY(0.9f + 0.1f * interpolated);
previewBackgroundDrawable.setAlpha((int) (0x80 * interpolated)); previewBackgroundDrawable.setAlpha((int) (0x2e * interpolated));
Theme.moveUpDrawable.setAlpha((int) (255 * interpolated)); Theme.moveUpDrawable.setAlpha((int) (255 * interpolated));
containerView.invalidate(); containerView.invalidate();
invalidate(); invalidate();
@ -828,7 +837,7 @@ public class ActionBarLayout extends FrameLayout {
if (preview) { if (preview) {
containerViewBack.setScaleX(0.9f + 0.1f * (1.0f - interpolated)); containerViewBack.setScaleX(0.9f + 0.1f * (1.0f - interpolated));
containerViewBack.setScaleY(0.9f + 0.1f * (1.0f - interpolated)); containerViewBack.setScaleY(0.9f + 0.1f * (1.0f - interpolated));
previewBackgroundDrawable.setAlpha((int) (0x80 * (1.0f - interpolated))); previewBackgroundDrawable.setAlpha((int) (0x2e * (1.0f - interpolated)));
Theme.moveUpDrawable.setAlpha((int) (255 * (1.0f - interpolated))); Theme.moveUpDrawable.setAlpha((int) (255 * (1.0f - interpolated)));
containerView.invalidate(); containerView.invalidate();
invalidate(); invalidate();
@ -865,7 +874,7 @@ public class ActionBarLayout extends FrameLayout {
fragment.setInPreviewMode(preview); fragment.setInPreviewMode(preview);
if (parentActivity.getCurrentFocus() != null) { if (parentActivity.getCurrentFocus() != null && fragment.hideKeyboardOnShow()) {
AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus()); AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus());
} }
boolean needAnimation = preview || !forceWithoutAnimation && MessagesController.getGlobalMainSettings().getBoolean("view_animations", true); boolean needAnimation = preview || !forceWithoutAnimation && MessagesController.getGlobalMainSettings().getBoolean("view_animations", true);
@ -933,7 +942,7 @@ public class ActionBarLayout extends FrameLayout {
fragmentView.setElevation(AndroidUtilities.dp(4)); fragmentView.setElevation(AndroidUtilities.dp(4));
} }
if (previewBackgroundDrawable == null) { if (previewBackgroundDrawable == null) {
previewBackgroundDrawable = new ColorDrawable(0x80000000); previewBackgroundDrawable = new ColorDrawable(0x2e000000);
} }
previewBackgroundDrawable.setAlpha(0); previewBackgroundDrawable.setAlpha(0);
Theme.moveUpDrawable.setAlpha(0); Theme.moveUpDrawable.setAlpha(0);
@ -1011,6 +1020,8 @@ public class ActionBarLayout extends FrameLayout {
currentFragment.onTransitionAnimationStart(false, false); currentFragment.onTransitionAnimationStart(false, false);
} }
fragment.onTransitionAnimationStart(true, false); fragment.onTransitionAnimationStart(true, false);
oldFragment = currentFragment;
newFragment = fragment;
AnimatorSet animation = null; AnimatorSet animation = null;
if (!preview) { if (!preview) {
animation = fragment.onCustomTransitionAnimation(true, () -> onAnimationEndCheck(false)); animation = fragment.onCustomTransitionAnimation(true, () -> onAnimationEndCheck(false));
@ -1250,6 +1261,8 @@ public class ActionBarLayout extends FrameLayout {
} }
} }
newFragment = previousFragment;
oldFragment = currentFragment;
previousFragment.onTransitionAnimationStart(true, true); previousFragment.onTransitionAnimationStart(true, true);
currentFragment.onTransitionAnimationStart(false, true); currentFragment.onTransitionAnimationStart(false, true);
previousFragment.onResume(); previousFragment.onResume();
@ -1709,8 +1722,12 @@ public class ActionBarLayout extends FrameLayout {
} }
transitionAnimationPreviewMode = false; transitionAnimationPreviewMode = false;
transitionAnimationStartTime = 0; transitionAnimationStartTime = 0;
onCloseAnimationEndRunnable.run(); newFragment = null;
oldFragment = null;
Runnable endRunnable = onCloseAnimationEndRunnable;
onCloseAnimationEndRunnable = null; onCloseAnimationEndRunnable = null;
endRunnable.run();
checkNeedRebuild();
checkNeedRebuild(); checkNeedRebuild();
} }
} }
@ -1734,8 +1751,11 @@ public class ActionBarLayout extends FrameLayout {
} }
transitionAnimationPreviewMode = false; transitionAnimationPreviewMode = false;
transitionAnimationStartTime = 0; transitionAnimationStartTime = 0;
onOpenAnimationEndRunnable.run(); newFragment = null;
oldFragment = null;
Runnable endRunnable = onOpenAnimationEndRunnable;
onOpenAnimationEndRunnable = null; onOpenAnimationEndRunnable = null;
endRunnable.run();
checkNeedRebuild(); checkNeedRebuild();
} }
} }

View File

@ -80,8 +80,9 @@ public class ActionBarMenuItem extends FrameLayout {
} }
} }
public interface ActionBarSumMenuItemDelegate { public interface ActionBarSubMenuItemDelegate {
void onShowSubMenu(); void onShowSubMenu();
void onHideSubMenu();
} }
public interface ActionBarMenuItemDelegate { public interface ActionBarMenuItemDelegate {
@ -106,7 +107,7 @@ public class ActionBarMenuItem extends FrameLayout {
private int subMenuOpenSide; private int subMenuOpenSide;
private int yOffset; private int yOffset;
private ActionBarMenuItemDelegate delegate; private ActionBarMenuItemDelegate delegate;
private ActionBarSumMenuItemDelegate subMenuDelegate; private ActionBarSubMenuItemDelegate subMenuDelegate;
private boolean allowCloseAnimation = true; private boolean allowCloseAnimation = true;
protected boolean overrideMenuClick; protected boolean overrideMenuClick;
private boolean processedPopupClick; private boolean processedPopupClick;
@ -248,8 +249,8 @@ public class ActionBarMenuItem extends FrameLayout {
delegate = actionBarMenuItemDelegate; delegate = actionBarMenuItemDelegate;
} }
public void setSubMenuDelegate(ActionBarSumMenuItemDelegate actionBarSumMenuItemDelegate) { public void setSubMenuDelegate(ActionBarSubMenuItemDelegate actionBarSubMenuItemDelegate) {
subMenuDelegate = actionBarSumMenuItemDelegate; subMenuDelegate = actionBarSubMenuItemDelegate;
} }
public void setIconColor(int color) { public void setIconColor(int color) {
@ -522,7 +523,12 @@ public class ActionBarMenuItem extends FrameLayout {
} }
return false; return false;
}); });
popupWindow.setOnDismissListener(this::onDismiss); popupWindow.setOnDismissListener(() -> {
onDismiss();
if (subMenuDelegate != null) {
subMenuDelegate.onHideSubMenu();
}
});
} }
if (measurePopup) { if (measurePopup) {
popupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - AndroidUtilities.dp(40), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, MeasureSpec.AT_MOST)); popupLayout.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x - AndroidUtilities.dp(40), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, MeasureSpec.AT_MOST));
@ -566,20 +572,23 @@ public class ActionBarMenuItem extends FrameLayout {
} }
} }
if (searchContainer.getVisibility() == VISIBLE) { if (searchContainer.getVisibility() == VISIBLE) {
if (openKeyboard) {
AndroidUtilities.hideKeyboard(searchField);
}
if (clearsTextOnSearchCollapse) {
searchField.setText("");
}
searchContainer.setVisibility(GONE); searchContainer.setVisibility(GONE);
searchField.clearFocus(); searchField.clearFocus();
setVisibility(VISIBLE); setVisibility(VISIBLE);
if (listener != null) { if (listener != null) {
listener.onSearchCollapse(); listener.onSearchCollapse();
} }
if (openKeyboard) {
AndroidUtilities.hideKeyboard(searchField);
}
if (clearsTextOnSearchCollapse) {
searchField.setText("");
}
return false; return false;
} else { } else {
if (listener != null) {
listener.onSearchExpand();
}
searchContainer.setVisibility(VISIBLE); searchContainer.setVisibility(VISIBLE);
setVisibility(GONE); setVisibility(GONE);
searchField.setText(""); searchField.setText("");
@ -587,9 +596,6 @@ public class ActionBarMenuItem extends FrameLayout {
if (openKeyboard) { if (openKeyboard) {
AndroidUtilities.showKeyboard(searchField); AndroidUtilities.showKeyboard(searchField);
} }
if (listener != null) {
listener.onSearchExpand();
}
return true; return true;
} }
} }
@ -598,6 +604,10 @@ public class ActionBarMenuItem extends FrameLayout {
clearsTextOnSearchCollapse = value; clearsTextOnSearchCollapse = value;
} }
public boolean isSubMenuShowing() {
return popupWindow != null && popupWindow.isShowing();
}
public void closeSubMenu() { public void closeSubMenu() {
if (popupWindow != null && popupWindow.isShowing()) { if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss(); popupWindow.dismiss();

View File

@ -232,6 +232,10 @@ public class ActionBarPopupWindow extends PopupWindow {
linearLayout.addView(child); linearLayout.addView(child);
} }
public void addView(View child, LinearLayout.LayoutParams layoutParams) {
linearLayout.addView(child, layoutParams);
}
public void removeInnerViews() { public void removeInnerViews() {
linearLayout.removeAllViews(); linearLayout.removeAllViews();
} }

View File

@ -114,6 +114,10 @@ public class BaseFragment {
} }
} }
protected boolean hideKeyboardOnShow() {
return true;
}
protected void clearViews() { protected void clearViews() {
if (fragmentView != null) { if (fragmentView != null) {
ViewGroup parent = (ViewGroup) fragmentView.getParent(); ViewGroup parent = (ViewGroup) fragmentView.getParent();
@ -375,6 +379,10 @@ public class BaseFragment {
} }
} }
protected void onTransitionAnimationProgress(boolean isOpen, float progress) {
}
protected void onTransitionAnimationStart(boolean isOpen, boolean backward) { protected void onTransitionAnimationStart(boolean isOpen, boolean backward) {
} }

View File

@ -16,6 +16,7 @@ import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Insets;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
@ -24,9 +25,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import androidx.core.view.NestedScrollingParent;
import androidx.core.view.NestedScrollingParentHelper;
import androidx.core.view.ViewCompat;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.Gravity; import android.view.Gravity;
@ -45,9 +43,14 @@ import android.widget.LinearLayout;
import android.widget.ScrollView; import android.widget.ScrollView;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.RequiresApi;
import androidx.core.view.NestedScrollingParent;
import androidx.core.view.NestedScrollingParentHelper;
import androidx.core.view.ViewCompat;
import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
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.UserConfig; import org.telegram.messenger.UserConfig;
@ -90,11 +93,18 @@ public class BottomSheet extends Dialog {
protected boolean isFullscreen; protected boolean isFullscreen;
protected ColorDrawable backDrawable = new ColorDrawable(0xff000000); protected ColorDrawable backDrawable = new ColorDrawable(0xff000000);
protected boolean useLightStatusBar = true;
protected String behindKeyboardColorKey = Theme.key_dialogBackground;
protected int behindKeyboardColor;
private boolean canDismissWithSwipe = true; private boolean canDismissWithSwipe = true;
private boolean allowCustomAnimation = true; private boolean allowCustomAnimation = true;
private boolean showWithoutAnimation; private boolean showWithoutAnimation;
protected boolean calcMandatoryInsets;
private int touchSlop; private int touchSlop;
private boolean useFastDismiss; private boolean useFastDismiss;
protected Interpolator openInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT; protected Interpolator openInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT;
@ -346,6 +356,9 @@ public class BottomSheet extends Dialog {
keyboardVisible = keyboardHeight > AndroidUtilities.dp(20); keyboardVisible = keyboardHeight > AndroidUtilities.dp(20);
if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { if (lastInsets != null && Build.VERSION.SDK_INT >= 21) {
bottomInset = lastInsets.getSystemWindowInsetBottom(); bottomInset = lastInsets.getSystemWindowInsetBottom();
if (Build.VERSION.SDK_INT >= 29) {
bottomInset += getAdditionalMandatoryOffsets();
}
if (keyboardVisible && rect.bottom != 0 && rect.top != 0) { if (keyboardVisible && rect.bottom != 0 && rect.top != 0) {
bottomInset -= keyboardHeight; bottomInset -= keyboardHeight;
} }
@ -355,7 +368,11 @@ public class BottomSheet extends Dialog {
} }
setMeasuredDimension(width, containerHeight); setMeasuredDimension(width, containerHeight);
if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { if (lastInsets != null && Build.VERSION.SDK_INT >= 21) {
height -= lastInsets.getSystemWindowInsetBottom(); int inset = lastInsets.getSystemWindowInsetBottom();
if (Build.VERSION.SDK_INT >= 29) {
inset += getAdditionalMandatoryOffsets();
}
height -= inset;
} }
if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { if (lastInsets != null && Build.VERSION.SDK_INT >= 21) {
width -= lastInsets.getSystemWindowInsetRight() + lastInsets.getSystemWindowInsetLeft(); width -= lastInsets.getSystemWindowInsetRight() + lastInsets.getSystemWindowInsetLeft();
@ -396,6 +413,9 @@ public class BottomSheet extends Dialog {
left += lastInsets.getSystemWindowInsetLeft(); left += lastInsets.getSystemWindowInsetLeft();
right -= lastInsets.getSystemWindowInsetRight(); right -= lastInsets.getSystemWindowInsetRight();
t -= lastInsets.getSystemWindowInsetBottom() - (drawNavigationBar ? 0 : bottomInset); t -= lastInsets.getSystemWindowInsetBottom() - (drawNavigationBar ? 0 : bottomInset);
if (Build.VERSION.SDK_INT >= 29) {
t -= getAdditionalMandatoryOffsets();
}
} }
int l = ((right - left) - containerView.getMeasuredWidth()) / 2; int l = ((right - left) - containerView.getMeasuredWidth()) / 2;
if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { if (lastInsets != null && Build.VERSION.SDK_INT >= 21) {
@ -440,9 +460,6 @@ public class BottomSheet extends Dialog {
} }
switch (verticalGravity) { switch (verticalGravity) {
case Gravity.TOP:
childTop = lp.topMargin;
break;
case Gravity.CENTER_VERTICAL: case Gravity.CENTER_VERTICAL:
childTop = (bottom - top - height) / 2 + lp.topMargin - lp.bottomMargin; childTop = (bottom - top - height) / 2 + lp.topMargin - lp.bottomMargin;
break; break;
@ -495,7 +512,15 @@ public class BottomSheet extends Dialog {
} else { } else {
backgroundPaint.setColor(0xff000000); backgroundPaint.setColor(0xff000000);
} }
canvas.drawRect(containerView.getLeft() + backgroundPaddingLeft, getMeasuredHeight() - bottomInset, containerView.getRight() - backgroundPaddingLeft, getMeasuredHeight(), backgroundPaint); float translation = 0;
if (Build.VERSION.SDK_INT >= 29 && getAdditionalMandatoryOffsets() > 0) {
float dist = containerView.getMeasuredHeight() - containerView.getTranslationY();
if (currentSheetAnimationType == 1) {
dist *= 0.1f;
}
translation = Math.max(0, bottomInset - dist);
}
canvas.drawRect(containerView.getLeft() + backgroundPaddingLeft, getMeasuredHeight() - bottomInset + translation, containerView.getRight() - backgroundPaddingLeft, getMeasuredHeight() + translation, backgroundPaint);
} }
} }
@ -503,16 +528,27 @@ public class BottomSheet extends Dialog {
protected void onDraw(Canvas canvas) { protected void onDraw(Canvas canvas) {
super.onDraw(canvas); super.onDraw(canvas);
if (lastInsets != null && keyboardHeight != 0) { if (lastInsets != null && keyboardHeight != 0) {
backgroundPaint.setColor(Theme.getColor(Theme.key_dialogBackground)); backgroundPaint.setColor(behindKeyboardColorKey != null ? Theme.getColor(behindKeyboardColorKey) : behindKeyboardColor);
canvas.drawRect(containerView.getLeft() + backgroundPaddingLeft, getMeasuredHeight() - keyboardHeight - (drawNavigationBar ? bottomInset : 0), containerView.getRight() - backgroundPaddingLeft, getMeasuredHeight() - (drawNavigationBar ? bottomInset : 0), backgroundPaint); canvas.drawRect(containerView.getLeft() + backgroundPaddingLeft, getMeasuredHeight() - keyboardHeight - (drawNavigationBar ? bottomInset : 0), containerView.getRight() - backgroundPaddingLeft, getMeasuredHeight() - (drawNavigationBar ? bottomInset : 0), backgroundPaint);
} }
onContainerDraw(canvas); onContainerDraw(canvas);
} }
} }
@RequiresApi(api = Build.VERSION_CODES.Q)
private int getAdditionalMandatoryOffsets() {
if (!calcMandatoryInsets) {
return 0;
}
Insets insets = lastInsets.getSystemGestureInsets();
return !keyboardVisible && drawNavigationBar && insets != null && (insets.left != 0 || insets.right != 0) ? insets.bottom : 0;
}
public interface BottomSheetDelegateInterface { public interface BottomSheetDelegateInterface {
void onOpenAnimationStart(); void onOpenAnimationStart();
void onOpenAnimationEnd(); void onOpenAnimationEnd();
boolean canDismiss(); boolean canDismiss();
} }
@ -584,6 +620,9 @@ public class BottomSheet extends Dialog {
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = currentType == 2 ? 80 : 48; int height = currentType == 2 ? 80 : 48;
if (currentType == 0) {
widthMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(height), MeasureSpec.EXACTLY)); super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(height), MeasureSpec.EXACTLY));
} }
@ -596,13 +635,21 @@ public class BottomSheet extends Dialog {
} }
public void setTextAndIcon(CharSequence text, int icon) { public void setTextAndIcon(CharSequence text, int icon) {
setTextAndIcon(text, icon, false); setTextAndIcon(text, icon, null, false);
} }
public void setTextAndIcon(CharSequence text, int icon, boolean bigTitle) { public void setTextAndIcon(CharSequence text, Drawable icon) {
setTextAndIcon(text, 0, icon, false);
}
public void setTextAndIcon(CharSequence text, int icon, Drawable drawable, boolean bigTitle) {
textView.setText(text); textView.setText(text);
if (icon != 0) { if (icon != 0 || drawable != null) {
imageView.setImageResource(icon); if (drawable != null) {
imageView.setImageDrawable(drawable);
} else {
imageView.setImageResource(icon);
}
imageView.setVisibility(VISIBLE); imageView.setVisibility(VISIBLE);
textView.setPadding(0, 0, 0, 0); textView.setPadding(0, 0, 0, 0);
} else { } else {
@ -615,6 +662,9 @@ public class BottomSheet extends Dialog {
return textView; return textView;
} }
public ImageView getImageView() {
return imageView;
}
} }
@Override @Override
@ -682,7 +732,7 @@ public class BottomSheet extends Dialog {
window.setWindowAnimations(R.style.DialogNoAnimation); window.setWindowAnimations(R.style.DialogNoAnimation);
setContentView(container, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); setContentView(container, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
if (Build.VERSION.SDK_INT >= 23) { if (useLightStatusBar && Build.VERSION.SDK_INT >= 23) {
int color = Theme.getColor(Theme.key_actionBarDefault, null, true); int color = Theme.getColor(Theme.key_actionBarDefault, null, true);
if (color == 0xffffffff) { if (color == 0xffffffff) {
int flags = container.getSystemUiVisibility(); int flags = container.getSystemUiVisibility();
@ -703,6 +753,7 @@ public class BottomSheet extends Dialog {
super.setTranslationY(translationY); super.setTranslationY(translationY);
onContainerTranslationYChanged(translationY); onContainerTranslationYChanged(translationY);
} }
{ {
setOrientation(VERTICAL); setOrientation(VERTICAL);
} }
@ -729,7 +780,7 @@ public class BottomSheet extends Dialog {
titleView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2)); titleView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2));
} }
titleView.setGravity(Gravity.CENTER_VERTICAL); titleView.setGravity(Gravity.CENTER_VERTICAL);
containerView.addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT,(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 21, 15, 21, 0)); containerView.addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 21, 15, 21, 0));
titleView.setOnTouchListener((v, event) -> true); titleView.setOnTouchListener((v, event) -> true);
} }
if (customView != null) { if (customView != null) {
@ -743,7 +794,7 @@ public class BottomSheet extends Dialog {
FrameLayout rootView = new ScrollView(getContext()); FrameLayout rootView = new ScrollView(getContext());
LinearLayout rowView = new LinearLayout(getContext()); LinearLayout rowView = new LinearLayout(getContext());
rowView.setOrientation(LinearLayout.VERTICAL); rowView.setOrientation(LinearLayout.VERTICAL);
rootView.addView(rowView,new ScrollView.LayoutParams(-1,-1)); rootView.addView(rowView, new ScrollView.LayoutParams(-1, -1));
containerView.addView(rootView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); containerView.addView(rootView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
for (int a = 0; a < items.length; a++) { for (int a = 0; a < items.length; a++) {
@ -751,8 +802,8 @@ public class BottomSheet extends Dialog {
continue; continue;
} }
BottomSheetCell cell = new BottomSheetCell(getContext(), 0); BottomSheetCell cell = new BottomSheetCell(getContext(), 0);
cell.setTextAndIcon(items[a], itemIcons != null ? itemIcons[a] : 0, bigTitle); cell.setTextAndIcon(items[a], itemIcons != null ? itemIcons[a] : 0, null, bigTitle);
rowView.addView(cell,LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 56, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); rowView.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 56, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0));
cell.setTag(a); cell.setTag(a);
cell.setOnClickListener(v -> dismissWithButtonClick((Integer) v.getTag())); cell.setOnClickListener(v -> dismissWithButtonClick((Integer) v.getTag()));
itemViews.add(cell); itemViews.add(cell);
@ -799,7 +850,7 @@ public class BottomSheet extends Dialog {
WindowManager.LayoutParams params = window.getAttributes(); WindowManager.LayoutParams params = window.getAttributes();
if (focusable) { if (focusable) {
params.softInputMode = (useSmoothKeyboard ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); params.softInputMode = (useSmoothKeyboard ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
params.flags &=~ WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; params.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else { } else {
params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
params.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; params.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;

View File

@ -68,6 +68,7 @@ import org.telegram.messenger.FileLog;
import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.LocaleController; import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R; import org.telegram.messenger.R;
@ -79,6 +80,7 @@ import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Cells.ThemesHorizontalListCell; import org.telegram.ui.Cells.ThemesHorizontalListCell;
import org.telegram.ui.Components.AudioVisualizerDrawable;
import org.telegram.ui.Components.BackgroundGradientDrawable; import org.telegram.ui.Components.BackgroundGradientDrawable;
import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieDrawable;
@ -129,7 +131,7 @@ public class Theme {
private Rect backupRect = new Rect(); private Rect backupRect = new Rect();
private boolean isOut; private final boolean isOut;
private int topY; private int topY;
private boolean isTopNear; private boolean isTopNear;
@ -151,6 +153,8 @@ public class Theme {
public static final int TYPE_MEDIA = 1; public static final int TYPE_MEDIA = 1;
public static final int TYPE_PREVIEW = 2; public static final int TYPE_PREVIEW = 2;
private int alpha;
public MessageDrawable(int type, boolean out, boolean selected) { public MessageDrawable(int type, boolean out, boolean selected) {
super(); super();
isOut = out; isOut = out;
@ -158,6 +162,7 @@ public class Theme {
isSelected = selected; isSelected = selected;
path = new Path(); path = new Path();
selectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); selectedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
alpha = 255;
} }
public boolean hasGradient() { public boolean hasGradient() {
@ -264,7 +269,7 @@ public class Theme {
LinearGradient gradientShader = new LinearGradient(0, 0, 0, dp(40), new int[]{0x155F6569, 0x295F6569}, null, Shader.TileMode.CLAMP); LinearGradient gradientShader = new LinearGradient(0, 0, 0, dp(40), new int[]{0x155F6569, 0x295F6569}, null, Shader.TileMode.CLAMP);
shadowPaint.setShader(gradientShader); shadowPaint.setShader(gradientShader);
shadowPaint.setColorFilter(new PorterDuffColorFilter(shadowColor, PorterDuff.Mode.MULTIPLY)); shadowPaint.setColorFilter(new PorterDuffColorFilter(shadowColor, PorterDuff.Mode.SRC_IN));
shadowPaint.setShadowLayer(2, 0, 1, 0xffffffff); shadowPaint.setShadowLayer(2, 0, 1, 0xffffffff);
if (AndroidUtilities.density > 1) { if (AndroidUtilities.density > 1) {
@ -302,7 +307,7 @@ public class Theme {
color = getColor(isOut ? key_chat_outBubble : key_chat_inBubble); color = getColor(isOut ? key_chat_outBubble : key_chat_inBubble);
} }
if (backgroundDrawable[idx2][idx] != null && (backgroundDrawableColor[idx2][idx] != color || forceSetColor)) { if (backgroundDrawable[idx2][idx] != null && (backgroundDrawableColor[idx2][idx] != color || forceSetColor)) {
backgroundDrawable[idx2][idx].setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); backgroundDrawable[idx2][idx].setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
backgroundDrawableColor[idx2][idx] = color; backgroundDrawableColor[idx2][idx] = color;
} }
return backgroundDrawable[idx2][idx]; return backgroundDrawable[idx2][idx];
@ -359,7 +364,7 @@ public class Theme {
} }
int color = getColor(isOut ? key_chat_outBubbleShadow : key_chat_inBubbleShadow); int color = getColor(isOut ? key_chat_outBubbleShadow : key_chat_inBubbleShadow);
if (shadowDrawable[idx] != null && (shadowDrawableColor[idx] != color || forceSetColor)) { if (shadowDrawable[idx] != null && (shadowDrawableColor[idx] != color || forceSetColor)) {
shadowDrawable[idx].setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); shadowDrawable[idx].setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN));
shadowDrawableColor[idx] = color; shadowDrawableColor[idx] = color;
} }
return shadowDrawable[idx]; return shadowDrawable[idx];
@ -560,13 +565,22 @@ public class Theme {
@Override @Override
public void setAlpha(int alpha) { public void setAlpha(int alpha) {
paint.setAlpha(alpha); if (this.alpha != alpha) {
if (isOut) { this.alpha = alpha;
selectedPaint.setAlpha((int) (Color.alpha(getColor(key_chat_outBubbleGradientSelectedOverlay)) * (alpha / 255.0f))); paint.setAlpha(alpha);
if (isOut) {
selectedPaint.setAlpha((int) (Color.alpha(getColor(key_chat_outBubbleGradientSelectedOverlay)) * (alpha / 255.0f)));
}
} }
if (gradientShader == null) { if (gradientShader == null) {
Drawable background = getBackgroundDrawable(); Drawable background = getBackgroundDrawable();
background.setAlpha(alpha); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
if (background.getAlpha() != alpha) {
background.setAlpha(alpha);
}
} else {
background.setAlpha(alpha);
}
} }
} }
@ -2151,6 +2165,9 @@ public class Theme {
public static Drawable chat_flameIcon; public static Drawable chat_flameIcon;
public static Drawable chat_gifIcon; public static Drawable chat_gifIcon;
private static AudioVisualizerDrawable chat_msgAudioVisualizeDrawable;
private static HashMap<MessageObject, AudioVisualizerDrawable> animatedOutVisualizerDrawables;
public static final String key_dialogBackground = "dialogBackground"; public static final String key_dialogBackground = "dialogBackground";
public static final String key_dialogBackgroundGray = "dialogBackgroundGray"; public static final String key_dialogBackgroundGray = "dialogBackgroundGray";
public static final String key_dialogTextBlack = "dialogTextBlack"; public static final String key_dialogTextBlack = "dialogTextBlack";
@ -7299,6 +7316,9 @@ public class Theme {
color = defaultColors.get(key); color = defaultColors.get(key);
} }
} }
if (color != null && (key_windowBackgroundWhite.equals(key) || key_windowBackgroundGray.equals(key))) {
color |= 0xff000000;
}
return color; return color;
} }
@ -7388,8 +7408,8 @@ public class Theme {
return getDefaultColor(key); return getDefaultColor(key);
} }
} }
if (key.equals(key_windowBackgroundWhite) || key.equals(key_windowBackgroundGray)) { if (key_windowBackgroundWhite.equals(key) || key_windowBackgroundGray.equals(key)) {
return 0xff000000 | color; color |= 0xff000000;
} }
return color; return color;
} }
@ -7933,4 +7953,40 @@ public class Theme {
public static boolean isPatternWallpaper() { public static boolean isPatternWallpaper() {
return isPatternWallpaper; return isPatternWallpaper;
} }
public static AudioVisualizerDrawable getCurrentAudiVisualizerDrawable() {
if (chat_msgAudioVisualizeDrawable == null) {
chat_msgAudioVisualizeDrawable = new AudioVisualizerDrawable();
}
return chat_msgAudioVisualizeDrawable;
}
public static void unrefAudioVisualizeDrawable(MessageObject messageObject) {
if (chat_msgAudioVisualizeDrawable == null) {
return;
}
if (chat_msgAudioVisualizeDrawable.getParentView() == null || messageObject == null) {
chat_msgAudioVisualizeDrawable.setParentView(null);
} else {
if (animatedOutVisualizerDrawables == null) {
animatedOutVisualizerDrawables = new HashMap<>();
}
animatedOutVisualizerDrawables.put(messageObject, chat_msgAudioVisualizeDrawable);
chat_msgAudioVisualizeDrawable.setWaveform(false, true, null);
AndroidUtilities.runOnUIThread(() -> {
AudioVisualizerDrawable drawable = animatedOutVisualizerDrawables.remove(messageObject);
if (drawable != null) {
drawable.setParentView(null);
}
}, 200);
chat_msgAudioVisualizeDrawable = null;
}
}
public static AudioVisualizerDrawable getAnimatedOutAudioVisualizerDrawable(MessageObject messageObject) {
if (animatedOutVisualizerDrawables == null || messageObject == null) {
return null;
}
return animatedOutVisualizerDrawables.get(messageObject);
}
} }

View File

@ -748,7 +748,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl
} else { } else {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX));
builder.setMessage(LocaleController.getString("WalletPermissionNoCamera", R.string.WalletPermissionNoCamera)); builder.setMessage(LocaleController.getString("QRCodePermissionNoCamera", R.string.QRCodePermissionNoCamera));
builder.setNegativeButton(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), (dialog, which) -> { builder.setNegativeButton(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), (dialog, which) -> {
try { try {
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);

View File

@ -697,6 +697,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter {
if (user.username != null && user.username.length() > 0 && (usernameString.length() > 0 && user.username.toLowerCase().startsWith(usernameString) || usernameString.length() == 0)) { if (user.username != null && user.username.length() > 0 && (usernameString.length() > 0 && user.username.toLowerCase().startsWith(usernameString) || usernameString.length() == 0)) {
newResult.add(user); newResult.add(user);
newResultsHashMap.put(user.id, user); newResultsHashMap.put(user.id, user);
newMap.put(user.id, user);
count++; count++;
} }
if (count == 5) { if (count == 5) {
@ -1075,7 +1076,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter {
if (hasTop) { if (hasTop) {
position--; position--;
} }
((ContextLinkCell) holder.itemView).setLink(searchResultBotContext.get(position), contextMedia, position != searchResultBotContext.size() - 1, hasTop && position == 0); ((ContextLinkCell) holder.itemView).setLink(searchResultBotContext.get(position), foundContextBot, contextMedia, position != searchResultBotContext.size() - 1, hasTop && position == 0, "gif".equals(searchingContextUsername));
} }
} else { } else {
if (searchResultUsernames != null) { if (searchResultUsernames != null) {

View File

@ -28,6 +28,7 @@ import org.telegram.messenger.UserConfig;
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.Theme; import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.EmptyCell; import org.telegram.ui.Cells.EmptyCell;
import org.telegram.ui.Cells.FeaturedStickerSetInfoCell; import org.telegram.ui.Cells.FeaturedStickerSetInfoCell;
import org.telegram.ui.Cells.StickerEmojiCell; import org.telegram.ui.Cells.StickerEmojiCell;
@ -86,6 +87,9 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter {
private ArrayList<ArrayList<TLRPC.Document>> emojiArrays = new ArrayList<>(); private ArrayList<ArrayList<TLRPC.Document>> emojiArrays = new ArrayList<>();
private SparseArray<TLRPC.StickerSetCovered> positionsToSets = new SparseArray<>(); private SparseArray<TLRPC.StickerSetCovered> positionsToSets = new SparseArray<>();
private ImageView emptyImageView;
private TextView emptyTextView;
private int reqId; private int reqId;
private int reqId2; private int reqId2;
@ -371,19 +375,19 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter {
layout.setOrientation(LinearLayout.VERTICAL); layout.setOrientation(LinearLayout.VERTICAL);
layout.setGravity(Gravity.CENTER); layout.setGravity(Gravity.CENTER);
ImageView imageView = new ImageView(context); emptyImageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER); emptyImageView.setScaleType(ImageView.ScaleType.CENTER);
imageView.setImageResource(R.drawable.stickers_empty); emptyImageView.setImageResource(R.drawable.stickers_empty);
imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelEmptyText), PorterDuff.Mode.MULTIPLY)); emptyImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_emojiPanelEmptyText), PorterDuff.Mode.SRC_IN));
layout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); layout.addView(emptyImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
layout.addView(new Space(context), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 15)); layout.addView(new Space(context), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 15));
TextView textView = new TextView(context); emptyTextView = new TextView(context);
textView.setText(LocaleController.getString("NoStickersFound", R.string.NoStickersFound)); emptyTextView.setText(LocaleController.getString("NoStickersFound", R.string.NoStickersFound));
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); emptyTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
textView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText)); emptyTextView.setTextColor(Theme.getColor(Theme.key_chat_emojiPanelEmptyText));
layout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); layout.addView(emptyTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
view = layout; view = layout;
view.setMinimumHeight(AndroidUtilities.dp(112)); view.setMinimumHeight(AndroidUtilities.dp(112));
@ -652,4 +656,22 @@ public class StickersSearchAdapter extends RecyclerListView.SelectionAdapter {
public TLRPC.StickerSetCovered getSetForPosition(int position) { public TLRPC.StickerSetCovered getSetForPosition(int position) {
return positionsToSets.get(position); return positionsToSets.get(position);
} }
public void updateColors(RecyclerListView listView) {
for (int i = 0, size = listView.getChildCount(); i < size; i++) {
final View child = listView.getChildAt(i);
if (child instanceof FeaturedStickerSetInfoCell) {
((FeaturedStickerSetInfoCell) child).updateColors();
} else if (child instanceof StickerSetNameCell) {
((StickerSetNameCell) child).updateColors();
}
}
}
public void getThemeDescriptions(List<ThemeDescription> descriptions, RecyclerListView listView, ThemeDescription.ThemeDescriptionDelegate delegate) {
FeaturedStickerSetInfoCell.createThemeDescriptions(descriptions, listView, delegate);
StickerSetNameCell.createThemeDescriptions(descriptions, listView, delegate);
descriptions.add(new ThemeDescription(emptyImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chat_emojiPanelEmptyText));
descriptions.add(new ThemeDescription(emptyTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_emojiPanelEmptyText));
}
} }

View File

@ -323,6 +323,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
TextSelectionHelper.ArticleTextSelectionHelper textSelectionHelper; TextSelectionHelper.ArticleTextSelectionHelper textSelectionHelper;
TextSelectionHelper.ArticleTextSelectionHelper textSelectionHelperBottomSheet; TextSelectionHelper.ArticleTextSelectionHelper textSelectionHelperBottomSheet;
int allowAnimationIndex = -1;
private final String BOTTOM_SHEET_VIEW_TAG = "bottomSheet"; private final String BOTTOM_SHEET_VIEW_TAG = "bottomSheet";
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
@ -741,6 +743,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
} else { } else {
setMeasuredDimension(widthSize, heightSize); setMeasuredDimension(widthSize, heightSize);
} }
menuButton.setAdditionalYOffset(-(currentHeaderHeight - AndroidUtilities.dp(56)) / 2 + (Build.VERSION.SDK_INT < 21 ? AndroidUtilities.statusBarHeight : 0));
keyboardVisible = heightSize < AndroidUtilities.displaySize.y - AndroidUtilities.dp(100); keyboardVisible = heightSize < AndroidUtilities.displaySize.y - AndroidUtilities.dp(100);
containerView.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(heightSize, View.MeasureSpec.EXACTLY)); containerView.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(heightSize, View.MeasureSpec.EXACTLY));
photoContainerView.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(heightSize, View.MeasureSpec.EXACTLY)); photoContainerView.measure(View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(heightSize, View.MeasureSpec.EXACTLY));
@ -3865,6 +3868,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
photoContainerView.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT)); photoContainerView.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT));
groupedPhotosListView = new GroupedPhotosListView(parentActivity); groupedPhotosListView = new GroupedPhotosListView(parentActivity);
groupedPhotosListView.setAnimationsEnabled(false);
photoContainerView.addView(groupedPhotosListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 62, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0)); photoContainerView.addView(groupedPhotosListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 62, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0));
groupedPhotosListView.setDelegate(new GroupedPhotosListView.GroupedPhotosListViewDelegate() { groupedPhotosListView.setDelegate(new GroupedPhotosListView.GroupedPhotosListViewDelegate() {
@Override @Override
@ -4382,7 +4386,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
titleTextView.setTranslationY((maxHeight - currentHeaderHeight) / 2); titleTextView.setTranslationY((maxHeight - currentHeaderHeight) / 2);
headerView.setTranslationY(currentHeaderHeight - maxHeight); headerView.setTranslationY(currentHeaderHeight - maxHeight);
searchShadow.setTranslationY(currentHeaderHeight - maxHeight); searchShadow.setTranslationY(currentHeaderHeight - maxHeight);
menuButton.setAdditionalYOffset(-(currentHeaderHeight - maxHeight) / 2); menuButton.setAdditionalYOffset(-(currentHeaderHeight - maxHeight) / 2 + (Build.VERSION.SDK_INT < 21 ? AndroidUtilities.statusBarHeight : 0));
textSelectionHelper.setTopOffset(currentHeaderHeight); textSelectionHelper.setTopOffset(currentHeaderHeight);
for (int i = 0; i < listView.length; i++) { for (int i = 0; i < listView.length; i++) {
listView[i].setTopGlowOffset(currentHeaderHeight); listView[i].setTopGlowOffset(currentHeaderHeight);
@ -4602,7 +4606,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
NotificationCenter.getInstance(currentAccount).setAnimationInProgress(false); NotificationCenter.getInstance(currentAccount).onAnimationFinish(allowAnimationIndex);
if (animationEndRunnable != null) { if (animationEndRunnable != null) {
animationEndRunnable.run(); animationEndRunnable.run();
animationEndRunnable = null; animationEndRunnable = null;
@ -4612,8 +4616,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
}); });
transitionAnimationStartTime = System.currentTimeMillis(); transitionAnimationStartTime = System.currentTimeMillis();
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
NotificationCenter.getInstance(currentAccount).setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats}); allowAnimationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(allowAnimationIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats});
NotificationCenter.getInstance(currentAccount).setAnimationInProgress(true);
animatorSet.start(); animatorSet.start();
}); });
if (Build.VERSION.SDK_INT >= 18) { if (Build.VERSION.SDK_INT >= 18) {
@ -6450,7 +6453,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
buttonY = (int) (imageView.getImageY() + (imageView.getImageHeight() - size) / 2.0f); buttonY = (int) (imageView.getImageY() + (imageView.getImageHeight() - size) / 2.0f);
radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size);
} }
textY = imageView.getImageY() + imageView.getImageHeight() + AndroidUtilities.dp(8); textY = (int) (imageView.getImageY() + imageView.getImageHeight() + AndroidUtilities.dp(8));
if (currentType == 0) { if (currentType == 0) {
captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, textY, currentBlock, parentAdapter); captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, textY, currentBlock, parentAdapter);
if (captionLayout != null) { if (captionLayout != null) {
@ -10318,7 +10321,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
buttonY = (int) (imageView.getImageY() + (imageView.getImageHeight() - size) / 2.0f); buttonY = (int) (imageView.getImageY() + (imageView.getImageHeight() - size) / 2.0f);
radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size);
} }
textY = imageView.getImageY() + imageView.getImageHeight() + AndroidUtilities.dp(8); textY = (int) (imageView.getImageY() + imageView.getImageHeight() + AndroidUtilities.dp(8));
if (currentType == 0) { if (currentType == 0) {
captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, textY, currentBlock, parentAdapter); captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, textY, currentBlock, parentAdapter);
@ -10370,7 +10373,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
} }
if (!TextUtils.isEmpty(currentBlock.url)) { if (!TextUtils.isEmpty(currentBlock.url)) {
int x = getMeasuredWidth() - AndroidUtilities.dp(11 + 24); int x = getMeasuredWidth() - AndroidUtilities.dp(11 + 24);
int y = imageView.getImageY() + AndroidUtilities.dp(11); int y = (int) (imageView.getImageY() + AndroidUtilities.dp(11));
linkDrawable.setBounds(x, y, x + AndroidUtilities.dp(24), y + AndroidUtilities.dp(24)); linkDrawable.setBounds(x, y, x + AndroidUtilities.dp(24), y + AndroidUtilities.dp(24));
linkDrawable.draw(canvas); linkDrawable.draw(canvas);
} }
@ -10624,7 +10627,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
} else if (currentUrl != null) { } else if (currentUrl != null) {
imageView.setImage(currentUrl, null, null, null, 0); imageView.setImage(currentUrl, null, null, null, 0);
} }
textY = imageView.getImageY() + imageView.getImageHeight() + AndroidUtilities.dp(8); textY = (int) (imageView.getImageY() + imageView.getImageHeight() + AndroidUtilities.dp(8));
if (currentType == 0) { if (currentType == 0) {
captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, textY, currentBlock, parentAdapter); captionLayout = createLayoutForText(this, null, currentBlock.caption.text, textWidth, textY, currentBlock, parentAdapter);
if (captionLayout != null) { if (captionLayout != null) {
@ -10670,8 +10673,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
if (currentMapProvider == 2 && imageView.hasNotThumb()) { if (currentMapProvider == 2 && imageView.hasNotThumb()) {
int w = (int) (Theme.chat_redLocationIcon.getIntrinsicWidth() * 0.8f); int w = (int) (Theme.chat_redLocationIcon.getIntrinsicWidth() * 0.8f);
int h = (int) (Theme.chat_redLocationIcon.getIntrinsicHeight() * 0.8f); int h = (int) (Theme.chat_redLocationIcon.getIntrinsicHeight() * 0.8f);
int x = imageView.getImageX() + (imageView.getImageWidth() - w) / 2; int x = (int) (imageView.getImageX() + (imageView.getImageWidth() - w) / 2);
int y = imageView.getImageY() + (imageView.getImageHeight() / 2 - h); int y = (int) (imageView.getImageY() + (imageView.getImageHeight() / 2 - h));
Theme.chat_redLocationIcon.setAlpha((int) (255 * imageView.getCurrentAlpha())); Theme.chat_redLocationIcon.setAlpha((int) (255 * imageView.getCurrentAlpha()));
Theme.chat_redLocationIcon.setBounds(x, y, x + w, y + h); Theme.chat_redLocationIcon.setBounds(x, y, x + w, y + h);
Theme.chat_redLocationIcon.draw(canvas); Theme.chat_redLocationIcon.draw(canvas);
@ -11497,7 +11500,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
hasViews = true; hasViews = true;
viewsTextView.setVisibility(VISIBLE); viewsTextView.setVisibility(VISIBLE);
textView.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL); textView.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
viewsTextView.setText(LocaleController.formatPluralString("Views", count)); viewsTextView.setText(LocaleController.formatPluralStringComma("Views", count));
} }
int color = Theme.getColor(Theme.key_switchTrack); int color = Theme.getColor(Theme.key_switchTrack);
textView.setTextColor(getGrayTextColor()); textView.setTextColor(getGrayTextColor());
@ -11968,7 +11971,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
} }
@Override @Override
public void onError(Exception e) { public void onError(VideoPlayer player, Exception e) {
FileLog.e(e); FileLog.e(e);
} }
@ -12723,7 +12726,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
NotificationCenter.getInstance(currentAccount).setAnimationInProgress(false); NotificationCenter.getInstance(currentAccount).onAnimationFinish(allowAnimationIndex);
if (photoAnimationEndRunnable != null) { if (photoAnimationEndRunnable != null) {
photoAnimationEndRunnable.run(); photoAnimationEndRunnable.run();
photoAnimationEndRunnable = null; photoAnimationEndRunnable = null;
@ -12733,8 +12736,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
}); });
photoTransitionAnimationStartTime = System.currentTimeMillis(); photoTransitionAnimationStartTime = System.currentTimeMillis();
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
NotificationCenter.getInstance(currentAccount).setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats}); allowAnimationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(allowAnimationIndex, new int[]{NotificationCenter.dialogsNeedReload, NotificationCenter.closeChats});
NotificationCenter.getInstance(currentAccount).setAnimationInProgress(true);
animatorSet.start(); animatorSet.start();
}); });
if (Build.VERSION.SDK_INT >= 18) { if (Build.VERSION.SDK_INT >= 18) {
@ -12791,8 +12793,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg
layoutParams.height = (int) drawRegion.height(); layoutParams.height = (int) drawRegion.height();
animatingImageView.setImageBitmap(object.thumb); animatingImageView.setImageBitmap(object.thumb);
} else { } else {
layoutParams.width = centerImage.getImageWidth(); layoutParams.width = (int) centerImage.getImageWidth();
layoutParams.height = centerImage.getImageHeight(); layoutParams.height = (int) centerImage.getImageHeight();
animatingImageView.setImageBitmap(centerImage.getBitmapSafe()); animatingImageView.setImageBitmap(centerImage.getBitmapSafe());
} }
if (layoutParams.width == 0) { if (layoutParams.width == 0) {

View File

@ -59,7 +59,6 @@ import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.AnimationProperties; 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;
@ -430,7 +429,7 @@ public class CameraScanActivity extends BaseFragment implements Camera.PreviewCa
cameraView.addView(recognizedMrzView); cameraView.addView(recognizedMrzView);
} else { } else {
if (needGalleryButton) { if (needGalleryButton) {
titleTextView.setText(LocaleController.getString("WalletScanCode", R.string.WalletScanCode)); //titleTextView.setText(LocaleController.getString("WalletScanCode", R.string.WalletScanCode));
} else { } else {
titleTextView.setText(LocaleController.getString("AuthAnotherClientScan", R.string.AuthAnotherClientScan)); titleTextView.setText(LocaleController.getString("AuthAnotherClientScan", R.string.AuthAnotherClientScan));
} }
@ -438,7 +437,7 @@ public class CameraScanActivity extends BaseFragment implements Camera.PreviewCa
recognizedMrzView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); recognizedMrzView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
recognizedMrzView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), AndroidUtilities.dp(10)); recognizedMrzView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), AndroidUtilities.dp(10));
if (needGalleryButton) { if (needGalleryButton) {
recognizedMrzView.setText(LocaleController.getString("WalletScanCodeNotFound", R.string.WalletScanCodeNotFound)); //recognizedMrzView.setText(LocaleController.getString("WalletScanCodeNotFound", R.string.WalletScanCodeNotFound));
} else { } else {
recognizedMrzView.setText(LocaleController.getString("AuthAnotherClientNotFound", R.string.AuthAnotherClientNotFound)); recognizedMrzView.setText(LocaleController.getString("AuthAnotherClientNotFound", R.string.AuthAnotherClientNotFound));
} }
@ -596,20 +595,8 @@ public class CameraScanActivity extends BaseFragment implements Camera.PreviewCa
}); });
} }
private void showErrorAlert() { private void onNoQrFound() {
if (any) {
AlertsCreator.createSimpleAlert(getParentActivity(), LocaleController.getString("WalletQRCode", R.string.WalletQRCode), LocaleController.getString("NoQrFound", R.string.NoQrFound)).show();
} else {
AlertsCreator.createSimpleAlert(getParentActivity(), LocaleController.getString("WalletQRCode", R.string.WalletQRCode), LocaleController.getString("WalletScanImageNotFound", R.string.WalletScanImageNotFound)).show();
}
}
private void onNoQrFound(boolean alert) {
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
if (alert) {
showErrorAlert();
return;
}
if (recognizedMrzView.getTag() != null) { if (recognizedMrzView.getTag() != null) {
recognizedMrzView.setTag(null); recognizedMrzView.setTag(null);
recognizedMrzView.animate().setDuration(200).alpha(0.0f).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); recognizedMrzView.animate().setDuration(200).alpha(0.0f).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
@ -617,19 +604,6 @@ public class CameraScanActivity extends BaseFragment implements Camera.PreviewCa
}); });
} }
private void onNoWalletFound(boolean alert) {
AndroidUtilities.runOnUIThread(() -> {
if (alert) {
showErrorAlert();
return;
}
if (recognizedMrzView.getTag() == null) {
recognizedMrzView.setTag(1);
recognizedMrzView.animate().setDuration(200).alpha(1.0f).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
}
});
}
@Override @Override
public void onPreviewFrame(final byte[] data, final Camera camera) { public void onPreviewFrame(final byte[] data, final Camera camera) {
handler.post(() -> { handler.post(() -> {
@ -668,7 +642,7 @@ public class CameraScanActivity extends BaseFragment implements Camera.PreviewCa
} }
} }
} catch (Throwable ignore) { } catch (Throwable ignore) {
onNoQrFound(false); onNoQrFound();
} }
}); });
} }
@ -701,32 +675,32 @@ public class CameraScanActivity extends BaseFragment implements Camera.PreviewCa
Result result = qrReader.decode(new BinaryBitmap(new GlobalHistogramBinarizer(source))); Result result = qrReader.decode(new BinaryBitmap(new GlobalHistogramBinarizer(source)));
if (result == null) { if (result == null) {
onNoQrFound(bitmap != null); onNoQrFound();
return null; return null;
} }
text = result.getText(); text = result.getText();
//} //}
if (TextUtils.isEmpty(text)) { if (TextUtils.isEmpty(text)) {
onNoQrFound(bitmap != null); onNoQrFound();
return null; return null;
} }
if (any) return text; if (any) return text;
if (needGalleryButton) { if (needGalleryButton) {
if (!text.startsWith("ton://transfer/")) { if (!text.startsWith("ton://transfer/")) {
onNoWalletFound(bitmap != null); //onNoWalletFound(bitmap != null);
return null; return null;
} }
Uri uri = Uri.parse(text); Uri uri = Uri.parse(text);
String path = uri.getPath().replace("/", ""); String path = uri.getPath().replace("/", "");
} else { } else {
if (!text.startsWith("tg://login?token=")) { if (!text.startsWith("tg://login?token=")) {
onNoWalletFound(false); onNoQrFound();
return null; return null;
} }
} }
return text; return text;
} catch (Throwable ignore) { } catch (Throwable ignore) {
onNoQrFound(bitmap != null); onNoQrFound();
} }
return null; return null;
} }

View File

@ -31,6 +31,8 @@ import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController; import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessageObject;
import org.telegram.messenger.browser.Browser; import org.telegram.messenger.browser.Browser;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.LinkPath;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
@ -49,9 +51,13 @@ public class AboutLinkCell extends FrameLayout {
private ClickableSpan pressedLink; private ClickableSpan pressedLink;
private LinkPath urlPath = new LinkPath(); private LinkPath urlPath = new LinkPath();
public AboutLinkCell(Context context) { private BaseFragment parentFragment;
public AboutLinkCell(Context context, BaseFragment fragment) {
super(context); super(context);
parentFragment = fragment;
valueTextView = new TextView(context); valueTextView = new TextView(context);
valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2));
valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
@ -148,7 +154,12 @@ public class AboutLinkCell extends FrameLayout {
} }
} else { } else {
if (pressedLink instanceof URLSpan) { if (pressedLink instanceof URLSpan) {
Browser.openUrl(getContext(), ((URLSpan) pressedLink).getURL()); String url = ((URLSpan) pressedLink).getURL();
if (AndroidUtilities.shouldShowUrlInAlert(url)) {
AlertsCreator.showOpenUrlAlert(parentFragment, url, true, true);
} else {
Browser.openUrl(getContext(), url);
}
} else { } else {
pressedLink.onClick(this); pressedLink.onClick(this);
} }

View File

@ -28,7 +28,6 @@ import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessageObject;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.messenger.browser.Browser;
import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.LinkPath;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.TypefaceSpan;
@ -43,12 +42,15 @@ public class BotHelpCell extends View {
private int height; private int height;
private int textX; private int textX;
private int textY; private int textY;
public boolean wasDraw;
private ClickableSpan pressedLink; private ClickableSpan pressedLink;
private LinkPath urlPath = new LinkPath(); private LinkPath urlPath = new LinkPath();
private BotHelpCellDelegate delegate; private BotHelpCellDelegate delegate;
private boolean animating;
public interface BotHelpCellDelegate { public interface BotHelpCellDelegate {
void didPressUrl(String url); void didPressUrl(String url);
} }
@ -167,7 +169,9 @@ public class BotHelpCell extends View {
} }
} else { } else {
if (pressedLink instanceof URLSpan) { if (pressedLink instanceof URLSpan) {
Browser.openUrl(getContext(), ((URLSpan) pressedLink).getURL()); if (delegate != null) {
delegate.didPressUrl(((URLSpan) pressedLink).getURL());
}
} else { } else {
pressedLink.onClick(this); pressedLink.onClick(this);
} }
@ -218,6 +222,14 @@ public class BotHelpCell extends View {
textLayout.draw(canvas); textLayout.draw(canvas);
} }
canvas.restore(); canvas.restore();
wasDraw = true;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
wasDraw = false;
} }
@Override @Override
@ -225,4 +237,12 @@ public class BotHelpCell extends View {
super.onInitializeAccessibilityNodeInfo(info); super.onInitializeAccessibilityNodeInfo(info);
info.setText(textLayout.getText()); info.setText(textLayout.getText());
} }
public boolean animating() {
return animating;
}
public void setAnimating(boolean animating) {
this.animating = animating;
}
} }

View File

@ -87,6 +87,8 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
private boolean canPreviewGif; private boolean canPreviewGif;
private boolean isForceGif;
private int linkY; private int linkY;
private StaticLayout linkLayout; private StaticLayout linkLayout;
@ -97,6 +99,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
private StaticLayout descriptionLayout; private StaticLayout descriptionLayout;
private TLRPC.BotInlineResult inlineResult; private TLRPC.BotInlineResult inlineResult;
private TLRPC.User inlineBot;
private TLRPC.Document documentAttach; private TLRPC.Document documentAttach;
private int currentDate; private int currentDate;
private TLRPC.Photo photoAttach; private TLRPC.Photo photoAttach;
@ -118,6 +121,8 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
private float scale; private float scale;
private static AccelerateInterpolator interpolator = new AccelerateInterpolator(0.5f); private static AccelerateInterpolator interpolator = new AccelerateInterpolator(0.5f);
private boolean hideLoadProgress;
private CheckBox2 checkBox; private CheckBox2 checkBox;
private ContextLinkCellDelegate delegate; private ContextLinkCellDelegate delegate;
@ -217,7 +222,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
String ext = null; String ext = null;
if (documentAttach != null) { if (documentAttach != null) {
if (MessageObject.isGifDocument(documentAttach)) { if (isForceGif || MessageObject.isGifDocument(documentAttach)) {
currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(documentAttach.thumbs, 90); currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(documentAttach.thumbs, 90);
} else if (MessageObject.isStickerDocument(documentAttach) || MessageObject.isAnimatedStickerDocument(documentAttach, true)) { } else if (MessageObject.isStickerDocument(documentAttach) || MessageObject.isAnimatedStickerDocument(documentAttach, true)) {
currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(documentAttach.thumbs, 90); currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(documentAttach.thumbs, 90);
@ -238,7 +243,11 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
if (inlineResult.content instanceof TLRPC.TL_webDocument) { if (inlineResult.content instanceof TLRPC.TL_webDocument) {
if (inlineResult.type != null) { if (inlineResult.type != null) {
if (inlineResult.type.startsWith("gif")) { if (inlineResult.type.startsWith("gif")) {
webDocument = (TLRPC.TL_webDocument) inlineResult.content; if (inlineResult.thumb instanceof TLRPC.TL_webDocument && "video/mp4".equals(inlineResult.thumb.mime_type)) {
webDocument = (TLRPC.TL_webDocument) inlineResult.thumb;
} else {
webDocument = (TLRPC.TL_webDocument) inlineResult.content;
}
documentAttachType = DOCUMENT_ATTACH_TYPE_GIF; documentAttachType = DOCUMENT_ATTACH_TYPE_GIF;
} else if (inlineResult.type.equals("photo")) { } else if (inlineResult.type.equals("photo")) {
if (inlineResult.thumb instanceof TLRPC.TL_webDocument) { if (inlineResult.thumb instanceof TLRPC.TL_webDocument) {
@ -317,7 +326,16 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) {
if (documentAttach != null) { if (documentAttach != null) {
linkImageView.setImage(ImageLocation.getForDocument(documentAttach), null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, documentAttach.size, ext, parentObject, 0); TLRPC.TL_videoSize thumb = MessageObject.getDocumentVideoThumb(documentAttach);
if (thumb != null) {
linkImageView.setImage(ImageLocation.getForDocument(thumb, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, -1, ext, parentObject, 1);
} else {
ImageLocation location = ImageLocation.getForDocument(documentAttach);
if (isForceGif) {
location.imageType = FileLoader.IMAGE_TYPE_ANIMATION;
}
linkImageView.setImage(location, null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), currentPhotoFilter, documentAttach.size, ext, parentObject, 0);
}
} else if (webFile != null) { } else if (webFile != null) {
linkImageView.setImage(ImageLocation.getForWebFile(webFile), null, ImageLocation.getForPhoto(currentPhotoObject, photoAttach), currentPhotoFilter, -1, ext, parentObject, 1); linkImageView.setImage(ImageLocation.getForWebFile(webFile), null, ImageLocation.getForPhoto(currentPhotoObject, photoAttach), currentPhotoFilter, -1, ext, parentObject, 1);
} else { } else {
@ -452,9 +470,14 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
} }
} }
public void setLink(TLRPC.BotInlineResult contextResult, boolean media, boolean divider, boolean shadow) { public void setLink(TLRPC.BotInlineResult contextResult, TLRPC.User bot, boolean media, boolean divider, boolean shadow) {
setLink(contextResult, bot, media, divider, shadow, false);
}
public void setLink(TLRPC.BotInlineResult contextResult, TLRPC.User bot, boolean media, boolean divider, boolean shadow, boolean forceGif) {
needDivider = divider; needDivider = divider;
needShadow = shadow; needShadow = shadow;
inlineBot = bot;
parentObject = inlineResult = contextResult; parentObject = inlineResult = contextResult;
if (inlineResult != null) { if (inlineResult != null) {
documentAttach = inlineResult.document; documentAttach = inlineResult.document;
@ -464,11 +487,19 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
photoAttach = null; photoAttach = null;
} }
mediaWebpage = media; mediaWebpage = media;
isForceGif = forceGif;
setAttachType(); setAttachType();
if (forceGif) {
documentAttachType = DOCUMENT_ATTACH_TYPE_GIF;
}
requestLayout(); requestLayout();
updateButtonState(false, false); updateButtonState(false, false);
} }
public TLRPC.User getInlineBot() {
return inlineBot;
}
public Object getParentObject() { public Object getParentObject() {
return parentObject; return parentObject;
} }
@ -486,7 +517,9 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
documentAttach = document; documentAttach = document;
photoAttach = null; photoAttach = null;
mediaWebpage = true; mediaWebpage = true;
isForceGif = true;
setAttachType(); setAttachType();
documentAttachType = DOCUMENT_ATTACH_TYPE_GIF;
requestLayout(); requestLayout();
updateButtonState(false, false); updateButtonState(false, false);
} }
@ -705,24 +738,24 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
} else if (inlineResult != null && inlineResult.type.equals("file")) { } else if (inlineResult != null && inlineResult.type.equals("file")) {
int w = Theme.chat_inlineResultFile.getIntrinsicWidth(); int w = Theme.chat_inlineResultFile.getIntrinsicWidth();
int h = Theme.chat_inlineResultFile.getIntrinsicHeight(); int h = Theme.chat_inlineResultFile.getIntrinsicHeight();
int x = linkImageView.getImageX() + (AndroidUtilities.dp(52) - w) / 2; int x = (int) (linkImageView.getImageX() + (AndroidUtilities.dp(52) - w) / 2);
int y = linkImageView.getImageY() + (AndroidUtilities.dp(52) - h) / 2; int y = (int) (linkImageView.getImageY() + (AndroidUtilities.dp(52) - h) / 2);
canvas.drawRect(linkImageView.getImageX(), linkImageView.getImageY(), linkImageView.getImageX() + AndroidUtilities.dp(52), linkImageView.getImageY() + AndroidUtilities.dp(52), LetterDrawable.paint); canvas.drawRect(linkImageView.getImageX(), linkImageView.getImageY(), linkImageView.getImageX() + AndroidUtilities.dp(52), linkImageView.getImageY() + AndroidUtilities.dp(52), LetterDrawable.paint);
Theme.chat_inlineResultFile.setBounds(x, y, x + w, y + h); Theme.chat_inlineResultFile.setBounds(x, y, x + w, y + h);
Theme.chat_inlineResultFile.draw(canvas); Theme.chat_inlineResultFile.draw(canvas);
} else if (inlineResult != null && (inlineResult.type.equals("audio") || inlineResult.type.equals("voice"))) { } else if (inlineResult != null && (inlineResult.type.equals("audio") || inlineResult.type.equals("voice"))) {
int w = Theme.chat_inlineResultAudio.getIntrinsicWidth(); int w = Theme.chat_inlineResultAudio.getIntrinsicWidth();
int h = Theme.chat_inlineResultAudio.getIntrinsicHeight(); int h = Theme.chat_inlineResultAudio.getIntrinsicHeight();
int x = linkImageView.getImageX() + (AndroidUtilities.dp(52) - w) / 2; int x = (int) (linkImageView.getImageX() + (AndroidUtilities.dp(52) - w) / 2);
int y = linkImageView.getImageY() + (AndroidUtilities.dp(52) - h) / 2; int y = (int) (linkImageView.getImageY() + (AndroidUtilities.dp(52) - h) / 2);
canvas.drawRect(linkImageView.getImageX(), linkImageView.getImageY(), linkImageView.getImageX() + AndroidUtilities.dp(52), linkImageView.getImageY() + AndroidUtilities.dp(52), LetterDrawable.paint); canvas.drawRect(linkImageView.getImageX(), linkImageView.getImageY(), linkImageView.getImageX() + AndroidUtilities.dp(52), linkImageView.getImageY() + AndroidUtilities.dp(52), LetterDrawable.paint);
Theme.chat_inlineResultAudio.setBounds(x, y, x + w, y + h); Theme.chat_inlineResultAudio.setBounds(x, y, x + w, y + h);
Theme.chat_inlineResultAudio.draw(canvas); Theme.chat_inlineResultAudio.draw(canvas);
} else if (inlineResult != null && (inlineResult.type.equals("venue") || inlineResult.type.equals("geo"))) { } else if (inlineResult != null && (inlineResult.type.equals("venue") || inlineResult.type.equals("geo"))) {
int w = Theme.chat_inlineResultLocation.getIntrinsicWidth(); int w = Theme.chat_inlineResultLocation.getIntrinsicWidth();
int h = Theme.chat_inlineResultLocation.getIntrinsicHeight(); int h = Theme.chat_inlineResultLocation.getIntrinsicHeight();
int x = linkImageView.getImageX() + (AndroidUtilities.dp(52) - w) / 2; int x = (int) (linkImageView.getImageX() + (AndroidUtilities.dp(52) - w) / 2);
int y = linkImageView.getImageY() + (AndroidUtilities.dp(52) - h) / 2; int y = (int) (linkImageView.getImageY() + (AndroidUtilities.dp(52) - h) / 2);
canvas.drawRect(linkImageView.getImageX(), linkImageView.getImageY(), linkImageView.getImageX() + AndroidUtilities.dp(52), linkImageView.getImageY() + AndroidUtilities.dp(52), LetterDrawable.paint); canvas.drawRect(linkImageView.getImageX(), linkImageView.getImageY(), linkImageView.getImageX() + AndroidUtilities.dp(52), linkImageView.getImageY() + AndroidUtilities.dp(52), LetterDrawable.paint);
Theme.chat_inlineResultLocation.setBounds(x, y, x + w, y + h); Theme.chat_inlineResultLocation.setBounds(x, y, x + w, y + h);
Theme.chat_inlineResultLocation.draw(canvas); Theme.chat_inlineResultLocation.draw(canvas);
@ -733,8 +766,8 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
if (inlineResult != null && (inlineResult.send_message instanceof TLRPC.TL_botInlineMessageMediaGeo || inlineResult.send_message instanceof TLRPC.TL_botInlineMessageMediaVenue)) { if (inlineResult != null && (inlineResult.send_message instanceof TLRPC.TL_botInlineMessageMediaGeo || inlineResult.send_message instanceof TLRPC.TL_botInlineMessageMediaVenue)) {
int w = Theme.chat_inlineResultLocation.getIntrinsicWidth(); int w = Theme.chat_inlineResultLocation.getIntrinsicWidth();
int h = Theme.chat_inlineResultLocation.getIntrinsicHeight(); int h = Theme.chat_inlineResultLocation.getIntrinsicHeight();
int x = linkImageView.getImageX() + (linkImageView.getImageWidth() - w) / 2; int x = (int) (linkImageView.getImageX() + (linkImageView.getImageWidth() - w) / 2);
int y = linkImageView.getImageY() + (linkImageView.getImageHeight() - h) / 2; int y = (int) (linkImageView.getImageY() + (linkImageView.getImageHeight() - h) / 2);
canvas.drawRect(linkImageView.getImageX(), linkImageView.getImageY(), linkImageView.getImageX() + linkImageView.getImageWidth(), linkImageView.getImageY() + linkImageView.getImageHeight(), LetterDrawable.paint); canvas.drawRect(linkImageView.getImageX(), linkImageView.getImageY(), linkImageView.getImageX() + linkImageView.getImageWidth(), linkImageView.getImageY() + linkImageView.getImageHeight(), LetterDrawable.paint);
Theme.chat_inlineResultLocation.setBounds(x, y, x + w, y + h); Theme.chat_inlineResultLocation.setBounds(x, y, x + w, y + h);
Theme.chat_inlineResultLocation.draw(canvas); Theme.chat_inlineResultLocation.draw(canvas);
@ -820,19 +853,28 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F
fileName = FileLoader.getAttachFileName(currentPhotoObject); fileName = FileLoader.getAttachFileName(currentPhotoObject);
cacheFile = FileLoader.getPathToAttach(currentPhotoObject); cacheFile = FileLoader.getPathToAttach(currentPhotoObject);
} else if (inlineResult.content instanceof TLRPC.TL_webDocument) { } else if (inlineResult.content instanceof TLRPC.TL_webDocument) {
fileName = Utilities.MD5(inlineResult.content.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.content.url, "jpg"); fileName = Utilities.MD5(inlineResult.content.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.content.url, FileLoader.getMimeTypePart(inlineResult.content.mime_type));
cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && inlineResult.thumb instanceof TLRPC.TL_webDocument && "video/mp4".equals(inlineResult.thumb.mime_type)) {
fileName = null;
}
} else if (inlineResult.thumb instanceof TLRPC.TL_webDocument) { } else if (inlineResult.thumb instanceof TLRPC.TL_webDocument) {
fileName = Utilities.MD5(inlineResult.thumb.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.thumb.url, "jpg"); fileName = Utilities.MD5(inlineResult.thumb.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.thumb.url, FileLoader.getMimeTypePart(inlineResult.thumb.mime_type));
cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
} }
} else if (documentAttach != null) { } else if (documentAttach != null) {
fileName = FileLoader.getAttachFileName(documentAttach); fileName = FileLoader.getAttachFileName(documentAttach);
cacheFile = FileLoader.getPathToAttach(documentAttach); cacheFile = FileLoader.getPathToAttach(documentAttach);
} }
if (documentAttach != null && documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.getDocumentVideoThumb(documentAttach) != null) {
fileName = null;
}
} }
if (TextUtils.isEmpty(fileName)) { if (TextUtils.isEmpty(fileName)) {
buttonState = -1;
radialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, false);
return; return;
} }
if (!cacheFile.exists()) { if (!cacheFile.exists()) {

View File

@ -2070,12 +2070,12 @@ public class DialogCell extends BaseCell {
if (user != null && isDialogCell && currentDialogFolderId == 0 && !MessagesController.isSupportUser(user) && !user.bot) { if (user != null && isDialogCell && currentDialogFolderId == 0 && !MessagesController.isSupportUser(user) && !user.bot) {
boolean isOnline = !user.self && (user.status != null && user.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(user.id)); boolean isOnline = !user.self && (user.status != null && user.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime() || MessagesController.getInstance(currentAccount).onlinePrivacy.containsKey(user.id));
if (isOnline || onlineProgress != 0) { if (isOnline || onlineProgress != 0) {
int top = avatarImage.getImageY2() - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8); int top = (int) (avatarImage.getImageY2() - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8));
int left; int left;
if (LocaleController.isRTL) { if (LocaleController.isRTL) {
left = avatarImage.getImageX() + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6); left = (int) (avatarImage.getImageX() + AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
} else { } else {
left = avatarImage.getImageX2() - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6); left = (int) (avatarImage.getImageX2() - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 6));
} }
Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite));

View File

@ -54,7 +54,7 @@ public class DrawerAddCell extends FrameLayout {
textView.setText(LocaleController.getString("AddAccount", R.string.AddAccount)); textView.setText(LocaleController.getString("AddAccount", R.string.AddAccount));
Drawable drawable = getResources().getDrawable(R.drawable.account_add); Drawable drawable = getResources().getDrawable(R.drawable.account_add);
if (drawable != null) { if (drawable != null) {
drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_menuItemIcon), PorterDuff.Mode.MULTIPLY)); drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_menuItemIcon), PorterDuff.Mode.SRC_IN));
} }
textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
} }

View File

@ -37,9 +37,14 @@ import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLObject; 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.ActionBar.ThemeDescription;
import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.ProgressButton; import org.telegram.ui.Components.ProgressButton;
import org.telegram.ui.Components.RecyclerListView;
import java.util.ArrayList;
import java.util.List;
public class FeaturedStickerSetCell2 extends FrameLayout { public class FeaturedStickerSetCell2 extends FrameLayout {
@ -87,8 +92,6 @@ public class FeaturedStickerSetCell2 extends FrameLayout {
addButton = new ProgressButton(context); addButton = new ProgressButton(context);
addButton.setText(LocaleController.getString("Add", R.string.Add)); addButton.setText(LocaleController.getString("Add", R.string.Add));
addButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); addButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
addButton.setProgressColor(Theme.getColor(Theme.key_featuredStickers_buttonProgress));
addButton.setBackgroundRoundRect(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed));
addView(addButton, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 18, 14, 0)); addView(addButton, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 18, 14, 0));
delButton = new TextView(context); delButton = new TextView(context);
@ -98,6 +101,8 @@ public class FeaturedStickerSetCell2 extends FrameLayout {
delButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); delButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
delButton.setText(LocaleController.getString("StickersRemove", R.string.StickersRemove)); delButton.setText(LocaleController.getString("StickersRemove", R.string.StickersRemove));
addView(delButton, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 16, 14, 0)); addView(delButton, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 16, 14, 0));
updateColors();
} }
@Override @Override
@ -294,4 +299,19 @@ public class FeaturedStickerSetCell2 extends FrameLayout {
public BackupImageView getImageView() { public BackupImageView getImageView() {
return imageView; return imageView;
} }
public void updateColors() {
addButton.setProgressColor(Theme.getColor(Theme.key_featuredStickers_buttonProgress));
addButton.setBackgroundRoundRect(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed));
}
public static void createThemeDescriptions(List<ThemeDescription> descriptions, RecyclerListView listView, ThemeDescription.ThemeDescriptionDelegate delegate) {
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{FeaturedStickerSetCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{FeaturedStickerSetCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{FeaturedStickerSetCell.class}, new String[]{"addButton"}, null, null, null, Theme.key_featuredStickers_buttonText));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{FeaturedStickerSetCell.class}, new String[]{"delButton"}, null, null, null, Theme.key_featuredStickers_removeButtonText));
descriptions.add(new ThemeDescription(listView, 0, new Class[]{FeaturedStickerSetCell.class}, Theme.dividerPaint, null, null, Theme.key_divider));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_featuredStickers_buttonProgress));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_featuredStickers_addButtonPressed));
}
} }

View File

@ -33,12 +33,18 @@ import org.telegram.messenger.R;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Components.ColorSpanUnderline; import org.telegram.ui.Components.ColorSpanUnderline;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.ProgressButton; import org.telegram.ui.Components.ProgressButton;
import org.telegram.ui.Components.RecyclerListView;
import java.util.List;
public class FeaturedStickerSetInfoCell extends FrameLayout { public class FeaturedStickerSetInfoCell extends FrameLayout {
private boolean canAddRemove;
private TextView nameTextView; private TextView nameTextView;
private TextView infoTextView; private TextView infoTextView;
private ProgressButton addButton; private ProgressButton addButton;
@ -55,12 +61,23 @@ public class FeaturedStickerSetInfoCell extends FrameLayout {
private int currentAccount = UserConfig.selectedAccount; private int currentAccount = UserConfig.selectedAccount;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private int stickerSetNameSearchIndex;
private int stickerSetNameSearchLength;
private CharSequence url;
private int urlSearchLength;
public FeaturedStickerSetInfoCell(Context context, int left) { public FeaturedStickerSetInfoCell(Context context, int left) {
this(context, left, false); this(context, left, false);
} }
public FeaturedStickerSetInfoCell(Context context, int left, boolean supportRtl) { public FeaturedStickerSetInfoCell(Context context, int left, boolean supportRtl) {
this(context, left, supportRtl, true);
}
public FeaturedStickerSetInfoCell(Context context, int left, boolean supportRtl, boolean canAddRemove) {
super(context); super(context);
this.canAddRemove = canAddRemove;
FrameLayout.LayoutParams lp; FrameLayout.LayoutParams lp;
@ -89,58 +106,65 @@ public class FeaturedStickerSetInfoCell extends FrameLayout {
} }
addView(infoTextView, lp); addView(infoTextView, lp);
addButton = new ProgressButton(context); if (canAddRemove) {
addButton.setProgressColor(Theme.getColor(Theme.key_featuredStickers_buttonProgress)); addButton = new ProgressButton(context);
addButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); addButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText));
addButton.setBackgroundRoundRect(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed)); addButton.setText(LocaleController.getString("Add", R.string.Add));
addButton.setText(LocaleController.getString("Add", R.string.Add)); if (supportRtl) {
if (supportRtl) { lp = LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 16, 14, 0);
lp = LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 16, 14, 0); } else {
} else { lp = LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.RIGHT, 0, 16, 14, 0);
lp = LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.RIGHT, 0, 16, 14, 0); }
} addView(addButton, lp);
addView(addButton, lp);
delButton = new TextView(context); delButton = new TextView(context);
delButton.setGravity(Gravity.CENTER); delButton.setGravity(Gravity.CENTER);
delButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_removeButtonText)); delButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_removeButtonText));
delButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); delButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
delButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); delButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
delButton.setText(LocaleController.getString("StickersRemove", R.string.StickersRemove)); delButton.setText(LocaleController.getString("StickersRemove", R.string.StickersRemove));
if (supportRtl) { if (supportRtl) {
lp = LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 16, 14, 0); lp = LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 16, 14, 0);
} else { } else {
lp = LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.RIGHT, 0, 16, 14, 0); lp = LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.RIGHT, 0, 16, 14, 0);
}
addView(delButton, lp);
} }
addView(delButton, lp);
setWillNotDraw(false); setWillNotDraw(false);
updateColors();
} }
@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(60), MeasureSpec.EXACTLY)); super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(60), MeasureSpec.EXACTLY));
int width = addButton.getMeasuredWidth(); if (canAddRemove) {
int width2 = delButton.getMeasuredWidth(); int width = addButton.getMeasuredWidth();
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) delButton.getLayoutParams(); int width2 = delButton.getMeasuredWidth();
if (width2 < width) { FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) delButton.getLayoutParams();
layoutParams.rightMargin = AndroidUtilities.dp(14) + (width - width2) / 2; if (width2 < width) {
} else { layoutParams.rightMargin = AndroidUtilities.dp(14) + (width - width2) / 2;
layoutParams.rightMargin = AndroidUtilities.dp(14); } else {
} layoutParams.rightMargin = AndroidUtilities.dp(14);
}
measureChildWithMargins(nameTextView, widthMeasureSpec, width, heightMeasureSpec, 0); measureChildWithMargins(nameTextView, widthMeasureSpec, width, heightMeasureSpec, 0);
}
} }
public void setAddOnClickListener(OnClickListener onClickListener) { public void setAddOnClickListener(OnClickListener onClickListener) {
hasOnClick = true; if (canAddRemove) {
addButton.setOnClickListener(onClickListener); hasOnClick = true;
delButton.setOnClickListener(onClickListener); addButton.setOnClickListener(onClickListener);
delButton.setOnClickListener(onClickListener);
}
} }
public void setAddDrawProgress(boolean drawProgress, boolean animated) { public void setAddDrawProgress(boolean drawProgress, boolean animated) {
addButton.setDrawProgress(drawProgress, animated); if (canAddRemove) {
addButton.setDrawProgress(drawProgress, animated);
}
} }
public void setStickerSet(TLRPC.StickerSetCovered stickerSet, boolean unread) { public void setStickerSet(TLRPC.StickerSetCovered stickerSet, boolean unread) {
@ -160,85 +184,98 @@ public class FeaturedStickerSetInfoCell extends FrameLayout {
animatorSet.cancel(); animatorSet.cancel();
animatorSet = null; animatorSet = null;
} }
set = stickerSet;
stickerSetNameSearchIndex = index;
stickerSetNameSearchLength = searchLength;
if (searchLength != 0) { if (searchLength != 0) {
SpannableStringBuilder builder = new SpannableStringBuilder(stickerSet.set.title); updateStickerSetNameSearchSpan();
try {
builder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + searchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception ignore) {
}
nameTextView.setText(builder);
} else { } else {
nameTextView.setText(stickerSet.set.title); nameTextView.setText(stickerSet.set.title);
} }
infoTextView.setText(LocaleController.formatPluralString("Stickers", stickerSet.set.count)); infoTextView.setText(LocaleController.formatPluralString("Stickers", stickerSet.set.count));
isUnread = unread; isUnread = unread;
if (hasOnClick) { if (canAddRemove) {
addButton.setVisibility(VISIBLE); if (hasOnClick) {
isInstalled = forceInstalled || MediaDataController.getInstance(currentAccount).isStickerPackInstalled(stickerSet.set.id); addButton.setVisibility(VISIBLE);
if (animated) { isInstalled = forceInstalled || MediaDataController.getInstance(currentAccount).isStickerPackInstalled(stickerSet.set.id);
if (isInstalled) { if (animated) {
delButton.setVisibility(VISIBLE); if (isInstalled) {
} else { delButton.setVisibility(VISIBLE);
addButton.setVisibility(VISIBLE); } else {
} addButton.setVisibility(VISIBLE);
animatorSet = new AnimatorSet();
animatorSet.setDuration(250);
animatorSet.playTogether(
ObjectAnimator.ofFloat(delButton, View.ALPHA, isInstalled ? 1.0f : 0.0f),
ObjectAnimator.ofFloat(delButton, View.SCALE_X, isInstalled ? 1.0f : 0.0f),
ObjectAnimator.ofFloat(delButton, View.SCALE_Y, isInstalled ? 1.0f : 0.0f),
ObjectAnimator.ofFloat(addButton, View.ALPHA, isInstalled ? 0.0f : 1.0f),
ObjectAnimator.ofFloat(addButton, View.SCALE_X, isInstalled ? 0.0f : 1.0f),
ObjectAnimator.ofFloat(addButton, View.SCALE_Y, isInstalled ? 0.0f : 1.0f));
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (isInstalled) {
addButton.setVisibility(INVISIBLE);
} else {
delButton.setVisibility(INVISIBLE);
}
} }
}); animatorSet = new AnimatorSet();
animatorSet.setInterpolator(new OvershootInterpolator(1.02f)); animatorSet.setDuration(250);
animatorSet.start(); animatorSet.playTogether(
} else { ObjectAnimator.ofFloat(delButton, View.ALPHA, isInstalled ? 1.0f : 0.0f),
if (isInstalled) { ObjectAnimator.ofFloat(delButton, View.SCALE_X, isInstalled ? 1.0f : 0.0f),
delButton.setVisibility(VISIBLE); ObjectAnimator.ofFloat(delButton, View.SCALE_Y, isInstalled ? 1.0f : 0.0f),
delButton.setAlpha(1.0f); ObjectAnimator.ofFloat(addButton, View.ALPHA, isInstalled ? 0.0f : 1.0f),
delButton.setScaleX(1.0f); ObjectAnimator.ofFloat(addButton, View.SCALE_X, isInstalled ? 0.0f : 1.0f),
delButton.setScaleY(1.0f); ObjectAnimator.ofFloat(addButton, View.SCALE_Y, isInstalled ? 0.0f : 1.0f));
addButton.setVisibility(INVISIBLE); animatorSet.addListener(new AnimatorListenerAdapter() {
addButton.setAlpha(0.0f); @Override
addButton.setScaleX(0.0f); public void onAnimationEnd(Animator animation) {
addButton.setScaleY(0.0f); if (isInstalled) {
addButton.setVisibility(INVISIBLE);
} else {
delButton.setVisibility(INVISIBLE);
}
}
});
animatorSet.setInterpolator(new OvershootInterpolator(1.02f));
animatorSet.start();
} else { } else {
addButton.setVisibility(VISIBLE); if (isInstalled) {
addButton.setAlpha(1.0f); delButton.setVisibility(VISIBLE);
addButton.setScaleX(1.0f); delButton.setAlpha(1.0f);
addButton.setScaleY(1.0f); delButton.setScaleX(1.0f);
delButton.setVisibility(INVISIBLE); delButton.setScaleY(1.0f);
delButton.setAlpha(0.0f); addButton.setVisibility(INVISIBLE);
delButton.setScaleX(0.0f); addButton.setAlpha(0.0f);
delButton.setScaleY(0.0f); addButton.setScaleX(0.0f);
addButton.setScaleY(0.0f);
} else {
addButton.setVisibility(VISIBLE);
addButton.setAlpha(1.0f);
addButton.setScaleX(1.0f);
addButton.setScaleY(1.0f);
delButton.setVisibility(INVISIBLE);
delButton.setAlpha(0.0f);
delButton.setScaleX(0.0f);
delButton.setScaleY(0.0f);
}
} }
} else {
addButton.setVisibility(GONE);
} }
} else {
addButton.setVisibility(GONE);
} }
}
set = stickerSet; private void updateStickerSetNameSearchSpan() {
if (stickerSetNameSearchLength != 0) {
SpannableStringBuilder builder = new SpannableStringBuilder(set.set.title);
try {
builder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), stickerSetNameSearchIndex, stickerSetNameSearchIndex + stickerSetNameSearchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception ignore) {
}
nameTextView.setText(builder);
}
} }
public void setUrl(CharSequence text, int searchLength) { public void setUrl(CharSequence text, int searchLength) {
if (text != null) { url = text;
SpannableStringBuilder builder = new SpannableStringBuilder(text); urlSearchLength = searchLength;
try { updateUrlSearchSpan();
builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), 0, searchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); }
builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_chat_emojiPanelTrendingDescription)), searchLength, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception ignore) {
private void updateUrlSearchSpan() {
if (url != null) {
SpannableStringBuilder builder = new SpannableStringBuilder(url);
try {
builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), 0, urlSearchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_chat_emojiPanelTrendingDescription)), urlSearchLength, url.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception ignore) {
} }
infoTextView.setText(builder); infoTextView.setText(builder);
} }
@ -270,4 +307,27 @@ public class FeaturedStickerSetInfoCell extends FrameLayout {
canvas.drawLine(0, 0, getWidth(), 0, Theme.dividerPaint); canvas.drawLine(0, 0, getWidth(), 0, Theme.dividerPaint);
} }
} }
public void updateColors() {
if (canAddRemove) {
addButton.setProgressColor(Theme.getColor(Theme.key_featuredStickers_buttonProgress));
addButton.setBackgroundRoundRect(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed));
}
updateStickerSetNameSearchSpan();
updateUrlSearchSpan();
}
public static void createThemeDescriptions(List<ThemeDescription> descriptions, RecyclerListView listView, ThemeDescription.ThemeDescriptionDelegate delegate) {
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{FeaturedStickerSetInfoCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_chat_emojiPanelTrendingTitle));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{FeaturedStickerSetInfoCell.class}, new String[]{"infoTextView"}, null, null, null, Theme.key_chat_emojiPanelTrendingDescription));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{FeaturedStickerSetInfoCell.class}, new String[]{"addButton"}, null, null, null, Theme.key_featuredStickers_buttonText));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{FeaturedStickerSetInfoCell.class}, new String[]{"delButton"}, null, null, null, Theme.key_featuredStickers_removeButtonText));
descriptions.add(new ThemeDescription(listView, 0, new Class[]{FeaturedStickerSetInfoCell.class}, null, null, null, Theme.key_featuredStickers_unread));
descriptions.add(new ThemeDescription(listView, 0, new Class[]{FeaturedStickerSetInfoCell.class}, Theme.dividerPaint, null, null, Theme.key_divider));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_featuredStickers_buttonProgress));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_featuredStickers_addButton));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_featuredStickers_addButtonPressed));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_windowBackgroundWhiteBlueText4));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_chat_emojiPanelTrendingDescription));
}
} }

View File

@ -17,12 +17,16 @@ import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController; import org.telegram.messenger.LocaleController;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RecyclerListView;
import java.util.List;
public class GraySectionCell extends FrameLayout { public class GraySectionCell extends FrameLayout {
private TextView textView; private TextView textView;
private TextView righTextView; private TextView rightTextView;
public GraySectionCell(Context context) { public GraySectionCell(Context context) {
super(context); super(context);
@ -36,11 +40,11 @@ public class GraySectionCell extends FrameLayout {
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 16, 0, 16, 0)); addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 16, 0, 16, 0));
righTextView = new TextView(getContext()); rightTextView = new TextView(getContext());
righTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); rightTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
righTextView.setTextColor(Theme.getColor(Theme.key_graySectionText)); rightTextView.setTextColor(Theme.getColor(Theme.key_graySectionText));
righTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL); rightTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL);
addView(righTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 16, 0, 16, 0)); addView(rightTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 16, 0, 16, 0));
} }
@Override @Override
@ -50,13 +54,19 @@ public class GraySectionCell extends FrameLayout {
public void setText(String text) { public void setText(String text) {
textView.setText(text); textView.setText(text);
righTextView.setVisibility(GONE); rightTextView.setVisibility(GONE);
} }
public void setText(String left, String right, OnClickListener onClickListener) { public void setText(String left, String right, OnClickListener onClickListener) {
textView.setText(left); textView.setText(left);
righTextView.setText(right); rightTextView.setText(right);
righTextView.setOnClickListener(onClickListener); rightTextView.setOnClickListener(onClickListener);
righTextView.setVisibility(VISIBLE); rightTextView.setVisibility(VISIBLE);
}
public static void createThemeDescriptions(List<ThemeDescription> descriptions, RecyclerListView listView) {
descriptions.add(new ThemeDescription(listView, 0, new Class[]{GraySectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_graySectionText));
descriptions.add(new ThemeDescription(listView, 0, new Class[]{GraySectionCell.class}, new String[]{"rightTextView"}, null, null, null, Theme.key_graySectionText));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{GraySectionCell.class}, null, null, null, Theme.key_graySection));
} }
} }

View File

@ -52,10 +52,13 @@ public class GroupCreateUserCell extends FrameLayout {
private boolean drawDivider; private boolean drawDivider;
private int padding; private int padding;
public GroupCreateUserCell(Context context, boolean needCheck, int padding) { private boolean showSelfAsSaved;
public GroupCreateUserCell(Context context, boolean needCheck, int pad, boolean selfAsSaved) {
super(context); super(context);
drawDivider = false; drawDivider = false;
this.padding = padding; padding = pad;
showSelfAsSaved = selfAsSaved;
avatarDrawable = new AvatarDrawable(); avatarDrawable = new AvatarDrawable();
avatarImageView = new BackupImageView(context); avatarImageView = new BackupImageView(context);
@ -174,7 +177,11 @@ public class GroupCreateUserCell extends FrameLayout {
statusTextView.setText(null); statusTextView.setText(null);
avatarImageView.setImage(null, "50_50", avatarDrawable); avatarImageView.setImage(null, "50_50", avatarDrawable);
} else { } else {
((LayoutParams) nameTextView.getLayoutParams()).topMargin = AndroidUtilities.dp(10); if (currentStatus != null && TextUtils.isEmpty(currentStatus)) {
((LayoutParams) nameTextView.getLayoutParams()).topMargin = AndroidUtilities.dp(19);
} else {
((LayoutParams) nameTextView.getLayoutParams()).topMargin = AndroidUtilities.dp(10);
}
avatarImageView.getLayoutParams().width = avatarImageView.getLayoutParams().height = AndroidUtilities.dp(46); avatarImageView.getLayoutParams().width = avatarImageView.getLayoutParams().height = AndroidUtilities.dp(46);
if (checkBox != null) { if (checkBox != null) {
((LayoutParams) checkBox.getLayoutParams()).topMargin = AndroidUtilities.dp(33); ((LayoutParams) checkBox.getLayoutParams()).topMargin = AndroidUtilities.dp(33);
@ -187,7 +194,7 @@ public class GroupCreateUserCell extends FrameLayout {
if (currentObject instanceof TLRPC.User) { if (currentObject instanceof TLRPC.User) {
TLRPC.User currentUser = (TLRPC.User) currentObject; TLRPC.User currentUser = (TLRPC.User) currentObject;
if (UserObject.isUserSelf(currentUser)) { if (showSelfAsSaved && UserObject.isUserSelf(currentUser)) {
nameTextView.setText(LocaleController.getString("SavedMessages", R.string.SavedMessages), true); nameTextView.setText(LocaleController.getString("SavedMessages", R.string.SavedMessages), true);
statusTextView.setText(null); statusTextView.setText(null);
avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED);

View File

@ -21,6 +21,7 @@ import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.SystemClock; import android.os.SystemClock;
import android.text.TextUtils;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.Gravity; import android.view.Gravity;
import android.view.MotionEvent; import android.view.MotionEvent;
@ -227,11 +228,22 @@ public class PhotoAttachPhotoCell extends FrameLayout {
imageView.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) {
imageView.setImage(searchImage.thumbPath, null, thumb); imageView.setImage(searchImage.thumbPath, null, thumb);
} else if (searchImage.thumbUrl != null && searchImage.thumbUrl.length() > 0) { } else if (!TextUtils.isEmpty(searchImage.thumbUrl)) {
imageView.setImage(searchImage.thumbUrl, null, thumb); ImageLocation location = ImageLocation.getForPath(searchImage.thumbUrl);
} else if (MessageObject.isDocumentHasThumb(searchImage.document)) { if (searchImage.type == 1 && searchImage.thumbUrl.endsWith("mp4")) {
TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(searchImage.document.thumbs, 320); location.imageType = FileLoader.IMAGE_TYPE_ANIMATION;
imageView.setImage(ImageLocation.getForDocument(photoSize, searchImage.document), null, thumb, searchImage); }
imageView.setImage(location, null, thumb, searchImage);
} else if (searchImage.document != null) {
MessageObject.getDocumentVideoThumb(searchImage.document);
TLRPC.TL_videoSize videoSize = MessageObject.getDocumentVideoThumb(searchImage.document);
if (videoSize != null) {
TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(searchImage.document.thumbs, 90);
imageView.setImage(ImageLocation.getForDocument(videoSize, searchImage.document), null, ImageLocation.getForDocument(currentPhotoObject, searchImage.document), "52_52", null, -1, 1, searchImage);
} else {
TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(searchImage.document.thumbs, 320);
imageView.setImage(ImageLocation.getForDocument(photoSize, searchImage.document), null, thumb, searchImage);
}
} else { } else {
imageView.setImageDrawable(thumb); imageView.setImageDrawable(thumb);
} }

View File

@ -8,18 +8,15 @@
package org.telegram.ui.Cells; package org.telegram.ui.Cells;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
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.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
@ -34,38 +31,51 @@ 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.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;
public class PhotoPickerPhotoCell extends FrameLayout { public class PhotoPickerPhotoCell extends FrameLayout {
public BackupImageView imageView; public BackupImageView imageView;
public FrameLayout checkFrame; public FrameLayout checkFrame;
public CheckBox checkBox; public CheckBox2 checkBox;
public TextView videoTextView; public TextView videoTextView;
public FrameLayout videoInfoContainer; public FrameLayout videoInfoContainer;
private AnimatorSet animator; private int itemWidth;
private AnimatorSet animatorSet; private int extraWidth;
public int itemWidth;
private boolean zoomOnSelect;
private Paint backgroundPaint = new Paint(); private Paint backgroundPaint = new Paint();
private MediaController.PhotoEntry photoEntry;
public PhotoPickerPhotoCell(Context context, boolean zoom) { public PhotoPickerPhotoCell(Context context) {
super(context); super(context);
setWillNotDraw(false); setWillNotDraw(false);
zoomOnSelect = zoom;
imageView = new BackupImageView(context); imageView = new BackupImageView(context);
imageView.setRoundRadius(AndroidUtilities.dp(4));
addView(imageView, 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));
videoInfoContainer = new FrameLayout(context); videoInfoContainer = new FrameLayout(context) {
videoInfoContainer.setBackgroundResource(R.drawable.phototime);
private Path path = new Path();
float[] radii = new float[8];
private RectF rect = new RectF();
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
@Override
protected void onDraw(Canvas canvas) {
rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
radii[0] = radii[1] = radii[2] = radii[3] = 0;
radii[4] = radii[5] = radii[6] = radii[7] = AndroidUtilities.dp(4);
path.reset();
path.addRoundRect(rect, radii, Path.Direction.CW);
path.close();
paint.setColor(0x7f000000);
canvas.drawPath(path, paint);
}
};
videoInfoContainer.setWillNotDraw(false);
videoInfoContainer.setPadding(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(3), 0); videoInfoContainer.setPadding(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(3), 0);
addView(videoInfoContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 16, Gravity.BOTTOM | Gravity.LEFT)); addView(videoInfoContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 16, Gravity.BOTTOM | Gravity.LEFT));
@ -79,19 +89,18 @@ public class PhotoPickerPhotoCell extends FrameLayout {
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, 18, -0.7f, 0, 0));
checkBox = new CheckBox(context, R.drawable.checkbig); checkBox = new CheckBox2(context, 24);
checkBox.setSize(zoom ? 30 : 26); checkBox.setDrawBackgroundAsArc(11);
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, 55, 4, 0, 0));
checkBox.setColor(Theme.getColor(Theme.key_dialogFloatingButton), 0xffffffff); checkBox.setVisibility(VISIBLE);
addView(checkBox, LayoutHelper.createFrame(zoom ? 30 : 26, zoom ? 30 : 26, Gravity.RIGHT | Gravity.TOP, 0, 4, 4, 0));
setFocusable(true); setFocusable(true);
} }
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY)); super.onMeasure(MeasureSpec.makeMeasureSpec(itemWidth + extraWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY));
} }
@Override @Override
@ -100,39 +109,30 @@ public class PhotoPickerPhotoCell extends FrameLayout {
updateColors(); updateColors();
} }
public void updateColors() { public void setItemWidth(int width, int extra) {
checkBox.setColor(Theme.getColor(Theme.key_dialogFloatingButton), 0xffffffff); itemWidth = width;
extraWidth = extra;
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) checkFrame.getLayoutParams();
layoutParams.rightMargin = extra;
layoutParams = (FrameLayout.LayoutParams) imageView.getLayoutParams();
layoutParams.rightMargin = extra;
layoutParams = (FrameLayout.LayoutParams) videoInfoContainer.getLayoutParams();
layoutParams.rightMargin = extra;
} }
public void showCheck(boolean show) { public void updateColors() {
if (animatorSet != null) { checkBox.setColor(Theme.key_chat_attachCheckBoxBackground, Theme.key_chat_attachPhotoBackground, Theme.key_chat_attachCheckBoxCheck);
animatorSet.cancel();
animatorSet = null;
}
animatorSet = new AnimatorSet();
animatorSet.setInterpolator(new DecelerateInterpolator());
animatorSet.setDuration(180);
animatorSet.playTogether(
ObjectAnimator.ofFloat(videoInfoContainer, "alpha", show ? 1.0f : 0.0f),
ObjectAnimator.ofFloat(checkBox, "alpha", show ? 1.0f : 0.0f));
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (animation.equals(animatorSet)) {
animatorSet = null;
}
}
});
animatorSet.start();
} }
public void setNum(int num) { public void setNum(int num) {
checkBox.setNum(num); checkBox.setNum(num);
} }
public void setImage(MediaController.PhotoEntry entry) { public void setImage(MediaController.PhotoEntry photoEntry) {
Drawable thumb = zoomOnSelect ? Theme.chat_attachEmptyDrawable : getResources().getDrawable(R.drawable.nophotos); Drawable thumb = getResources().getDrawable(R.drawable.nophotos);
photoEntry = entry;
if (photoEntry.thumbPath != null) { if (photoEntry.thumbPath != null) {
imageView.setImage(photoEntry.thumbPath, null, thumb); imageView.setImage(photoEntry.thumbPath, null, thumb);
} else if (photoEntry.path != null) { } else if (photoEntry.path != null) {
@ -153,7 +153,7 @@ public class PhotoPickerPhotoCell extends FrameLayout {
} }
public void setImage(MediaController.SearchImage searchImage) { public void setImage(MediaController.SearchImage searchImage) {
Drawable thumb = zoomOnSelect ? Theme.chat_attachEmptyDrawable : getResources().getDrawable(R.drawable.nophotos); Drawable thumb = getResources().getDrawable(R.drawable.nophotos);
if (searchImage.thumbPhotoSize != null) { if (searchImage.thumbPhotoSize != null) {
imageView.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) {
@ -172,50 +172,5 @@ public class PhotoPickerPhotoCell extends FrameLayout {
public void setChecked(final int num, final boolean checked, final boolean animated) { public void setChecked(final int num, final boolean checked, final boolean animated) {
checkBox.setChecked(num, checked, animated); checkBox.setChecked(num, checked, animated);
if (animator != null) {
animator.cancel();
animator = null;
}
if (zoomOnSelect) {
if (animated) {
animator = new AnimatorSet();
animator.playTogether(ObjectAnimator.ofFloat(imageView, View.SCALE_X, checked ? 0.85f : 1.0f),
ObjectAnimator.ofFloat(imageView, View.SCALE_Y, checked ? 0.85f : 1.0f));
animator.setDuration(200);
animator.addListener(new AnimatorListenerAdapter() {
@Override
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 {
imageView.setScaleX(checked ? 0.85f : 1.0f);
imageView.setScaleY(checked ? 0.85f : 1.0f);
}
}
}
@Override
protected void onDraw(Canvas canvas) {
if (!zoomOnSelect) {
return;
}
if (checkBox.isChecked() || imageView.getScaleX() != 1.0f || !imageView.getImageReceiver().hasNotThumb() || imageView.getImageReceiver().getCurrentAlpha() != 1.0f || photoEntry != null && PhotoViewer.isShowingImage(photoEntry.path)) {
backgroundPaint.setColor(Theme.getColor(Theme.key_chat_attachPhotoBackground));
canvas.drawRect(0, 0, imageView.getMeasuredWidth(), imageView.getMeasuredHeight(), backgroundPaint);
}
} }
} }

View File

@ -31,7 +31,6 @@ import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessageObject;
import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.TLRPC; import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.CheckBox2;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
@ -46,10 +45,8 @@ public class SharedLinkCell extends FrameLayout {
public interface SharedLinkCellDelegate { public interface SharedLinkCellDelegate {
void needOpenWebView(TLRPC.WebPage webPage); void needOpenWebView(TLRPC.WebPage webPage);
boolean canPerformActions(); boolean canPerformActions();
void onLinkPress(final String urlFinal, boolean longPress);
void onLinkLongPress(final String urlFinal);
} }
private boolean checkingForLongPress = false; private boolean checkingForLongPress = false;
@ -75,7 +72,7 @@ public class SharedLinkCell extends FrameLayout {
checkingForLongPress = false; checkingForLongPress = false;
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
if (pressedLink >= 0) { if (pressedLink >= 0) {
delegate.onLinkLongPress(links.get(pressedLink)); delegate.onLinkPress(links.get(pressedLink), true);
} }
MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0);
onTouchEvent(event); onTouchEvent(event);
@ -430,7 +427,7 @@ public class SharedLinkCell extends FrameLayout {
if (webPage != null && webPage.embed_url != null && webPage.embed_url.length() != 0) { if (webPage != null && webPage.embed_url != null && webPage.embed_url.length() != 0) {
delegate.needOpenWebView(webPage); delegate.needOpenWebView(webPage);
} else { } else {
Browser.openUrl(getContext(), links.get(pressedLink)); delegate.onLinkPress(links.get(pressedLink), false);
} }
} catch (Exception e) { } catch (Exception e) {
FileLog.e(e); FileLog.e(e);

View File

@ -25,8 +25,12 @@ import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.Emoji; import org.telegram.messenger.Emoji;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Components.ColorSpanUnderline; import org.telegram.ui.Components.ColorSpanUnderline;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RecyclerListView;
import java.util.List;
public class StickerSetNameCell extends FrameLayout { public class StickerSetNameCell extends FrameLayout {
@ -36,6 +40,13 @@ public class StickerSetNameCell extends FrameLayout {
private boolean empty; private boolean empty;
private boolean isEmoji; private boolean isEmoji;
private CharSequence stickerSetName;
private int stickerSetNameSearchIndex;
private int stickerSetNameSearchLength;
private CharSequence url;
private int urlSearchLength;
public StickerSetNameCell(Context context, boolean emoji) { public StickerSetNameCell(Context context, boolean emoji) {
this(context, emoji, false); this(context, emoji, false);
} }
@ -85,18 +96,21 @@ public class StickerSetNameCell extends FrameLayout {
} }
public void setUrl(CharSequence text, int searchLength) { public void setUrl(CharSequence text, int searchLength) {
if (text != null) { url = text;
SpannableStringBuilder builder = new SpannableStringBuilder(text); urlSearchLength = searchLength;
try { urlTextView.setVisibility(text != null ? VISIBLE : GONE);
builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_chat_emojiPanelStickerSetNameHighlight)), 0, searchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //TODO updateUrlSearchSpan();
builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_chat_emojiPanelStickerSetName)), searchLength, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); }
} catch (Exception ignore) {
private void updateUrlSearchSpan() {
if (url != null) {
SpannableStringBuilder builder = new SpannableStringBuilder(url);
try {
builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_chat_emojiPanelStickerSetNameHighlight)), 0, urlSearchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.setSpan(new ColorSpanUnderline(Theme.getColor(Theme.key_chat_emojiPanelStickerSetName)), urlSearchLength, url.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception ignore) {
} }
urlTextView.setText(builder); urlTextView.setText(builder);
urlTextView.setVisibility(VISIBLE);
} else {
urlTextView.setVisibility(GONE);
} }
} }
@ -104,20 +118,21 @@ public class StickerSetNameCell extends FrameLayout {
setText(text, resId, 0, 0); setText(text, resId, 0, 0);
} }
public void setTitleColor(int color) {
textView.setTextColor(color);
}
public void setText(CharSequence text, int resId, int index, int searchLength) { public void setText(CharSequence text, int resId, int index, int searchLength) {
stickerSetName = text;
stickerSetNameSearchIndex = index;
stickerSetNameSearchLength = searchLength;
if (text == null) { if (text == null) {
empty = true; empty = true;
textView.setText(""); textView.setText("");
buttonView.setVisibility(INVISIBLE); buttonView.setVisibility(INVISIBLE);
} else { } else {
if (searchLength != 0) { if (searchLength != 0) {
SpannableStringBuilder builder = new SpannableStringBuilder(text); updateTextSearchSpan();
try {
builder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chat_emojiPanelStickerSetNameHighlight)), index, index + searchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception ignore) {
}
textView.setText(builder);
} else { } else {
textView.setText(Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); textView.setText(Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false));
} }
@ -130,6 +145,17 @@ public class StickerSetNameCell extends FrameLayout {
} }
} }
private void updateTextSearchSpan() {
if (stickerSetName != null && stickerSetNameSearchLength != 0) {
SpannableStringBuilder builder = new SpannableStringBuilder(stickerSetName);
try {
builder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_chat_emojiPanelStickerSetNameHighlight)), stickerSetNameSearchIndex, stickerSetNameSearchIndex + stickerSetNameSearchLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} catch (Exception ignore) {
}
textView.setText(Emoji.replaceEmoji(builder, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false));
}
}
public void setOnIconClickListener(OnClickListener onIconClickListener) { public void setOnIconClickListener(OnClickListener onIconClickListener) {
buttonView.setOnClickListener(onIconClickListener); buttonView.setOnClickListener(onIconClickListener);
} }
@ -156,4 +182,17 @@ public class StickerSetNameCell extends FrameLayout {
} }
super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
} }
public void updateColors() {
updateTextSearchSpan();
updateUrlSearchSpan();
}
public static void createThemeDescriptions(List<ThemeDescription> descriptions, RecyclerListView listView, ThemeDescription.ThemeDescriptionDelegate delegate) {
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{StickerSetNameCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_emojiPanelStickerSetName));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{StickerSetNameCell.class}, new String[]{"urlTextView"}, null, null, null, Theme.key_chat_emojiPanelStickerSetName));
descriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{StickerSetNameCell.class}, new String[]{"buttonView"}, null, null, null, Theme.key_chat_emojiPanelStickerSetNameIcon));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_chat_emojiPanelStickerSetNameHighlight));
descriptions.add(new ThemeDescription(null, 0, null, null, null, delegate, Theme.key_chat_emojiPanelStickerSetName));
}
} }

View File

@ -60,6 +60,7 @@ import tw.nekomimi.nekogram.transtale.Translator;
import tw.nekomimi.nekogram.utils.AlertUtil; import tw.nekomimi.nekogram.utils.AlertUtil;
import tw.nekomimi.nekogram.utils.ProxyUtil; import tw.nekomimi.nekogram.utils.ProxyUtil;
import static com.google.zxing.common.detector.MathUtils.distance;
import static org.telegram.ui.ActionBar.FloatingToolbar.STYLE_THEME; import static org.telegram.ui.ActionBar.FloatingToolbar.STYLE_THEME;
import static org.telegram.ui.ActionBar.Theme.key_chat_inTextSelectionHighlight; import static org.telegram.ui.ActionBar.Theme.key_chat_inTextSelectionHighlight;
@ -418,10 +419,6 @@ public abstract class TextSelectionHelper<Cell extends TextSelectionHelper.Selec
return selectionStart >= 0 && selectionEnd >= 0; return selectionStart >= 0 && selectionEnd >= 0;
} }
float distance(int x1, int y1, int x2, int y2) {
return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
private ActionBarPopupWindow popupWindow; private ActionBarPopupWindow popupWindow;
private ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout; private ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout;
private TextView deleteView; private TextView deleteView;

View File

@ -89,7 +89,6 @@ import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.SimpleTextView;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.BotHelpCell;
import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.Cells.ChatActionCell;
import org.telegram.ui.Cells.ChatLoadingCell; import org.telegram.ui.Cells.ChatLoadingCell;
import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Cells.ChatMessageCell;
@ -188,6 +187,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
private MessageObject scrollToMessage; private MessageObject scrollToMessage;
private int allowAnimationIndex;
private PhotoViewer.PhotoViewerProvider provider = new PhotoViewer.EmptyPhotoViewerProvider() { private PhotoViewer.PhotoViewerProvider provider = new PhotoViewer.EmptyPhotoViewerProvider() {
@Override @Override
@ -1740,9 +1741,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
@Override @Override
public void onTransitionAnimationStart(boolean isOpen, boolean backward) { public void onTransitionAnimationStart(boolean isOpen, boolean backward) {
if (isOpen) { if (isOpen) {
NotificationCenter.getInstance(currentAccount).setAllowedNotificationsDutingAnimation(new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload, allowAnimationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(allowAnimationIndex, new int[]{NotificationCenter.chatInfoDidLoad, NotificationCenter.dialogsNeedReload,
NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad/*, NotificationCenter.botInfoDidLoad*/}); NotificationCenter.closeChats, NotificationCenter.messagesDidLoad, NotificationCenter.botKeyboardDidLoad/*, NotificationCenter.botInfoDidLoad*/});
NotificationCenter.getInstance(currentAccount).setAnimationInProgress(true);
openAnimationEnded = false; openAnimationEnded = false;
} }
} }
@ -1750,7 +1750,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
@Override @Override
public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { public void onTransitionAnimationEnd(boolean isOpen, boolean backward) {
if (isOpen) { if (isOpen) {
NotificationCenter.getInstance(currentAccount).setAnimationInProgress(false); NotificationCenter.getInstance(currentAccount).onAnimationFinish(allowAnimationIndex);
openAnimationEnded = true; openAnimationEnded = true;
} }
} }
@ -2207,17 +2207,6 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio
}); });
} else if (viewType == 2) { } else if (viewType == 2) {
view = new ChatUnreadCell(mContext); view = new ChatUnreadCell(mContext);
} else if (viewType == 3) {
view = new BotHelpCell(mContext);
((BotHelpCell) view).setDelegate(url -> {
if (url.startsWith("@")) {
MessagesController.getInstance(currentAccount).openByUserName(url.substring(1), ChannelAdminLogActivity.this, 0);
} else if (url.startsWith("#")) {
DialogsActivity fragment = new DialogsActivity(null);
fragment.setSearchString(url);
presentFragment(fragment);
}
});
} else if (viewType == 4) { } else if (viewType == 4) {
view = new ChatLoadingCell(mContext); view = new ChatLoadingCell(mContext);
} }

View File

@ -302,7 +302,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0);
int keyboardSize = SharedConfig.smoothKeyboard ? 0 : getKeyboardHeight(); int keyboardSize = SharedConfig.smoothKeyboard ? 0 : measureKeyboardHeight();
if (keyboardSize > AndroidUtilities.dp(20)) { if (keyboardSize > AndroidUtilities.dp(20)) {
ignoreLayout = true; ignoreLayout = true;
nameTextView.hideEmojiView(); nameTextView.hideEmojiView();
@ -335,7 +335,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC
protected void onLayout(boolean changed, int l, int t, int r, int b) { protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount(); final int count = getChildCount();
int keyboardSize = SharedConfig.smoothKeyboard ? 0 : getKeyboardHeight(); int keyboardSize = SharedConfig.smoothKeyboard ? 0 : measureKeyboardHeight();
int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? nameTextView.getEmojiPadding() : 0; int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? nameTextView.getEmojiPadding() : 0;
setBottomClip(paddingBottom); setBottomClip(paddingBottom);

File diff suppressed because it is too large Load Diff

View File

@ -248,7 +248,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0); measureChildWithMargins(actionBar, widthMeasureSpec, 0, heightMeasureSpec, 0);
int keyboardSize = SharedConfig.smoothKeyboard ? 0 : getKeyboardHeight(); int keyboardSize = SharedConfig.smoothKeyboard ? 0 : measureKeyboardHeight();
if (keyboardSize > AndroidUtilities.dp(20)) { if (keyboardSize > AndroidUtilities.dp(20)) {
ignoreLayout = true; ignoreLayout = true;
nameTextView.hideEmojiView(); nameTextView.hideEmojiView();
@ -281,7 +281,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image
protected void onLayout(boolean changed, int l, int t, int r, int b) { protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount(); final int count = getChildCount();
int keyboardSize = SharedConfig.smoothKeyboard ? 0 : getKeyboardHeight(); int keyboardSize = SharedConfig.smoothKeyboard ? 0 : measureKeyboardHeight();
int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? nameTextView.getEmojiPadding() : 0; int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? nameTextView.getEmojiPadding() : 0;
setBottomClip(paddingBottom); setBottomClip(paddingBottom);

View File

@ -659,7 +659,7 @@ public class ChatRightsEditActivity extends BaseFragment {
} }
builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("EditAdminTransferReadyAlertText", R.string.EditAdminTransferReadyAlertText, currentChat.title, UserObject.getFirstName(currentUser)))); builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("EditAdminTransferReadyAlertText", R.string.EditAdminTransferReadyAlertText, currentChat.title, UserObject.getFirstName(currentUser))));
builder.setPositiveButton(LocaleController.getString("EditAdminTransferChangeOwner", R.string.EditAdminTransferChangeOwner), (dialogInterface, i) -> { builder.setPositiveButton(LocaleController.getString("EditAdminTransferChangeOwner", R.string.EditAdminTransferChangeOwner), (dialogInterface, i) -> {
TwoStepVerificationActivity fragment = new TwoStepVerificationActivity(0); TwoStepVerificationActivity fragment = new TwoStepVerificationActivity();
fragment.setDelegate(password -> initTransfer(password, fragment)); fragment.setDelegate(password -> initTransfer(password, fragment));
presentFragment(fragment); presentFragment(fragment);
}); });
@ -734,7 +734,7 @@ public class ChatRightsEditActivity extends BaseFragment {
} }
if ("PASSWORD_MISSING".equals(error.text)) { if ("PASSWORD_MISSING".equals(error.text)) {
builder.setPositiveButton(LocaleController.getString("EditAdminTransferSetPassword", R.string.EditAdminTransferSetPassword), (dialogInterface, i) -> presentFragment(new TwoStepVerificationActivity(0))); builder.setPositiveButton(LocaleController.getString("EditAdminTransferSetPassword", R.string.EditAdminTransferSetPassword), (dialogInterface, i) -> presentFragment(new TwoStepVerificationSetupActivity(TwoStepVerificationSetupActivity.TYPE_INTRO, null)));
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
} else { } else {
messageTextView = new TextView(getParentActivity()); messageTextView = new TextView(getParentActivity());

View File

@ -17,6 +17,7 @@ import android.graphics.Color;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Vibrator; import android.os.Vibrator;
import android.text.Html; import android.text.Html;
@ -56,6 +57,7 @@ import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject; import org.telegram.messenger.UserObject;
import org.telegram.messenger.Utilities; import org.telegram.messenger.Utilities;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLObject;
@ -80,6 +82,7 @@ import org.telegram.ui.ReportOtherActivity;
import org.telegram.ui.ThemePreviewActivity; import org.telegram.ui.ThemePreviewActivity;
import org.telegram.ui.TooManyCommunitiesActivity; import org.telegram.ui.TooManyCommunitiesActivity;
import java.net.IDN;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
@ -452,7 +455,7 @@ public class AlertsCreator {
} }
public static AlertDialog.Builder createSimpleAlert(Context context, final String title, final String text) { public static AlertDialog.Builder createSimpleAlert(Context context, final String title, final String text) {
if (text == null) { if (context == null || text == null) {
return null; return null;
} }
AlertDialog.Builder builder = new AlertDialog.Builder(context); AlertDialog.Builder builder = new AlertDialog.Builder(context);
@ -807,6 +810,47 @@ public class AlertsCreator {
} }
} }
public static void showOpenUrlAlert(BaseFragment fragment, String url, boolean punycode, boolean ask) {
showOpenUrlAlert(fragment, url, punycode, true, ask);
}
public static void showOpenUrlAlert(BaseFragment fragment, String url, boolean punycode, boolean tryTelegraph, boolean ask) {
if (fragment == null || fragment.getParentActivity() == null) {
return;
}
long inlineReturn = (fragment instanceof ChatActivity) ? ((ChatActivity) fragment).getInlineReturn() : 0;
if (Browser.isInternalUrl(url, null) || !ask) {
Browser.openUrl(fragment.getParentActivity(), url, inlineReturn == 0, tryTelegraph);
} else {
String urlFinal;
if (punycode) {
try {
Uri uri = Uri.parse(url);
String host = IDN.toASCII(uri.getHost(), IDN.ALLOW_UNASSIGNED);
urlFinal = uri.getScheme() + "://" + host + uri.getPath();
} catch (Exception e) {
FileLog.e(e);
urlFinal = url;
}
} else {
urlFinal = url;
}
AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity());
builder.setTitle(LocaleController.getString("OpenUrlTitle", R.string.OpenUrlTitle));
String format = LocaleController.getString("OpenUrlAlert2", R.string.OpenUrlAlert2);
int index = format.indexOf("%");
SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format(format, urlFinal));
if (index >= 0) {
stringBuilder.setSpan(new URLSpan(urlFinal), index, index + urlFinal.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
builder.setMessage(stringBuilder);
builder.setMessageTextViewClickable(false);
builder.setPositiveButton(LocaleController.getString("Open", R.string.Open), (dialogInterface, i) -> Browser.openUrl(fragment.getParentActivity(), url, inlineReturn == 0, tryTelegraph));
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
fragment.showDialog(builder.create());
}
}
public static AlertDialog createSupportAlert(BaseFragment fragment) { public static AlertDialog createSupportAlert(BaseFragment fragment) {
if (fragment == null || fragment.getParentActivity() == null) { if (fragment == null || fragment.getParentActivity() == null) {
return null; return null;
@ -1047,7 +1091,11 @@ public class AlertsCreator {
} }
if (second) { if (second) {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllMessagesAlert", R.string.DeleteAllMessagesAlert))); if (UserObject.isUserSelf(user)) {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllMessagesSavedAlert", R.string.DeleteAllMessagesSavedAlert)));
} else {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("DeleteAllMessagesAlert", R.string.DeleteAllMessagesAlert)));
}
} else { } else {
if (clear) { if (clear) {
if (user != null) { if (user != null) {
@ -1088,7 +1136,7 @@ public class AlertsCreator {
if (user.id == selfUserId) { if (user.id == selfUserId) {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("AreYouSureDeleteThisChatSavedMessages", R.string.AreYouSureDeleteThisChatSavedMessages))); messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("AreYouSureDeleteThisChatSavedMessages", R.string.AreYouSureDeleteThisChatSavedMessages)));
} else { } else {
if (user.bot) { if (user.bot && !user.support) {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithBot", R.string.AreYouSureDeleteThisChatWithBot, UserObject.getUserName(user)))); messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithBot", R.string.AreYouSureDeleteThisChatWithBot, UserObject.getUserName(user))));
} else { } else {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithUser", R.string.AreYouSureDeleteThisChatWithUser, UserObject.getUserName(user)))); messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithUser", R.string.AreYouSureDeleteThisChatWithUser, UserObject.getUserName(user))));
@ -1143,17 +1191,22 @@ public class AlertsCreator {
} }
} }
builder.setPositiveButton(actionText, (dialogInterface, i) -> { builder.setPositiveButton(actionText, (dialogInterface, i) -> {
if (user != null && !clearingCache && !second && deleteForAll[0]) { if (!clearingCache && !second) {
MessagesStorage.getInstance(fragment.getCurrentAccount()).getMessagesCount(user.id, (count) -> { if (UserObject.isUserSelf(user)) {
if (count >= 50) { createClearOrDeleteDialogAlert(fragment, clear, admin, true, chat, user, secret, onProcessRunnable);
createClearOrDeleteDialogAlert(fragment, clear, admin, true, chat, user, secret, onProcessRunnable); return;
} else { } else if (user != null && deleteForAll[0]) {
if (onProcessRunnable != null) { MessagesStorage.getInstance(fragment.getCurrentAccount()).getMessagesCount(user.id, (count) -> {
onProcessRunnable.run(deleteForAll[0]); if (count >= 50) {
createClearOrDeleteDialogAlert(fragment, clear, admin, true, chat, user, secret, onProcessRunnable);
} else {
if (onProcessRunnable != null) {
onProcessRunnable.run(deleteForAll[0]);
}
} }
} });
}); return;
return; }
} }
if (onProcessRunnable != null) { if (onProcessRunnable != null) {
onProcessRunnable.run(second || deleteForAll[0]); onProcessRunnable.run(second || deleteForAll[0]);

View File

@ -42,7 +42,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
private static native long createDecoder(String src, int[] params, int account, long streamFileSize, Object readCallback, boolean preview); private static native long createDecoder(String src, int[] params, int account, long streamFileSize, Object readCallback, boolean preview);
private static native void destroyDecoder(long ptr); private static native void destroyDecoder(long ptr);
private static native void stopDecoder(long ptr); private static native void stopDecoder(long ptr);
private static native int getVideoFrame(long ptr, Bitmap bitmap, int[] params, int stride, boolean preview); private static native int getVideoFrame(long ptr, Bitmap bitmap, int[] params, int stride, boolean preview, float startTimeSeconds, float endTimeSeconds);
private static native void seekToMs(long ptr, long ms, boolean precise); private static native void seekToMs(long ptr, long ms, boolean precise);
private static native void prepareToSeek(long ptr); private static native void prepareToSeek(long ptr);
private static native void getVideoInfo(int sdkVersion, String src, int[] params); private static native void getVideoInfo(int sdkVersion, String src, int[] params);
@ -108,6 +108,9 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
private volatile boolean isRecycled; private volatile boolean isRecycled;
public volatile long nativePtr; public volatile long nativePtr;
private DispatchQueue decodeQueue; private DispatchQueue decodeQueue;
private float startTime;
private float endTime;
private View parentView; private View parentView;
private View secondParentView; private View secondParentView;
@ -115,6 +118,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
private AnimatedFileDrawableStream stream; private AnimatedFileDrawableStream stream;
private boolean useSharedQueue; private boolean useSharedQueue;
private boolean invalidatePath = true;
private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2, new ThreadPoolExecutor.DiscardPolicy()); private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2, new ThreadPoolExecutor.DiscardPolicy());
@ -189,7 +193,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
nextRenderingBitmapTime = backgroundBitmapTime; nextRenderingBitmapTime = backgroundBitmapTime;
nextRenderingShader = backgroundShader; nextRenderingShader = backgroundShader;
if (metaData[3] < lastTimeStamp) { if (metaData[3] < lastTimeStamp) {
lastTimeStamp = 0; lastTimeStamp = startTime > 0 ? (int) (startTime * 1000) : 0;
} }
if (metaData[3] - lastTimeStamp != 0) { if (metaData[3] - lastTimeStamp != 0) {
invalidateAfter = metaData[3] - lastTimeStamp; invalidateAfter = metaData[3] - lastTimeStamp;
@ -247,7 +251,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
} }
if (backgroundBitmap != null) { if (backgroundBitmap != null) {
lastFrameDecodeTime = System.currentTimeMillis(); lastFrameDecodeTime = System.currentTimeMillis();
if (getVideoFrame(nativePtr, backgroundBitmap, metaData, backgroundBitmap.getRowBytes(), false) == 0) { if (getVideoFrame(nativePtr, backgroundBitmap, metaData, backgroundBitmap.getRowBytes(), false, startTime, endTime) == 0) {
AndroidUtilities.runOnUIThread(uiRunnableNoFrame); AndroidUtilities.runOnUIThread(uiRunnableNoFrame);
return; return;
} }
@ -306,7 +310,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
if (backgroundBitmap == null) { if (backgroundBitmap == null) {
backgroundBitmap = Bitmap.createBitmap(metaData[0], metaData[1], Bitmap.Config.ARGB_8888); backgroundBitmap = Bitmap.createBitmap(metaData[0], metaData[1], Bitmap.Config.ARGB_8888);
} }
int result = getVideoFrame(nativePtr, backgroundBitmap, metaData, backgroundBitmap.getRowBytes(), true); int result = getVideoFrame(nativePtr, backgroundBitmap, metaData, backgroundBitmap.getRowBytes(), true, 0, 0);
return result != 0 ? backgroundBitmap : null; return result != 0 ? backgroundBitmap : null;
} }
@ -571,13 +575,16 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
shaderMatrix.preScale(scaleX, scaleY); shaderMatrix.preScale(scaleX, scaleY);
renderingShader.setLocalMatrix(shaderMatrix); renderingShader.setLocalMatrix(shaderMatrix);
for (int a = 0; a < roundRadius.length; a++) { if (invalidatePath) {
radii[a * 2] = roundRadius[a]; invalidatePath = false;
radii[a * 2 + 1] = roundRadius[a]; for (int a = 0; a < roundRadius.length; a++) {
radii[a * 2] = roundRadius[a];
radii[a * 2 + 1] = roundRadius[a];
}
roundPath.reset();
roundPath.addRoundRect(actualDrawRect, radii, Path.Direction.CW);
roundPath.close();
} }
roundPath.reset();
roundPath.addRoundRect(actualDrawRect, radii, Path.Direction.CW);
roundPath.close();
canvas.drawPath(roundPath, paint); canvas.drawPath(roundPath, paint);
} else { } else {
canvas.translate(dstRect.left, dstRect.top); canvas.translate(dstRect.left, dstRect.top);
@ -642,7 +649,12 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
} }
public void setActualDrawRect(float x, float y, float width, float height) { public void setActualDrawRect(float x, float y, float width, float height) {
actualDrawRect.set(x, y, x + width, y + height); float bottom = y + height;
float right = x + width;
if (actualDrawRect.left != x || actualDrawRect.top != y || actualDrawRect.right != right || actualDrawRect.bottom != bottom) {
actualDrawRect.set(x, y, right, bottom);
invalidatePath = true;
}
} }
public void setRoundRadius(int[] value) { public void setRoundRadius(int[] value) {
@ -652,8 +664,13 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
} }
System.arraycopy(roundRadius, 0, roundRadiusBackup, 0, roundRadiusBackup.length); System.arraycopy(roundRadius, 0, roundRadiusBackup, 0, roundRadiusBackup.length);
} }
System.arraycopy(value, 0, roundRadius, 0, roundRadius.length); boolean changed = false;
for (int i = 0; i < 4; i++) {
changed = value[i] != roundRadius[i];
roundRadius[i] = value[i];
}
getPaint().setFlags(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); getPaint().setFlags(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
invalidatePath = changed;
} }
private boolean hasRoundRadius() { private boolean hasRoundRadius() {
@ -688,4 +705,16 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable {
public static void getVideoInfo(String src, int[] params) { public static void getVideoInfo(String src, int[] params) {
getVideoInfo(Build.VERSION.SDK_INT, src, params); getVideoInfo(Build.VERSION.SDK_INT, src, params);
} }
public void setStartEndTime(long startTime, long endTime) {
this.startTime = startTime / 1000f;
this.endTime = endTime / 1000f;
if (getCurrentProgressMs() < startTime) {
seekTo(startTime, true);
}
}
public long getStartTime() {
return (long) (startTime * 1000);
}
} }

View File

@ -0,0 +1,194 @@
package org.telegram.ui.Components;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.ChatMessageCell;
import java.util.Random;
public class AudioVisualizerDrawable {
private final CircleBezierDrawable[] drawables;
private final int[] tmpWaveform = new int[3];
private final float[] animateTo = new float[8];
private final float[] current = new float[8];
private final float[] dt = new float[8];
private float idleScale;
private boolean idleScaleInc;
private final Paint p1;
private View parentView;
private final Random random = new Random();
public float IDLE_RADIUS = AndroidUtilities.dp(6) * 0.33f;
public float WAVE_RADIUS = AndroidUtilities.dp(12) * 0.36f;
public float ANIMATION_DURATION = 120;
public int ALPHA = 61;
public AudioVisualizerDrawable() {
drawables = new CircleBezierDrawable[2];
for (int i = 0; i < 2; i++) {
CircleBezierDrawable drawable = drawables[i] = new CircleBezierDrawable(6);
drawable.idleStateDiff = 0;
drawable.radius = AndroidUtilities.dp(24);
drawable.radiusDiff = 0;
drawable.randomK = 1f;
}
p1 = new Paint(Paint.ANTI_ALIAS_FLAG);
}
final int MAX_SAMPLE_SUM = 6;
private float[] lastAmplitude = new float[MAX_SAMPLE_SUM];
private int lastAmplitudeCount;
private int lastAmplitudePointer;
public void setWaveform(boolean playing, boolean animate, float[] waveform) {
if (!playing && !animate) {
for (int i = 0; i < 8; i++) {
animateTo[i] = current[i] = 0;
}
return;
}
boolean idleState = waveform != null && waveform[6] == 0;
float amplitude = waveform == null ? 0 : waveform[6];
if (waveform != null && amplitude > 0.4) {
lastAmplitude[lastAmplitudePointer] = amplitude;
lastAmplitudePointer++;
if (lastAmplitudePointer > MAX_SAMPLE_SUM - 1) {
lastAmplitudePointer = 0;
}
lastAmplitudeCount++;
} else {
lastAmplitudeCount = 0;
}
if (idleState) {
for (int i = 0; i < 6; i++) {
waveform[i] = ((random.nextInt() % 500) / 1000f);
}
}
float duration = idleState ? ANIMATION_DURATION * 2 : ANIMATION_DURATION;
if (lastAmplitudeCount > MAX_SAMPLE_SUM) {
float a = 0;
for (int i = 0; i < MAX_SAMPLE_SUM; i++) {
a += lastAmplitude[i];
}
a /= (float) MAX_SAMPLE_SUM;
if (a > 0.52f) {
duration -= ANIMATION_DURATION * (a - 0.40f);
}
}
for (int i = 0; i < 7; i++) {
if (waveform == null) {
animateTo[i] = 0;
} else {
animateTo[i] = waveform[i];
}
if (parentView == null) {
current[i] = animateTo[i];
} else if (i == 6) {
dt[i] = (animateTo[i] - current[i]) / (ANIMATION_DURATION + 80);
} else {
dt[i] = (animateTo[i] - current[i]) / duration;
}
}
animateTo[7] = playing ? 1f : 0f;
dt[7] = (animateTo[7] - current[7]) / 120;
}
float rotation;
public void draw(Canvas canvas, float cx, float cy, boolean outOwner) {
if (outOwner) {
p1.setColor(Theme.getColor(Theme.key_chat_outLoader));
p1.setAlpha(ALPHA);
} else {
p1.setColor(Theme.getColor(Theme.key_chat_inLoader));
p1.setAlpha(ALPHA);
}
for (int i = 0; i < 8; i++) {
if (animateTo[i] != current[i]) {
current[i] += dt[i] * 16;
if ((dt[i] > 0 && current[i] > animateTo[i]) || (dt[i] < 0 && current[i] < animateTo[i])) {
current[i] = animateTo[i];
}
parentView.invalidate();
}
}
if (idleScaleInc) {
idleScale += 0.02f;
if (idleScale > 1f) {
idleScaleInc = false;
idleScale = 1f;
}
} else {
idleScale -= 0.02f;
if (idleScale < 0) {
idleScaleInc = true;
idleScale = 0;
}
}
float enterProgress = current[7];
float radiusProgress = current[6] * current[0];
// float idleProgress = radiusProgress > 0.4f ? 0 : (1f - radiusProgress / 0.4f);
for (int i = 0; i < 3; i++) {
tmpWaveform[i] = (int) (current[i] * WAVE_RADIUS);
}
//drawables[0].idleStateDiff = enterProgress * idleProgress * IDLE_AMPLITUDE;
//drawables[1].idleStateDiff = enterProgress * idleProgress * IDLE_AMPLITUDE;
drawables[0].setAdditionals(tmpWaveform);
for (int i = 0; i < 3; i++) {
tmpWaveform[i] = (int) (current[i + 3] * WAVE_RADIUS);
}
drawables[1].setAdditionals(tmpWaveform);
float radius = AndroidUtilities.dp(22) +
AndroidUtilities.dp(4) * radiusProgress +
IDLE_RADIUS * enterProgress;
if (radius > AndroidUtilities.dp(26)) {
radius = AndroidUtilities.dp(26);
}
drawables[0].radius = drawables[1].radius = radius;
canvas.save();
rotation += 0.6;
canvas.rotate(rotation, cx, cy);
canvas.save();
float s = 1f + 0.04f * idleScale;
canvas.scale(s, s, cx, cy);
drawables[0].draw(cx, cy, canvas, p1);
canvas.restore();
canvas.rotate(60, cx, cy);
s = 1f + 0.04f * (1f - idleScale);
canvas.scale(s, s, cx, cy);
drawables[1].draw(cx, cy, canvas, p1);
canvas.restore();
}
public void setParentView(ChatMessageCell parentView) {
this.parentView = parentView;
}
public View getParentView() {
return parentView;
}
}

View File

@ -1,427 +0,0 @@
package org.telegram.ui.Components;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.CancellationSignal;
import android.provider.Settings;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.BottomSheet;
import org.telegram.ui.ActionBar.Theme;
import javax.crypto.Cipher;
public class BiometricPromtHelper {
private BaseFragment parentFragment;
private CancellationSignal cancellationSignal;
private BottomSheet bottomSheet;
private ImageView iconImageView;
private Button negativeButton;
private TextView errorTextView;
private int currentState;
private static final int STATE_IDLE = 0;
private static final int STATE_AUTHENTICATING = 1;
private static final int STATE_ERROR = 2;
private static final int STATE_PENDING_CONFIRMATION = 3;
private static final int STATE_AUTHENTICATED = 4;
private Runnable resetRunnable = this::handleResetMessage;
public interface ContinueCallback {
void run(boolean useBiometric);
}
public interface CipherCallback {
void run(Cipher cipher);
}
public BiometricPromtHelper(BaseFragment fragment) {
parentFragment = fragment;
}
public void promtWithCipher(Cipher cipher, String text, CipherCallback callback) {
promtWithCipher(cipher, text, callback, shouldUseFingerprintForCrypto());
}
private void promtWithCipher(Cipher cipher, String text, CipherCallback callback, boolean forceFingerprint) {
if (cipher == null || callback == null || parentFragment == null || parentFragment.getParentActivity() == null) {
return;
}
Activity activity = parentFragment.getParentActivity();
if (Build.VERSION.SDK_INT >= 28 && !forceFingerprint) {
cancellationSignal = new CancellationSignal();
BiometricPrompt.Builder builder = new BiometricPrompt.Builder(activity);
builder.setTitle(LocaleController.getString("Wallet", R.string.Wallet));
builder.setDescription(text);
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), activity.getMainExecutor(), (dialog, which) -> {
});
builder.build().authenticate(new BiometricPrompt.CryptoObject(cipher), cancellationSignal, activity.getMainExecutor(), new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT) {
AlertsCreator.showSimpleAlert(parentFragment, LocaleController.getString("Wallet", R.string.Wallet), LocaleController.getString("WalletBiometricTooManyAttempts", R.string.WalletBiometricTooManyAttempts));
} else if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_NO_BIOMETRICS) {
promtWithCipher(cipher, text, callback, true);
}
}
@Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
}
@Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
callback.run(result.getCryptoObject().getCipher());
}
@Override
public void onAuthenticationFailed() {
}
});
} else if (Build.VERSION.SDK_INT >= 23) {
cancellationSignal = new CancellationSignal();
Context context = parentFragment.getParentActivity();
BottomSheet.Builder builder = new BottomSheet.Builder(context);
builder.setUseFullWidth(false);
builder.setApplyTopPadding(false);
builder.setApplyBottomPadding(false);
LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 0, 4, 4, 4));
builder.setCustomView(linearLayout);
TextView titleTextView = new TextView(context);
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
titleTextView.setGravity(Gravity.CENTER_HORIZONTAL);
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
titleTextView.setText(LocaleController.getString("Wallet", R.string.Wallet));
linearLayout.addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 24, 24, 0));
TextView descriptionTextView = new TextView(context);
descriptionTextView.setGravity(Gravity.CENTER_HORIZONTAL);
descriptionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
descriptionTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
descriptionTextView.setText(text);
descriptionTextView.setPadding(0, AndroidUtilities.dp(8), 0, 0);
linearLayout.addView(descriptionTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 0, 24, 0));
iconImageView = new ImageView(context);
iconImageView.setScaleType(ImageView.ScaleType.FIT_XY);
linearLayout.addView(iconImageView, LayoutHelper.createLinear(64, 64, Gravity.CENTER_HORIZONTAL, 0, 48, 0, 0));
errorTextView = new TextView(context);
errorTextView.setGravity(Gravity.CENTER_HORIZONTAL);
errorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
errorTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray2));
errorTextView.setText(LocaleController.getString("Wallet", R.string.Wallet));
errorTextView.setPadding(0, AndroidUtilities.dp(16), 0, AndroidUtilities.dp(24));
linearLayout.addView(errorTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 0, 24, 0));
negativeButton = new Button(context);
negativeButton.setGravity(Gravity.CENTER);
negativeButton.setTextColor(Theme.getColor(Theme.key_dialogButton));
negativeButton.setText(LocaleController.getString("Cancel", R.string.Cancel));
negativeButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
negativeButton.setSingleLine(true);
negativeButton.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0);
negativeButton.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(Theme.getColor(Theme.key_dialogButton)));
linearLayout.addView(negativeButton, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36, 14, 42, 0, 14));
negativeButton.setOnClickListener(v -> builder.getDismissRunnable().run());
parentFragment.showDialog(bottomSheet = builder.create(), dialog -> {
if (cancellationSignal != null) {
cancellationSignal.cancel();
cancellationSignal = null;
}
bottomSheet = null;
});
FingerprintManager fingerprintManager = getFingerprintManagerOrNull();
if (fingerprintManager != null) {
fingerprintManager.authenticate(new FingerprintManager.CryptoObject(cipher), cancellationSignal, 0, new FingerprintManager.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
if (errorCode == FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED) {
bottomSheet.dismiss();
} else {
updateState(STATE_ERROR);
showTemporaryMessage(errString);
}
}
@Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
updateState(STATE_ERROR);
showTemporaryMessage(helpString);
}
@Override
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
builder.getDismissRunnable().run();
callback.run(result.getCryptoObject().getCipher());
}
@Override
public void onAuthenticationFailed() {
updateState(STATE_ERROR);
showTemporaryMessage(LocaleController.getString("WalletTouchFingerprintNotRecognized", R.string.WalletTouchFingerprintNotRecognized));
}
}, null);
}
updateState(STATE_AUTHENTICATING);
errorTextView.setText(LocaleController.getString("WalletTouchFingerprint", R.string.WalletTouchFingerprint));
errorTextView.setVisibility(View.VISIBLE);
}
}
private void updateState(int newState) {
if (newState == STATE_PENDING_CONFIRMATION) {
AndroidUtilities.cancelRunOnUIThread(resetRunnable);
errorTextView.setVisibility(View.INVISIBLE);
} else if (newState == STATE_AUTHENTICATED) {
negativeButton.setVisibility(View.GONE);
errorTextView.setVisibility(View.INVISIBLE);
}
updateIcon(currentState, newState);
currentState = newState;
}
private void showTemporaryMessage(CharSequence message) {
AndroidUtilities.cancelRunOnUIThread(resetRunnable);
errorTextView.setText(message);
errorTextView.setTextColor(Theme.getColor(Theme.key_dialogTextRed2));
errorTextView.setContentDescription(message);
AndroidUtilities.runOnUIThread(resetRunnable, 2000);
}
private void handleResetMessage() {
if (errorTextView == null) {
return;
}
updateState(STATE_AUTHENTICATING);
errorTextView.setText(LocaleController.getString("WalletTouchFingerprint", R.string.WalletTouchFingerprint));
errorTextView.setTextColor(Theme.getColor(Theme.key_dialogButton));
}
private void updateIcon(int lastState, int newState) {
if (Build.VERSION.SDK_INT < 21) {
return;
}
final Drawable icon = getAnimationForTransition(lastState, newState);
if (icon == null) {
return;
}
final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable ? (AnimatedVectorDrawable) icon : null;
iconImageView.setImageDrawable(icon);
if (animation != null && shouldAnimateForTransition(lastState, newState)) {
animation.start();
}
}
private boolean shouldAnimateForTransition(int oldState, int newState) {
if (newState == STATE_ERROR) {
return true;
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
return true;
} else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
return false;
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
return false;
} else if (newState == STATE_AUTHENTICATING) {
return false;
}
return false;
}
private Drawable getAnimationForTransition(int oldState, int newState) {
if (parentFragment == null || parentFragment.getParentActivity() == null || Build.VERSION.SDK_INT < 21) {
return null;
}
int iconRes;
if (newState == STATE_ERROR) {
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATING) {
iconRes = R.drawable.fingerprint_dialog_error_to_fp;
} else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
} else if (newState == STATE_AUTHENTICATING) {
iconRes = R.drawable.fingerprint_dialog_fp_to_error;
} else {
return null;
}
return parentFragment.getParentActivity().getDrawable(iconRes);
}
public void onPause() {
if (bottomSheet != null) {
bottomSheet.dismiss();
bottomSheet = null;
}
if (cancellationSignal != null) {
cancellationSignal.cancel();
cancellationSignal = null;
}
}
public void cancelPromt() {
cancellationSignal.cancel();
cancellationSignal = null;
}
private static FingerprintManager getFingerprintManagerOrNull() {
if (Build.VERSION.SDK_INT == 23) {
return ApplicationLoader.applicationContext.getSystemService(FingerprintManager.class);
} else if (Build.VERSION.SDK_INT > 23 && ApplicationLoader.applicationContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
return ApplicationLoader.applicationContext.getSystemService(FingerprintManager.class);
} else {
return null;
}
}
public static boolean hasBiometricEnrolled() {
if (Build.VERSION.SDK_INT >= 29 && !shouldUseFingerprintForCrypto()) {
BiometricManager biometricManager = ApplicationLoader.applicationContext.getSystemService(android.hardware.biometrics.BiometricManager.class);
return biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS;
} else if (Build.VERSION.SDK_INT >= 23) {
FingerprintManager fingerprintManager = getFingerprintManagerOrNull();
return fingerprintManager != null && fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints();
}
return false;
}
public static boolean canAddBiometric() {
if (Build.VERSION.SDK_INT >= 29 && !shouldUseFingerprintForCrypto()) {
BiometricManager biometricManager = ApplicationLoader.applicationContext.getSystemService(android.hardware.biometrics.BiometricManager.class);
return biometricManager.canAuthenticate() != BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
}
return hasFingerprintHardware();
}
public static boolean hasFingerprintHardware() {
if (Build.VERSION.SDK_INT >= 23) {
FingerprintManager fingerprintManager = getFingerprintManagerOrNull();
return fingerprintManager != null && fingerprintManager.isHardwareDetected();
}
return false;
}
public static boolean hasLockscreenProtected() {
if (Build.VERSION.SDK_INT >= 23) {
KeyguardManager keyguardManager = (KeyguardManager) ApplicationLoader.applicationContext.getSystemService(Context.KEYGUARD_SERVICE);
return keyguardManager.isDeviceSecure();
}
return false;
}
public static void askForBiometric(BaseFragment fragment, ContinueCallback callback, String continueButton) {
if (fragment == null || fragment.getParentActivity() == null || callback == null) {
return;
}
boolean hasBiometric = hasBiometricEnrolled();
if (hasBiometric || Build.VERSION.SDK_INT < 23 || hasLockscreenProtected() && !hasFingerprintHardware()) {
callback.run(hasBiometric);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity());
builder.setTitle(LocaleController.getString("WalletSecurityAlertTitle", R.string.WalletSecurityAlertTitle));
boolean biometricOnly;
if (hasLockscreenProtected()) {
builder.setMessage(LocaleController.getString("WalletSecurityAlertTextBiometric", R.string.WalletSecurityAlertTextBiometric));
biometricOnly = true;
} else if (hasFingerprintHardware()) {
builder.setMessage(LocaleController.getString("WalletSecurityAlertTextLockscreenBiometric", R.string.WalletSecurityAlertTextLockscreenBiometric));
biometricOnly = false;
} else {
builder.setMessage(LocaleController.getString("WalletSecurityAlertTextLockscreen", R.string.WalletSecurityAlertTextLockscreen));
biometricOnly = false;
}
builder.setPositiveButton(LocaleController.getString("WalletSecurityAlertSetup", R.string.WalletSecurityAlertSetup), (dialog, which) -> {
try {
if (biometricOnly && Build.VERSION.SDK_INT >= 28) {
fragment.getParentActivity().startActivity(new Intent(Settings.ACTION_FINGERPRINT_ENROLL));
} else {
fragment.getParentActivity().startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
}
} catch (Exception e) {
FileLog.e(e);
}
});
builder.setNegativeButton(continueButton, (dialog, which) -> callback.run(false));
fragment.showDialog(builder.create());
}
}
final static String[] badBiometricModels = new String[]{
"SM-G95",
"SM-G96",
"SM-G97",
"SM-N95",
"SM-N96",
"SM-N97",
"SM-A20"
};
final static String[] hideBiometricModels = new String[]{
"SM-G97",
"SM-N97"
};
private static boolean shouldHideBiometric() {
return isModelInList(Build.MODEL, hideBiometricModels);
}
private static boolean shouldUseFingerprintForCrypto() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P || Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
return false;
}
return isModelInList(Build.MODEL, badBiometricModels);
}
private static boolean isModelInList(String deviceModel, String[] list) {
if (deviceModel == null) {
return false;
}
for (int a = 0; a < list.length; a++) {
if (deviceModel.startsWith(list[a])) {
return true;
}
}
return false;
}
}

View File

@ -12,7 +12,6 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.DispatchQueue;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.Utilities; import org.telegram.messenger.Utilities;
import org.telegram.ui.ActionBar.BackDrawable;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
import static android.graphics.Canvas.ALL_SAVE_FLAG; import static android.graphics.Canvas.ALL_SAVE_FLAG;
@ -134,11 +133,11 @@ public class BlurBehindDrawable {
blurCanvas[i].scale(1f / DOWN_SCALE, 1f / DOWN_SCALE, 0, 0); blurCanvas[i].scale(1f / DOWN_SCALE, 1f / DOWN_SCALE, 0, 0);
Drawable backDrawable = behindView.getBackground(); Drawable backDrawable = behindView.getBackground();
if (backDrawable == null) { if (backDrawable == null) {
backDrawable = Theme.getCachedWallpaperNonBlocking();; backDrawable = Theme.getCachedWallpaperNonBlocking();
} }
behindView.setTag(TAG_DRAWING_AS_BACKGROUND, i); behindView.setTag(TAG_DRAWING_AS_BACKGROUND, i);
if (i == STATIC_CONTENT) { if (i == STATIC_CONTENT) {
blurCanvas[i].translate(0,-panTranslationY); blurCanvas[i].translate(0, -panTranslationY);
behindView.draw(blurCanvas[i]); behindView.draw(blurCanvas[i]);
} }
@ -225,14 +224,16 @@ public class BlurBehindDrawable {
blurBackgroundTask.canceled = true; blurBackgroundTask.canceled = true;
blurBackgroundTask = new BlurBackgroundTask(); blurBackgroundTask = new BlurBackgroundTask();
for (int i = 0; i < 2; i ++) { for (int i = 0; i < 2; i++) {
int lastH = parentView.getMeasuredHeight(); int lastH = parentView.getMeasuredHeight();
int lastW = parentView.getMeasuredWidth(); int lastW = parentView.getMeasuredWidth();
toolbarH = AndroidUtilities.statusBarHeight + AndroidUtilities.dp(100); toolbarH = AndroidUtilities.statusBarHeight + AndroidUtilities.dp(100);
int h = i == 0 ? toolbarH : lastH; int h = i == 0 ? toolbarH : lastH;
if (bitmap[i].getHeight() != h || bitmap[i].getWidth() != parentView.getMeasuredWidth()) { if (bitmap[i].getHeight() != h || bitmap[i].getWidth() != parentView.getMeasuredWidth()) {
queue.cleanupQueue(); if (queue != null) {
queue.cleanupQueue();
}
blurredBitmapTmp[i] = Bitmap.createBitmap((int) (lastW / DOWN_SCALE), (int) (h / DOWN_SCALE), Bitmap.Config.ARGB_8888); blurredBitmapTmp[i] = Bitmap.createBitmap((int) (lastW / DOWN_SCALE), (int) (h / DOWN_SCALE), Bitmap.Config.ARGB_8888);
blurCanvas[i] = new Canvas(blurredBitmapTmp[i]); blurCanvas[i] = new Canvas(blurredBitmapTmp[i]);
@ -245,11 +246,11 @@ public class BlurBehindDrawable {
blurCanvas[i].scale(1f / DOWN_SCALE, 1f / DOWN_SCALE, 0, 0); blurCanvas[i].scale(1f / DOWN_SCALE, 1f / DOWN_SCALE, 0, 0);
Drawable backDrawable = behindView.getBackground(); Drawable backDrawable = behindView.getBackground();
if (backDrawable == null) { if (backDrawable == null) {
backDrawable = Theme.getCachedWallpaperNonBlocking();; backDrawable = Theme.getCachedWallpaperNonBlocking();
} }
behindView.setTag(TAG_DRAWING_AS_BACKGROUND, i); behindView.setTag(TAG_DRAWING_AS_BACKGROUND, i);
if (i == STATIC_CONTENT) { if (i == STATIC_CONTENT) {
blurCanvas[i].translate(0,-panTranslationY); blurCanvas[i].translate(0, -panTranslationY);
behindView.draw(blurCanvas[i]); behindView.draw(blurCanvas[i]);
} }

View File

@ -48,7 +48,6 @@ import android.text.StaticLayout;
import android.text.TextPaint; import android.text.TextPaint;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.style.ImageSpan; import android.text.style.ImageSpan;
import android.text.style.ReplacementSpan;
import android.util.Property; import android.util.Property;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.ActionMode; import android.view.ActionMode;
@ -133,9 +132,6 @@ import tw.nekomimi.nekogram.utils.AlertUtil;
public class ChatActivityEnterView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate { public class ChatActivityEnterView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierFrameLayout.SizeNotifierFrameLayoutDelegate, StickersAlert.StickersAlertDelegate {
private float circleAlpha1 = 0.4f;
private float circleAlpha2 = 0.3f;
public interface ChatActivityEnterViewDelegate { public interface ChatActivityEnterViewDelegate {
void onMessageSend(CharSequence message, boolean notify, int scheduleDate); void onMessageSend(CharSequence message, boolean notify, int scheduleDate);
void needSendTyping(); void needSendTyping();
@ -169,6 +165,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
void onAudioVideoInterfaceUpdated(); void onAudioVideoInterfaceUpdated();
default void bottomPanelTranslationYChanged(float translation) { default void bottomPanelTranslationYChanged(float translation) {
}
default void prepareMessageSending() {
} }
} }
@ -300,8 +299,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
private ImageView doneButtonImage; private ImageView doneButtonImage;
private AnimatorSet doneButtonAnimation; private AnimatorSet doneButtonAnimation;
private ContextProgressView doneButtonProgress; private ContextProgressView doneButtonProgress;
private View topView; protected View topView;
private View topLineView; protected View topLineView;
private BotKeyboardView botKeyboardView; private BotKeyboardView botKeyboardView;
private ImageView notifyButton; private ImageView notifyButton;
private ImageView scheduledButton; private ImageView scheduledButton;
@ -313,6 +312,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
private MediaActionDrawable playPauseDrawable; private MediaActionDrawable playPauseDrawable;
private int searchingType; private int searchingType;
private Runnable focusRunnable; private Runnable focusRunnable;
protected float topViewEnterProgress;
protected int animatedTop;
private ValueAnimator currentTopViewAnimation;
private boolean destroyed; private boolean destroyed;
@ -376,21 +378,24 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
private TLRPC.WebPage messageWebPage; private TLRPC.WebPage messageWebPage;
private boolean messageWebPageSearch = true; private boolean messageWebPageSearch = true;
private ChatActivityEnterViewDelegate delegate; private ChatActivityEnterViewDelegate delegate;
private TrendingStickersAlert trendingStickersAlert;
private TLRPC.TL_document audioToSend; private TLRPC.TL_document audioToSend;
private String audioToSendPath; private String audioToSendPath;
private MessageObject audioToSendMessageObject; private MessageObject audioToSendMessageObject;
private VideoEditedInfo videoToSendMessageObject; private VideoEditedInfo videoToSendMessageObject;
private boolean topViewShowed; protected boolean topViewShowed;
private boolean needShowTopView; private boolean needShowTopView;
private boolean allowShowTopView; private boolean allowShowTopView;
private AnimatorSet currentTopViewAnimation;
private MessageObject pendingMessageObject; private MessageObject pendingMessageObject;
private TLRPC.KeyboardButton pendingLocationButton; private TLRPC.KeyboardButton pendingLocationButton;
private boolean configAnimationsEnabled; private boolean configAnimationsEnabled;
private boolean waitingForKeyboardOpen; private boolean waitingForKeyboardOpen;
private boolean wasSendTyping; private boolean wasSendTyping;
private Runnable openKeyboardRunnable = new Runnable() { private Runnable openKeyboardRunnable = new Runnable() {
@ -760,6 +765,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
private float wavesEnterAnimation = 0f; private float wavesEnterAnimation = 0f;
private boolean showWaves = true; private boolean showWaves = true;
private Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
public RecordCircle(Context context) { public RecordCircle(Context context) {
super(context); super(context);
micDrawable = getResources().getDrawable(R.drawable.input_mic_pressed).mutate(); micDrawable = getResources().getDrawable(R.drawable.input_mic_pressed).mutate();
@ -1225,7 +1232,6 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
path.lineTo(0, 0); path.lineTo(0, 0);
path.lineTo(AndroidUtilities.dpf2(5), AndroidUtilities.dpf2(4)); path.lineTo(AndroidUtilities.dpf2(5), AndroidUtilities.dpf2(4));
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.WHITE); p.setColor(Color.WHITE);
p.setAlpha(alphaInt); p.setAlpha(alphaInt);
p.setStyle(Paint.Style.STROKE); p.setStyle(Paint.Style.STROKE);
@ -1774,8 +1780,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
float radiusDiff = AndroidUtilities.dp(10) + AndroidUtilities.dp(50) * WAVE_ANGLE * animateToAmplitude; float radiusDiff = AndroidUtilities.dp(10) + AndroidUtilities.dp(50) * WAVE_ANGLE * animateToAmplitude;
circleBezierDrawable.idleStateDiff = idleRadius * circleBezierDrawable.idleStateDiff = idleRadius * (1f - waveAmplitude);
(1f - waveAmplitude);
float kDiff = 0.35f * waveAmplitude * waveDif; float kDiff = 0.35f * waveAmplitude * waveDif;
circleBezierDrawable.radiusDiff = radiusDiff * kDiff; circleBezierDrawable.radiusDiff = radiusDiff * kDiff;
@ -1926,7 +1931,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
public InputConnection onCreateInputConnection(EditorInfo editorInfo) { public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
final InputConnection ic = super.onCreateInputConnection(editorInfo); final InputConnection ic = super.onCreateInputConnection(editorInfo);
try { try {
EditorInfoCompat.setContentMimeTypes(editorInfo, new String[]{"image/gif", "image/*", "image/jpg", "image/png"}); EditorInfoCompat.setContentMimeTypes(editorInfo, new String[]{"image/gif", "image/*", "image/jpg", "image/png", "image/webp"});
final InputConnectionCompat.OnCommitContentListener callback = (inputContentInfo, flags, opts) -> { final InputConnectionCompat.OnCommitContentListener callback = (inputContentInfo, flags, opts) -> {
if (BuildCompat.isAtLeastNMR1() && (flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) { if (BuildCompat.isAtLeastNMR1() && (flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
@ -2838,11 +2843,19 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
animatorSet.start(); animatorSet.start();
} }
public int getBackgroundTop() {
int t = getTop();
if (topView != null && topView.getVisibility() == View.VISIBLE) {
t += topView.getLayoutParams().height;
}
return t;
}
@Override @Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) { protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (child == topView) { if (child == topView) {
canvas.save(); canvas.save();
canvas.clipRect(0, 0, getMeasuredWidth(), child.getLayoutParams().height + AndroidUtilities.dp(2)); canvas.clipRect(0, animatedTop, getMeasuredWidth(), animatedTop + child.getLayoutParams().height + AndroidUtilities.dp(2));
} }
boolean result = super.drawChild(canvas, child, drawingTime); boolean result = super.drawChild(canvas, child, drawingTime);
if (child == topView) { if (child == topView) {
@ -2853,8 +2866,12 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
@Override @Override
protected void onDraw(Canvas canvas) { protected void onDraw(Canvas canvas) {
int top = topView != null && topView.getVisibility() == VISIBLE ? (int) topView.getTranslationY() : 0; int top = animatedTop;
if (topView != null && topView.getVisibility() == View.VISIBLE) {
top += (1f - topViewEnterProgress) * topView.getLayoutParams().height;
}
int bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); int bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight();
Theme.chat_composeShadowDrawable.setBounds(0, top, getMeasuredWidth(), bottom); Theme.chat_composeShadowDrawable.setBounds(0, top, getMeasuredWidth(), bottom);
Theme.chat_composeShadowDrawable.draw(canvas); Theme.chat_composeShadowDrawable.draw(canvas);
canvas.drawRect(0, bottom, getWidth(), getHeight(), Theme.chat_composeBackgroundPaint); canvas.drawRect(0, bottom, getWidth(), getHeight(), Theme.chat_composeBackgroundPaint);
@ -3114,6 +3131,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
topView = view; topView = view;
topView.setVisibility(GONE); topView.setVisibility(GONE);
topViewEnterProgress = 0f;
topView.setTranslationY(height); topView.setTranslationY(height);
addView(topView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, height, Gravity.TOP | Gravity.LEFT, 0, 2, 0, 0)); addView(topView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, height, Gravity.TOP | Gravity.LEFT, 0, 2, 0, 0));
needShowTopView = false; needShowTopView = false;
@ -3148,6 +3166,17 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
emojiView.switchToGifRecent(); emojiView.switchToGifRecent();
} }
private final ValueAnimator.AnimatorUpdateListener topViewUpdateListener = animation -> {
if (topView != null) {
float v = (float) animation.getAnimatedValue();
topViewEnterProgress = v;
topView.setTranslationY(animatedTop + (1f - v) * topView.getLayoutParams().height);
topLineView.setAlpha(v);
topLineView.setTranslationY(animatedTop);
}
};
public void showTopView(boolean animated, final boolean openKeyboard) { public void showTopView(boolean animated, final boolean openKeyboard) {
if (topView == null || topViewShowed || getVisibility() != VISIBLE) { if (topView == null || topViewShowed || getVisibility() != VISIBLE) {
if (recordedAudioPanel.getVisibility() != VISIBLE && (!forceShowSendButton || openKeyboard)) { if (recordedAudioPanel.getVisibility() != VISIBLE && (!forceShowSendButton || openKeyboard)) {
@ -3166,10 +3195,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
} }
resizeForTopView(true); resizeForTopView(true);
if (animated) { if (animated) {
currentTopViewAnimation = new AnimatorSet(); currentTopViewAnimation = ValueAnimator.ofFloat(topViewEnterProgress, 1f);
currentTopViewAnimation.playTogether( currentTopViewAnimation.addUpdateListener(topViewUpdateListener);
ObjectAnimator.ofFloat(topView, View.TRANSLATION_Y, 0),
ObjectAnimator.ofFloat(topLineView, View.ALPHA, 1.0f));
currentTopViewAnimation.addListener(new AnimatorListenerAdapter() { currentTopViewAnimation.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
@ -3182,6 +3209,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
currentTopViewAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); currentTopViewAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT);
currentTopViewAnimation.start(); currentTopViewAnimation.start();
} else { } else {
topViewEnterProgress = 1f;
topView.setTranslationY(0); topView.setTranslationY(0);
topLineView.setAlpha(1.0f); topLineView.setAlpha(1.0f);
} }
@ -3283,10 +3311,8 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
currentTopViewAnimation = null; currentTopViewAnimation = null;
} }
if (animated) { if (animated) {
currentTopViewAnimation = new AnimatorSet(); currentTopViewAnimation = ValueAnimator.ofFloat(topViewEnterProgress, 0);
currentTopViewAnimation.playTogether( currentTopViewAnimation.addUpdateListener(topViewUpdateListener);
ObjectAnimator.ofFloat(topView, View.TRANSLATION_Y, topView.getLayoutParams().height),
ObjectAnimator.ofFloat(topLineView, View.ALPHA, 0.0f));
currentTopViewAnimation.addListener(new AnimatorListenerAdapter() { currentTopViewAnimation.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
@ -3305,10 +3331,12 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
} }
} }
}); });
currentTopViewAnimation.setDuration(200); currentTopViewAnimation.setDuration(220);
currentTopViewAnimation.setStartDelay(50);
currentTopViewAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); currentTopViewAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT);
currentTopViewAnimation.start(); currentTopViewAnimation.start();
} else { } else {
topViewEnterProgress = 0f;
topView.setVisibility(GONE); topView.setVisibility(GONE);
topLineView.setVisibility(GONE); topLineView.setVisibility(GONE);
topLineView.setAlpha(0.0f); topLineView.setAlpha(0.0f);
@ -3339,6 +3367,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
topLineView.setVisibility(GONE); topLineView.setVisibility(GONE);
topLineView.setAlpha(0.0f); topLineView.setAlpha(0.0f);
resizeForTopView(false); resizeForTopView(false);
topViewEnterProgress = 0f;
topView.setTranslationY(topView.getLayoutParams().height); topView.setTranslationY(topView.getLayoutParams().height);
} }
} }
@ -3350,6 +3379,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
topLineView.setVisibility(VISIBLE); topLineView.setVisibility(VISIBLE);
topLineView.setAlpha(1.0f); topLineView.setAlpha(1.0f);
resizeForTopView(true); resizeForTopView(true);
topViewEnterProgress = 1f;
topView.setTranslationY(0); topView.setTranslationY(0);
} }
} }
@ -3841,6 +3871,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
boolean supportsNewEntities = supportsSendingNewEntities(); boolean supportsNewEntities = supportsSendingNewEntities();
int maxLength = accountInstance.getMessagesController().maxMessageLength; int maxLength = accountInstance.getMessagesController().maxMessageLength;
if (text.length() != 0) { if (text.length() != 0) {
if (delegate != null && parentFragment != null && (scheduleDate != 0) == parentFragment.isInScheduleMode()) {
delegate.prepareMessageSending();
}
int count = (int) Math.ceil(text.length() / (float) maxLength); int count = (int) Math.ceil(text.length() / (float) maxLength);
for (int a = 0; a < count; a++) { for (int a = 0; a < count; a++) {
CharSequence[] message = new CharSequence[]{text.subSequence(a * maxLength, Math.min((a + 1) * maxLength, text.length()))}; CharSequence[] message = new CharSequence[]{text.subSequence(a * maxLength, Math.min((a + 1) * maxLength, text.length()))};
@ -4470,8 +4503,6 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
if (animation.equals(runningAnimation)) { if (animation.equals(runningAnimation)) {
sendButton.setVisibility(GONE);
cancelBotButton.setVisibility(GONE);
setSlowModeButtonVisible(false); setSlowModeButtonVisible(false);
runningAnimation = null; runningAnimation = null;
runningAnimationType = 0; runningAnimationType = 0;
@ -5396,6 +5427,10 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
return emojiView; return emojiView;
} }
public TrendingStickersAlert getTrendingStickersAlert() {
return trendingStickersAlert;
}
public void updateColors() { public void updateColors() {
if (emojiView != null) { if (emojiView != null) {
emojiView.updateColors(); emojiView.updateColors();
@ -5758,7 +5793,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
if (button instanceof TLRPC.TL_keyboardButton) { if (button instanceof TLRPC.TL_keyboardButton) {
SendMessagesHelper.getInstance(currentAccount).sendMessage(button.text, dialog_id, replyMessageObject, null, false, null, null, null, true, 0); SendMessagesHelper.getInstance(currentAccount).sendMessage(button.text, dialog_id, replyMessageObject, null, false, null, null, null, true, 0);
} else if (button instanceof TLRPC.TL_keyboardButtonUrl) { } else if (button instanceof TLRPC.TL_keyboardButtonUrl) {
parentFragment.showOpenUrlAlert(button.url, false, true); AlertsCreator.showOpenUrlAlert(parentFragment, button.url, false, true);
} else if (button instanceof TLRPC.TL_keyboardButtonRequestPhone) { } else if (button instanceof TLRPC.TL_keyboardButtonRequestPhone) {
parentFragment.shareMyContact(2, messageObject); parentFragment.shareMyContact(2, messageObject);
} else if (button instanceof TLRPC.TL_keyboardButtonRequestPoll) { } else if (button instanceof TLRPC.TL_keyboardButtonRequestPoll) {
@ -5871,8 +5906,6 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
emojiView.setVisibility(GONE); emojiView.setVisibility(GONE);
emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { emojiView.setDelegate(new EmojiView.EmojiViewDelegate() {
private TrendingStickersAlert trendingStickersAlert;
@Override @Override
public boolean onBackspace() { public boolean onBackspace() {
if (messageEditText.length() == 0) { if (messageEditText.length() == 0) {
@ -5973,6 +6006,7 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
HashMap<String, String> params = new HashMap<>(); HashMap<String, String> params = new HashMap<>();
params.put("id", result.id); params.put("id", result.id);
params.put("query_id", "" + result.query_id); params.put("query_id", "" + result.query_id);
params.put("force_gif", "1");
SendMessagesHelper.prepareSendingBotContextResult(accountInstance, result, params, dialog_id, replyingMessageObject, notify, scheduleDate); SendMessagesHelper.prepareSendingBotContextResult(accountInstance, result, params, dialog_id, replyingMessageObject, notify, scheduleDate);
@ -6087,7 +6121,9 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
@Override @Override
public void dismiss() { public void dismiss() {
super.dismiss(); super.dismiss();
trendingStickersAlert = null; if (trendingStickersAlert == this) {
trendingStickersAlert = null;
}
} }
}; };
trendingStickersAlert.show(); trendingStickersAlert.show();
@ -6456,6 +6492,17 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
emojiButtonAnimation.setDuration(150); emojiButtonAnimation.setDuration(150);
emojiButtonAnimation.start(); emojiButtonAnimation.start();
} }
onEmojiIconChanged(nextIcon);
}
protected void onEmojiIconChanged(int currentIcon) {
if (currentIcon == 3 && emojiView == null) {
MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_IMAGE, true, true, false);
final ArrayList<String> gifSearchEmojies = MessagesController.getInstance(currentAccount).gifSearchEmojies;
for (int i = 0, N = Math.min(10, gifSearchEmojies.size()); i < N; i++) {
Emoji.preloadEmoji(gifSearchEmojies.get(i));
}
}
} }
public void hidePopup(boolean byBackButton) { public void hidePopup(boolean byBackButton) {
@ -7526,17 +7573,4 @@ public class ChatActivityEnterView extends FrameLayout implements NotificationCe
stoppedInternal = false; stoppedInternal = false;
} }
} }
private static class EmptyStubSpan extends ReplacementSpan {
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) {
return (int) paint.measureText(text, start, end);
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
}
}
} }

View File

@ -95,6 +95,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
void didSelectBot(TLRPC.User user); void didSelectBot(TLRPC.User user);
void onCameraOpened(); void onCameraOpened();
void needEnterComment(); void needEnterComment();
void doOnIdle(Runnable runnable);
} }
public float translationProgress; public float translationProgress;
@ -571,7 +572,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
ignoreLayout = false; ignoreLayout = false;
} }
int availableHeight = totalHeight - getPaddingTop(); int availableHeight = totalHeight - getPaddingTop();
int keyboardSize = useSmoothKeyboard ? 0 : getKeyboardHeight(); int keyboardSize = useSmoothKeyboard ? 0 : measureKeyboardHeight();
if (!AndroidUtilities.isInMultiwindow && keyboardSize <= AndroidUtilities.dp(20)) { if (!AndroidUtilities.isInMultiwindow && keyboardSize <= AndroidUtilities.dp(20)) {
availableHeight -= commentTextView.getEmojiPadding(); availableHeight -= commentTextView.getEmojiPadding();
} }
@ -612,7 +613,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
setMeasuredDimension(widthSize, heightSize); setMeasuredDimension(widthSize, heightSize);
widthSize -= backgroundPaddingLeft * 2; widthSize -= backgroundPaddingLeft * 2;
int keyboardSize = useSmoothKeyboard ? 0 : getKeyboardHeight(); int keyboardSize = useSmoothKeyboard ? 0 : measureKeyboardHeight();
if (keyboardSize <= AndroidUtilities.dp(20)) { if (keyboardSize <= AndroidUtilities.dp(20)) {
if (!AndroidUtilities.isInMultiwindow) { if (!AndroidUtilities.isInMultiwindow) {
heightSize -= commentTextView.getEmojiPadding(); heightSize -= commentTextView.getEmojiPadding();
@ -661,7 +662,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
setSystemGestureExclusionRects(exclusionRects); setSystemGestureExclusionRects(exclusionRects);
} }
int keyboardSize = useSmoothKeyboard ? 0 : getKeyboardHeight(); int keyboardSize = useSmoothKeyboard ? 0 : measureKeyboardHeight();
int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.getEmojiPadding() : 0; int paddingBottom = keyboardSize <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isTablet() ? commentTextView.getEmojiPadding() : 0;
setBottomClip(paddingBottom); setBottomClip(paddingBottom);
@ -969,10 +970,11 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
} else { } else {
info.searchImage = searchImage; info.searchImage = searchImage;
} }
info.thumbPath = searchImage.thumbPath;
info.videoEditedInfo = searchImage.editedInfo;
info.caption = searchImage.caption != null ? searchImage.caption.toString() : null; info.caption = searchImage.caption != null ? searchImage.caption.toString() : null;
info.entities = searchImage.entities; info.entities = searchImage.entities;
info.masks = !searchImage.stickers.isEmpty() ? new ArrayList<>(searchImage.stickers) : null; info.masks = searchImage.stickers;
info.ttl = searchImage.ttl; info.ttl = searchImage.ttl;
if (searchImage.inlineResult != null && searchImage.type == 1) { if (searchImage.inlineResult != null && searchImage.type == 1) {
info.inlineResult = searchImage.inlineResult; info.inlineResult = searchImage.inlineResult;
@ -1027,7 +1029,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
shadow = new View(context); shadow = new View(context);
shadow.setBackgroundResource(R.drawable.attach_shadow); shadow.setBackgroundResource(R.drawable.attach_shadow);
shadow.getBackground().setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); shadow.getBackground().setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN));
containerView.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 84)); containerView.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 84));
buttonsRecyclerView = new RecyclerListView(context) { buttonsRecyclerView = new RecyclerListView(context) {
@ -1339,6 +1341,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
public void show() { public void show() {
super.show(); super.show();
buttonPressed = false; buttonPressed = false;
if (baseFragment instanceof ChatActivity) {
ChatActivity chatActivity = (ChatActivity) baseFragment;
calcMandatoryInsets = chatActivity.isKeyboardVisible();
}
} }
public void setEditingMessageObject(MessageObject messageObject) { public void setEditingMessageObject(MessageObject messageObject) {
@ -1899,7 +1905,6 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
return; return;
} }
int newOffset = layout.getCurrentItemTop(); int newOffset = layout.getCurrentItemTop();
FileLog.d(layout + " offset = " + newOffset);
if (newOffset == Integer.MAX_VALUE) { if (newOffset == Integer.MAX_VALUE) {
return; return;
} }
@ -2146,7 +2151,6 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
@Override @Override
public void onOpenAnimationEnd() { public void onOpenAnimationEnd() {
NotificationCenter.getInstance(currentAccount).setAnimationInProgress(false);
MediaController.AlbumEntry albumEntry; MediaController.AlbumEntry albumEntry;
if (baseFragment instanceof ChatActivity) { if (baseFragment instanceof ChatActivity) {
albumEntry = MediaController.allMediaAlbumEntry; albumEntry = MediaController.allMediaAlbumEntry;
@ -2328,6 +2332,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
@Override @Override
public void dismissInternal() { public void dismissInternal() {
delegate.doOnIdle(this::removeFromRoot);
}
private void removeFromRoot() {
if (containerView != null) { if (containerView != null) {
containerView.setVisibility(View.INVISIBLE); containerView.setVisibility(View.INVISIBLE);
} }

View File

@ -145,7 +145,7 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou
emptyImageView = new ImageView(context); emptyImageView = new ImageView(context);
emptyImageView.setImageResource(R.drawable.music_empty); emptyImageView.setImageResource(R.drawable.music_empty);
emptyImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogEmptyImage), PorterDuff.Mode.MULTIPLY)); emptyImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogEmptyImage), PorterDuff.Mode.SRC_IN));
emptyView.addView(emptyImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); emptyView.addView(emptyImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
emptyTitleTextView = new TextView(context); emptyTitleTextView = new TextView(context);
@ -336,7 +336,7 @@ public class ChatAttachAlertAudioLayout extends ChatAttachAlert.AttachAlertLayou
@Override @Override
void onPreMeasure(int availableWidth, int availableHeight) { void onPreMeasure(int availableWidth, int availableHeight) {
int padding; int padding;
if (parentAlert.sizeNotifierFrameLayout.getKeyboardHeight() > AndroidUtilities.dp(20)) { if (parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20)) {
padding = AndroidUtilities.dp(8); padding = AndroidUtilities.dp(8);
parentAlert.setAllowNestedScroll(false); parentAlert.setAllowNestedScroll(false);
} else { } else {

View File

@ -420,7 +420,7 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa
@Override @Override
void onPreMeasure(int availableWidth, int availableHeight) { void onPreMeasure(int availableWidth, int availableHeight) {
int padding; int padding;
if (parentAlert.sizeNotifierFrameLayout.getKeyboardHeight() > AndroidUtilities.dp(20)) { if (parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20)) {
padding = AndroidUtilities.dp(8); padding = AndroidUtilities.dp(8);
parentAlert.setAllowNestedScroll(false); parentAlert.setAllowNestedScroll(false);
} else { } else {

View File

@ -466,7 +466,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa
@Override @Override
void onPreMeasure(int availableWidth, int availableHeight) { void onPreMeasure(int availableWidth, int availableHeight) {
int padding; int padding;
if (parentAlert.actionBar.isSearchFieldVisible() || parentAlert.sizeNotifierFrameLayout.getKeyboardHeight() > AndroidUtilities.dp(20)) { if (parentAlert.actionBar.isSearchFieldVisible() || parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20)) {
padding = AndroidUtilities.dp(56); padding = AndroidUtilities.dp(56);
parentAlert.setAllowNestedScroll(false); parentAlert.setAllowNestedScroll(false);
} else { } else {
@ -584,18 +584,17 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa
media.add(info); media.add(info);
if (object instanceof MediaController.PhotoEntry) { if (object instanceof MediaController.PhotoEntry) {
MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object; MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object;
if (photoEntry.isVideo) { if (photoEntry.imagePath != null) {
info.path = photoEntry.path;
info.videoEditedInfo = photoEntry.editedInfo;
} else if (photoEntry.imagePath != null) {
info.path = photoEntry.imagePath; info.path = photoEntry.imagePath;
} else if (photoEntry.path != null) { } else {
info.path = photoEntry.path; info.path = photoEntry.path;
} }
info.thumbPath = photoEntry.thumbPath;
info.videoEditedInfo = photoEntry.editedInfo;
info.isVideo = photoEntry.isVideo; info.isVideo = photoEntry.isVideo;
info.caption = photoEntry.caption != null ? photoEntry.caption.toString() : null; info.caption = photoEntry.caption != null ? photoEntry.caption.toString() : null;
info.entities = photoEntry.entities; info.entities = photoEntry.entities;
info.masks = !photoEntry.stickers.isEmpty() ? new ArrayList<>(photoEntry.stickers) : null; info.masks = photoEntry.stickers;
info.ttl = photoEntry.ttl; info.ttl = photoEntry.ttl;
} }
} }

View File

@ -261,7 +261,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
lastPressedMarkerView = new FrameLayout(context); lastPressedMarkerView = new FrameLayout(context);
lastPressedMarkerView.setBackgroundResource(R.drawable.venue_tooltip); lastPressedMarkerView.setBackgroundResource(R.drawable.venue_tooltip);
lastPressedMarkerView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); lastPressedMarkerView.getBackground().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.SRC_IN));
frameLayout.addView(lastPressedMarkerView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 71)); frameLayout.addView(lastPressedMarkerView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 71));
lastPressedMarkerView.setAlpha(0.0f); lastPressedMarkerView.setAlpha(0.0f);
lastPressedMarkerView.setOnClickListener(v -> { lastPressedMarkerView.setOnClickListener(v -> {
@ -511,7 +511,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
Drawable drawable = Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(40), Theme.getColor(Theme.key_location_actionBackground), Theme.getColor(Theme.key_location_actionPressedBackground)); Drawable drawable = Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(40), Theme.getColor(Theme.key_location_actionBackground), Theme.getColor(Theme.key_location_actionPressedBackground));
if (Build.VERSION.SDK_INT < 21) { if (Build.VERSION.SDK_INT < 21) {
Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.places_btn).mutate(); Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.places_btn).mutate();
shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN));
CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, AndroidUtilities.dp(2), AndroidUtilities.dp(2)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, AndroidUtilities.dp(2), AndroidUtilities.dp(2));
combinedDrawable.setFullsize(true); combinedDrawable.setFullsize(true);
drawable = combinedDrawable; drawable = combinedDrawable;
@ -555,7 +555,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), Theme.getColor(Theme.key_location_actionBackground), Theme.getColor(Theme.key_location_actionPressedBackground)); drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), Theme.getColor(Theme.key_location_actionBackground), Theme.getColor(Theme.key_location_actionPressedBackground));
if (Build.VERSION.SDK_INT < 21) { if (Build.VERSION.SDK_INT < 21) {
Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate();
shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN));
CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0);
combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40)); combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40));
drawable = combinedDrawable; drawable = combinedDrawable;
@ -612,7 +612,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), Theme.getColor(Theme.key_location_actionBackground), Theme.getColor(Theme.key_location_actionPressedBackground)); drawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(40), Theme.getColor(Theme.key_location_actionBackground), Theme.getColor(Theme.key_location_actionPressedBackground));
if (Build.VERSION.SDK_INT < 21) { if (Build.VERSION.SDK_INT < 21) {
Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate();
shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); shadowDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.SRC_IN));
CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, drawable, 0, 0);
combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40)); combinedDrawable.setIconSize(AndroidUtilities.dp(40), AndroidUtilities.dp(40));
drawable = combinedDrawable; drawable = combinedDrawable;
@ -632,7 +632,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
locationButton.setBackgroundDrawable(drawable); locationButton.setBackgroundDrawable(drawable);
locationButton.setImageResource(R.drawable.location_current); locationButton.setImageResource(R.drawable.location_current);
locationButton.setScaleType(ImageView.ScaleType.CENTER); locationButton.setScaleType(ImageView.ScaleType.CENTER);
locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.SRC_IN));
locationButton.setTag(Theme.key_location_actionActiveIcon); locationButton.setTag(Theme.key_location_actionActiveIcon);
locationButton.setContentDescription(LocaleController.getString("AccDescrMyLocation", R.string.AccDescrMyLocation)); locationButton.setContentDescription(LocaleController.getString("AccDescrMyLocation", R.string.AccDescrMyLocation));
FrameLayout.LayoutParams layoutParams1 = LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 40 : 44, Build.VERSION.SDK_INT >= 21 ? 40 : 44, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 12, 12); FrameLayout.LayoutParams layoutParams1 = LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 40 : 44, Build.VERSION.SDK_INT >= 21 ? 40 : 44, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 12, 12);
@ -648,7 +648,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
} }
} }
if (myLocation != null && mapView != null) { if (myLocation != null && mapView != null) {
locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.SRC_IN));
locationButton.setTag(Theme.key_location_actionActiveIcon); locationButton.setTag(Theme.key_location_actionActiveIcon);
adapter.setCustomLocation(null); adapter.setCustomLocation(null);
userLocationMoved = false; userLocationMoved = false;
@ -676,7 +676,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
emptyImageView = new ImageView(context); emptyImageView = new ImageView(context);
emptyImageView.setImageResource(R.drawable.location_empty); emptyImageView.setImageResource(R.drawable.location_empty);
emptyImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogEmptyImage), PorterDuff.Mode.MULTIPLY)); emptyImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogEmptyImage), PorterDuff.Mode.SRC_IN));
emptyView.addView(emptyImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); emptyView.addView(emptyImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
emptyTitleTextView = new TextView(context); emptyTitleTextView = new TextView(context);
@ -848,7 +848,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
} }
if (ev.getAction() == MotionEvent.ACTION_MOVE) { if (ev.getAction() == MotionEvent.ACTION_MOVE) {
if (!userLocationMoved) { if (!userLocationMoved) {
locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.SRC_IN));
locationButton.setTag(Theme.key_location_actionIcon); locationButton.setTag(Theme.key_location_actionIcon);
userLocationMoved = true; userLocationMoved = true;
} }
@ -1039,7 +1039,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
@Override @Override
void onPreMeasure(int availableWidth, int availableHeight) { void onPreMeasure(int availableWidth, int availableHeight) {
int padding; int padding;
if (parentAlert.actionBar.isSearchFieldVisible() || parentAlert.sizeNotifierFrameLayout.getKeyboardHeight() > AndroidUtilities.dp(20)) { if (parentAlert.actionBar.isSearchFieldVisible() || parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20)) {
padding = mapHeight - overScrollHeight; padding = mapHeight - overScrollHeight;
parentAlert.setAllowNestedScroll(false); parentAlert.setAllowNestedScroll(false);
} else { } else {
@ -1200,7 +1200,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa
public boolean onMarkerClick(Marker marker, MapView mapView) { public boolean onMarkerClick(Marker marker, MapView mapView) {
markerImageView.setVisibility(View.INVISIBLE); markerImageView.setVisibility(View.INVISIBLE);
if (!userLocationMoved) { if (!userLocationMoved) {
locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.MULTIPLY)); locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionIcon), PorterDuff.Mode.SRC_IN));
locationButton.setTag(Theme.key_location_actionIcon); locationButton.setTag(Theme.key_location_actionIcon);
userLocationMoved = true; userLocationMoved = true;
} }

View File

@ -17,7 +17,6 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.hardware.Camera; import android.hardware.Camera;
import android.media.MediaMetadataRetriever; import android.media.MediaMetadataRetriever;
import android.media.ThumbnailUtils;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.provider.MediaStore; import android.provider.MediaStore;
@ -50,6 +49,7 @@ import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessageObject;
import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.messenger.SendMessagesHelper;
import org.telegram.messenger.SharedConfig; import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.Utilities; import org.telegram.messenger.Utilities;
import org.telegram.messenger.VideoEditedInfo; import org.telegram.messenger.VideoEditedInfo;
@ -442,7 +442,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
dropDown.setText(LocaleController.getString("ChatGallery", R.string.ChatGallery)); dropDown.setText(LocaleController.getString("ChatGallery", R.string.ChatGallery));
dropDown.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); dropDown.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
dropDownDrawable = context.getResources().getDrawable(R.drawable.ic_arrow_drop_down).mutate(); dropDownDrawable = context.getResources().getDrawable(R.drawable.ic_arrow_drop_down).mutate();
dropDownDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogTextBlack), PorterDuff.Mode.MULTIPLY)); dropDownDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogTextBlack), PorterDuff.Mode.SRC_IN));
dropDown.setCompoundDrawablePadding(AndroidUtilities.dp(4)); dropDown.setCompoundDrawablePadding(AndroidUtilities.dp(4));
dropDown.setPadding(0, 0, AndroidUtilities.dp(10), 0); dropDown.setPadding(0, 0, AndroidUtilities.dp(10), 0);
dropDownContainer.addView(dropDown, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 16, 0, 0, 0)); dropDownContainer.addView(dropDown, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 16, 0, 0, 0));
@ -651,7 +651,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
recordTime = new TextView(context); recordTime = new TextView(context);
recordTime.setBackgroundResource(R.drawable.system); recordTime.setBackgroundResource(R.drawable.system);
recordTime.getBackground().setColorFilter(new PorterDuffColorFilter(0x66000000, PorterDuff.Mode.MULTIPLY)); recordTime.getBackground().setColorFilter(new PorterDuffColorFilter(0x66000000, PorterDuff.Mode.SRC_IN));
recordTime.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); recordTime.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
recordTime.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); recordTime.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
recordTime.setAlpha(0.0f); recordTime.setAlpha(0.0f);
@ -1836,7 +1836,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
FileLog.e(e); FileLog.e(e);
} }
} }
final Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND); final Bitmap bitmap = SendMessagesHelper.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND);
String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".jpg"; String fileName = Integer.MIN_VALUE + "_" + SharedConfig.getLastLocalId() + ".jpg";
final File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); final File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName);
try { try {
@ -2329,7 +2329,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou
gridView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); gridView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow));
RecyclerView.ViewHolder holder = gridView.findViewHolderForAdapterPosition(0); RecyclerView.ViewHolder holder = gridView.findViewHolderForAdapterPosition(0);
if (holder != null && holder.itemView instanceof PhotoAttachCameraCell) { if (holder != null && holder.itemView instanceof PhotoAttachCameraCell) {
((PhotoAttachCameraCell) holder.itemView).getImageView().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogCameraIcon), PorterDuff.Mode.MULTIPLY)); ((PhotoAttachCameraCell) holder.itemView).getImageView().setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogCameraIcon), PorterDuff.Mode.SRC_IN));
} }
dropDown.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); dropDown.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));

View File

@ -479,7 +479,7 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout
@Override @Override
void onPreMeasure(int availableWidth, int availableHeight) { void onPreMeasure(int availableWidth, int availableHeight) {
int padding; int padding;
if (parentAlert.sizeNotifierFrameLayout.getKeyboardHeight() > AndroidUtilities.dp(20)) { if (parentAlert.sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20)) {
padding = AndroidUtilities.dp(52); padding = AndroidUtilities.dp(52);
parentAlert.setAllowNestedScroll(false); parentAlert.setAllowNestedScroll(false);
} else { } else {
@ -792,8 +792,8 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout
textCell.setColors(null, Theme.key_windowBackgroundWhiteBlueText4); textCell.setColors(null, Theme.key_windowBackgroundWhiteBlueText4);
Drawable drawable1 = mContext.getResources().getDrawable(R.drawable.poll_add_circle); Drawable drawable1 = mContext.getResources().getDrawable(R.drawable.poll_add_circle);
Drawable drawable2 = mContext.getResources().getDrawable(R.drawable.poll_add_plus); Drawable drawable2 = mContext.getResources().getDrawable(R.drawable.poll_add_plus);
drawable1.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_switchTrackChecked), PorterDuff.Mode.MULTIPLY)); drawable1.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_switchTrackChecked), PorterDuff.Mode.SRC_IN));
drawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_checkboxCheck), PorterDuff.Mode.MULTIPLY)); drawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_checkboxCheck), PorterDuff.Mode.SRC_IN));
CombinedDrawable combinedDrawable = new CombinedDrawable(drawable1, drawable2); CombinedDrawable combinedDrawable = new CombinedDrawable(drawable1, drawable2);
textCell.setTextAndIcon(LocaleController.getString("AddAnOption", R.string.AddAnOption), combinedDrawable, false); textCell.setTextAndIcon(LocaleController.getString("AddAnOption", R.string.AddAnOption), combinedDrawable, false);
break; break;

View File

@ -243,7 +243,7 @@ public class CheckBoxBase {
drawBitmap.eraseColor(0); drawBitmap.eraseColor(0);
float rad = AndroidUtilities.dp(size / 2); float rad = AndroidUtilities.dp(size / 2);
float outerRad = rad; float outerRad = rad;
if (drawBackgroundAsArc != 0) { if (drawBackgroundAsArc != 0 && drawBackgroundAsArc != 11) {
outerRad -= AndroidUtilities.dp(0.2f); outerRad -= AndroidUtilities.dp(0.2f);
} }
@ -291,7 +291,7 @@ public class CheckBoxBase {
} }
paint.setColor(Theme.getColor(checkColorKey)); paint.setColor(Theme.getColor(checkColorKey));
if (drawBackgroundAsArc != 7 && drawBackgroundAsArc != 8 && drawBackgroundAsArc != 9 && drawBackgroundAsArc != 10) { if (drawBackgroundAsArc != 7 && drawBackgroundAsArc != 8 && drawBackgroundAsArc != 9 && drawBackgroundAsArc != 10) {
if (drawBackgroundAsArc == 0) { if (drawBackgroundAsArc == 0 || drawBackgroundAsArc == 11) {
canvas.drawCircle(cx, cy, rad, backgroundPaint); canvas.drawCircle(cx, cy, rad, backgroundPaint);
} else { } else {
rect.set(cx - outerRad, cy - outerRad, cx + outerRad, cy + outerRad); rect.set(cx - outerRad, cy - outerRad, cx + outerRad, cy + outerRad);
@ -330,7 +330,7 @@ public class CheckBoxBase {
if (drawBackgroundAsArc == 9) { if (drawBackgroundAsArc == 9) {
paint.setColor(Theme.getColor(background2ColorKey)); paint.setColor(Theme.getColor(background2ColorKey));
} else if (drawBackgroundAsArc == 6 || drawBackgroundAsArc == 7 || drawBackgroundAsArc == 10 || !drawUnchecked && backgroundColorKey != null) { } else if (drawBackgroundAsArc == 11 || drawBackgroundAsArc == 6 || drawBackgroundAsArc == 7 || drawBackgroundAsArc == 10 || !drawUnchecked && backgroundColorKey != null) {
paint.setColor(Theme.getColor(backgroundColorKey)); paint.setColor(Theme.getColor(backgroundColorKey));
} else { } else {
paint.setColor(Theme.getColor(enabled ? Theme.key_checkbox : Theme.key_checkboxDisabled)); paint.setColor(Theme.getColor(enabled ? Theme.key_checkbox : Theme.key_checkboxDisabled));

View File

@ -18,15 +18,15 @@ public class CircleBezierDrawable {
float globalRotate = 0f; float globalRotate = 0f;
public float idleStateDiff = 0f; public float idleStateDiff = 0f;
float radius; public float radius;
float radiusDiff; public float radiusDiff;
float cubicBezierK = 1f; public float cubicBezierK = 1f;
final Random random = new Random(); final Random random = new Random();
float[] randomAdditionals; float[] randomAdditionals;
float randomK; public float randomK;
public CircleBezierDrawable(int n) { public CircleBezierDrawable(int n) {
N = n; N = n;
@ -41,7 +41,14 @@ public class CircleBezierDrawable {
} }
} }
protected void draw(float cX, float cY, Canvas canvas, Paint paint) { public void setAdditionals(int[] additionals) {
for (int i = 0; i < N; i += 2) {
randomAdditionals[i] = additionals[i / 2];
randomAdditionals[i + 1] = 0;
}
}
public void draw(float cX, float cY, Canvas canvas, Paint paint) {
float r1 = radius - idleStateDiff / 2f - radiusDiff / 2f; float r1 = radius - idleStateDiff / 2f - radiusDiff / 2f;
float r2 = radius + radiusDiff / 2 + idleStateDiff / 2f; float r2 = radius + radiusDiff / 2 + idleStateDiff / 2f;

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