mirror of https://github.com/NekoX-Dev/NekoX.git
Update to 6.2.0 (1984)
This commit is contained in:
parent
9c11ea0f31
commit
06bcaa7d3f
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,8 +0,0 @@
|
||||||
#ifndef image_h
|
|
||||||
#define image_h
|
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
|
|
||||||
jint imageOnJNILoad(JavaVM *vm, JNIEnv *env);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 |
File diff suppressed because it is too large
Load Diff
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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⃣", "🔟", "🔢", "#⃣", "*⃣", "⏏", "▶", "⏸", "⏯", "⏹", "⏺", "⏭", "⏮", "⏩", "⏪", "⏫", "⏬", "◀", "🔼", "🔽", "➡", "⬅", "⬆", "⬇", "↗", "↘", "↙", "↖", "↕", "↔", "↪", "↩", "⤴", "⤵", "🔀", "🔁", "🔂", "🔄", "🔃", "🎵", "🎶", "➕", "➖", "➗", "✖", "♾", "💲", "💱", "™", "©", "®", "👁🗨", "🔚", "🔙", "🔛", "🔝", "🔜", "〰", "➰", "➿", "✔", "☑", "🔘", "🔴", "🟠", "🟡", "🟢", "🔵", "🟣", "⚫", "⚪", "🟤", "🔺", "🔻", "🔸", "🔹", "🔶", "🔷", "🔳", "🔲", "▪", "▫", "◾", "◽", "◼", "◻", "🟥", "🟧", "🟨", "🟩", "🟦", "🟪", "⬛", "⬜", "🟫", "🔈", "🔇", "🔉", "🔊", "🔔", "🔕", "📣", "📢", "💬", "💭", "🗯", "♠", "♣", "♥", "♦", "🃏", "🎴", "🀄", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", "🕛", "🕜", "🕝", "🕞", "🕟", "🕠", "🕡", "🕢", "🕣", "🕤", "🕥", "🕦", "🕧"
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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()) {
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
Loading…
Reference in New Issue