mirror of
https://github.com/DrKLO/Telegram.git
synced 2024-12-22 06:25:14 +01:00
update to 9.5.8
This commit is contained in:
parent
7e6d40a77a
commit
683c4e6dcb
25 changed files with 399 additions and 336 deletions
|
@ -435,7 +435,7 @@ target_include_directories(breakpad PUBLIC
|
||||||
#voip
|
#voip
|
||||||
include(${CMAKE_HOME_DIRECTORY}/voip/CMakeLists.txt)
|
include(${CMAKE_HOME_DIRECTORY}/voip/CMakeLists.txt)
|
||||||
|
|
||||||
set(NATIVE_LIB "tmessages.43")
|
set(NATIVE_LIB "tmessages.44")
|
||||||
|
|
||||||
#tmessages
|
#tmessages
|
||||||
add_library(${NATIVE_LIB} SHARED
|
add_library(${NATIVE_LIB} SHARED
|
||||||
|
|
|
@ -13,47 +13,48 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
#include <android/log.h>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <android/log.h>
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
#define __STDC_CONSTANT_MACROS
|
||||||
#ifdef _STDINT_H
|
#ifdef _STDINT_H
|
||||||
#undef _STDINT_H
|
#undef _STDINT_H
|
||||||
#endif
|
#endif
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
#include <libavresample/avresample.h>
|
|
||||||
#include <libavutil/channel_layout.h>
|
#include <libavutil/channel_layout.h>
|
||||||
#include <libavutil/error.h>
|
#include <libavutil/error.h>
|
||||||
#include <libavutil/opt.h>
|
#include <libavutil/opt.h>
|
||||||
|
#include <libswresample/swresample.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOG_TAG "ffmpeg_jni"
|
#define LOG_TAG "ffmpeg_jni"
|
||||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \
|
#define LOGE(...) \
|
||||||
__VA_ARGS__))
|
((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||||
|
|
||||||
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
|
|
||||||
extern "C" { \
|
|
||||||
JNIEXPORT RETURN_TYPE \
|
|
||||||
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegDecoder_ ## NAME \
|
|
||||||
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
|
|
||||||
} \
|
|
||||||
JNIEXPORT RETURN_TYPE \
|
|
||||||
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegDecoder_ ## NAME \
|
|
||||||
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
|
|
||||||
|
|
||||||
#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
|
#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
|
||||||
extern "C" { \
|
extern "C" { \
|
||||||
JNIEXPORT RETURN_TYPE \
|
JNIEXPORT RETURN_TYPE \
|
||||||
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_ ## NAME \
|
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_##NAME( \
|
||||||
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
|
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
JNIEXPORT RETURN_TYPE \
|
JNIEXPORT RETURN_TYPE \
|
||||||
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_ ## NAME \
|
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegLibrary_##NAME( \
|
||||||
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
|
JNIEnv *env, jobject thiz, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define AUDIO_DECODER_FUNC(RETURN_TYPE, NAME, ...) \
|
||||||
|
extern "C" { \
|
||||||
|
JNIEXPORT RETURN_TYPE \
|
||||||
|
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegAudioDecoder_##NAME( \
|
||||||
|
JNIEnv *env, jobject thiz, ##__VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
JNIEXPORT RETURN_TYPE \
|
||||||
|
Java_com_google_android_exoplayer2_ext_ffmpeg_FfmpegAudioDecoder_##NAME( \
|
||||||
|
JNIEnv *env, jobject thiz, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define ERROR_STRING_BUFFER_LENGTH 256
|
#define ERROR_STRING_BUFFER_LENGTH 256
|
||||||
|
|
||||||
|
@ -62,9 +63,8 @@ static const AVSampleFormat OUTPUT_FORMAT_PCM_16BIT = AV_SAMPLE_FMT_S16;
|
||||||
// Output format corresponding to AudioFormat.ENCODING_PCM_FLOAT.
|
// Output format corresponding to AudioFormat.ENCODING_PCM_FLOAT.
|
||||||
static const AVSampleFormat OUTPUT_FORMAT_PCM_FLOAT = AV_SAMPLE_FMT_FLT;
|
static const AVSampleFormat OUTPUT_FORMAT_PCM_FLOAT = AV_SAMPLE_FMT_FLT;
|
||||||
|
|
||||||
// Error codes matching FfmpegDecoder.java.
|
static const int AUDIO_DECODER_ERROR_INVALID_DATA = -1;
|
||||||
static const int DECODER_ERROR_INVALID_DATA = -1;
|
static const int AUDIO_DECODER_ERROR_OTHER = -2;
|
||||||
static const int DECODER_ERROR_OTHER = -2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the AVCodec with the specified name, or NULL if it is not available.
|
* Returns the AVCodec with the specified name, or NULL if it is not available.
|
||||||
|
@ -82,11 +82,17 @@ AVCodecContext *createContext(JNIEnv *env, AVCodec *codec, jbyteArray extraData,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes the packet into the output buffer, returning the number of bytes
|
* Decodes the packet into the output buffer, returning the number of bytes
|
||||||
* written, or a negative DECODER_ERROR constant value in the case of an error.
|
* written, or a negative AUDIO_DECODER_ERROR constant value in the case of an
|
||||||
|
* error.
|
||||||
*/
|
*/
|
||||||
int decodePacket(AVCodecContext *context, AVPacket *packet,
|
int decodePacket(AVCodecContext *context, AVPacket *packet,
|
||||||
uint8_t *outputBuffer, int outputSize);
|
uint8_t *outputBuffer, int outputSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms ffmpeg AVERROR into a negative AUDIO_DECODER_ERROR constant value.
|
||||||
|
*/
|
||||||
|
int transformError(int errorNumber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Outputs a log message describing the avcodec error number.
|
* Outputs a log message describing the avcodec error number.
|
||||||
*/
|
*/
|
||||||
|
@ -101,12 +107,17 @@ LIBRARY_FUNC(jstring, ffmpegGetVersion) {
|
||||||
return env->NewStringUTF(LIBAVCODEC_IDENT);
|
return env->NewStringUTF(LIBAVCODEC_IDENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBRARY_FUNC(jint, ffmpegGetInputBufferPaddingSize) {
|
||||||
|
return (jint)AV_INPUT_BUFFER_PADDING_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
LIBRARY_FUNC(jboolean, ffmpegHasDecoder, jstring codecName) {
|
LIBRARY_FUNC(jboolean, ffmpegHasDecoder, jstring codecName) {
|
||||||
return getCodecByName(env, codecName) != NULL;
|
return getCodecByName(env, codecName) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName, jbyteArray extraData,
|
AUDIO_DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName,
|
||||||
jboolean outputFloat, jint rawSampleRate, jint rawChannelCount) {
|
jbyteArray extraData, jboolean outputFloat,
|
||||||
|
jint rawSampleRate, jint rawChannelCount) {
|
||||||
AVCodec *codec = getCodecByName(env, codecName);
|
AVCodec *codec = getCodecByName(env, codecName);
|
||||||
if (!codec) {
|
if (!codec) {
|
||||||
LOGE("Codec not found.");
|
LOGE("Codec not found.");
|
||||||
|
@ -116,7 +127,7 @@ DECODER_FUNC(jlong, ffmpegInitialize, jstring codecName, jbyteArray extraData,
|
||||||
rawChannelCount);
|
rawChannelCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
|
AUDIO_DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
|
||||||
jint inputSize, jobject outputData, jint outputSize) {
|
jint inputSize, jobject outputData, jint outputSize) {
|
||||||
if (!context) {
|
if (!context) {
|
||||||
LOGE("Context must be non-NULL.");
|
LOGE("Context must be non-NULL.");
|
||||||
|
@ -144,7 +155,7 @@ DECODER_FUNC(jint, ffmpegDecode, jlong context, jobject inputData,
|
||||||
outputSize);
|
outputSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
|
AUDIO_DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
|
||||||
if (!context) {
|
if (!context) {
|
||||||
LOGE("Context must be non-NULL.");
|
LOGE("Context must be non-NULL.");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -152,7 +163,7 @@ DECODER_FUNC(jint, ffmpegGetChannelCount, jlong context) {
|
||||||
return ((AVCodecContext *)context)->channels;
|
return ((AVCodecContext *)context)->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
|
AUDIO_DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
|
||||||
if (!context) {
|
if (!context) {
|
||||||
LOGE("Context must be non-NULL.");
|
LOGE("Context must be non-NULL.");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -160,7 +171,7 @@ DECODER_FUNC(jint, ffmpegGetSampleRate, jlong context) {
|
||||||
return ((AVCodecContext *)context)->sample_rate;
|
return ((AVCodecContext *)context)->sample_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
|
AUDIO_DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
|
||||||
AVCodecContext *context = (AVCodecContext *)jContext;
|
AVCodecContext *context = (AVCodecContext *)jContext;
|
||||||
if (!context) {
|
if (!context) {
|
||||||
LOGE("Tried to reset without a context.");
|
LOGE("Tried to reset without a context.");
|
||||||
|
@ -188,7 +199,7 @@ DECODER_FUNC(jlong, ffmpegReset, jlong jContext, jbyteArray extraData) {
|
||||||
return (jlong)context;
|
return (jlong)context;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECODER_FUNC(void, ffmpegRelease, jlong context) {
|
AUDIO_DECODER_FUNC(void, ffmpegRelease, jlong context) {
|
||||||
if (context) {
|
if (context) {
|
||||||
releaseContext((AVCodecContext *)context);
|
releaseContext((AVCodecContext *)context);
|
||||||
}
|
}
|
||||||
|
@ -249,8 +260,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
|
||||||
result = avcodec_send_packet(context, packet);
|
result = avcodec_send_packet(context, packet);
|
||||||
if (result) {
|
if (result) {
|
||||||
logError("avcodec_send_packet", result);
|
logError("avcodec_send_packet", result);
|
||||||
return result == AVERROR_INVALIDDATA ? DECODER_ERROR_INVALID_DATA
|
return transformError(result);
|
||||||
: DECODER_ERROR_OTHER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dequeue output data until it runs out.
|
// Dequeue output data until it runs out.
|
||||||
|
@ -259,7 +269,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
|
||||||
AVFrame *frame = av_frame_alloc();
|
AVFrame *frame = av_frame_alloc();
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
LOGE("Failed to allocate output frame.");
|
LOGE("Failed to allocate output frame.");
|
||||||
return -1;
|
return AUDIO_DECODER_ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
result = avcodec_receive_frame(context, frame);
|
result = avcodec_receive_frame(context, frame);
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -268,7 +278,7 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
logError("avcodec_receive_frame", result);
|
logError("avcodec_receive_frame", result);
|
||||||
return result;
|
return transformError(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resample output.
|
// Resample output.
|
||||||
|
@ -279,11 +289,11 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
|
||||||
int sampleCount = frame->nb_samples;
|
int sampleCount = frame->nb_samples;
|
||||||
int dataSize = av_samples_get_buffer_size(NULL, channelCount, sampleCount,
|
int dataSize = av_samples_get_buffer_size(NULL, channelCount, sampleCount,
|
||||||
sampleFormat, 1);
|
sampleFormat, 1);
|
||||||
AVAudioResampleContext *resampleContext;
|
SwrContext *resampleContext;
|
||||||
if (context->opaque) {
|
if (context->opaque) {
|
||||||
resampleContext = (AVAudioResampleContext *) context->opaque;
|
resampleContext = (SwrContext *)context->opaque;
|
||||||
} else {
|
} else {
|
||||||
resampleContext = avresample_alloc_context();
|
resampleContext = swr_alloc();
|
||||||
av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0);
|
av_opt_set_int(resampleContext, "in_channel_layout", channelLayout, 0);
|
||||||
av_opt_set_int(resampleContext, "out_channel_layout", channelLayout, 0);
|
av_opt_set_int(resampleContext, "out_channel_layout", channelLayout, 0);
|
||||||
av_opt_set_int(resampleContext, "in_sample_rate", sampleRate, 0);
|
av_opt_set_int(resampleContext, "in_sample_rate", sampleRate, 0);
|
||||||
|
@ -292,37 +302,36 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
|
||||||
// The output format is always the requested format.
|
// The output format is always the requested format.
|
||||||
av_opt_set_int(resampleContext, "out_sample_fmt",
|
av_opt_set_int(resampleContext, "out_sample_fmt",
|
||||||
context->request_sample_fmt, 0);
|
context->request_sample_fmt, 0);
|
||||||
result = avresample_open(resampleContext);
|
result = swr_init(resampleContext);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
logError("avresample_open", result);
|
logError("swr_init", result);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
return -1;
|
return transformError(result);
|
||||||
}
|
}
|
||||||
context->opaque = resampleContext;
|
context->opaque = resampleContext;
|
||||||
}
|
}
|
||||||
int inSampleSize = av_get_bytes_per_sample(sampleFormat);
|
int inSampleSize = av_get_bytes_per_sample(sampleFormat);
|
||||||
int outSampleSize = av_get_bytes_per_sample(context->request_sample_fmt);
|
int outSampleSize = av_get_bytes_per_sample(context->request_sample_fmt);
|
||||||
int outSamples = avresample_get_out_samples(resampleContext, sampleCount);
|
int outSamples = swr_get_out_samples(resampleContext, sampleCount);
|
||||||
int bufferOutSize = outSampleSize * channelCount * outSamples;
|
int bufferOutSize = outSampleSize * channelCount * outSamples;
|
||||||
if (outSize + bufferOutSize > outputSize) {
|
if (outSize + bufferOutSize > outputSize) {
|
||||||
LOGE("Output buffer size (%d) too small for output data (%d).",
|
LOGE("Output buffer size (%d) too small for output data (%d).",
|
||||||
outputSize, outSize + bufferOutSize);
|
outputSize, outSize + bufferOutSize);
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
return -1;
|
return AUDIO_DECODER_ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
result = avresample_convert(resampleContext, &outputBuffer, bufferOutSize,
|
result = swr_convert(resampleContext, &outputBuffer, bufferOutSize,
|
||||||
outSamples, frame->data, frame->linesize[0],
|
(const uint8_t **)frame->data, frame->nb_samples);
|
||||||
sampleCount);
|
|
||||||
av_frame_free(&frame);
|
av_frame_free(&frame);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
logError("avresample_convert", result);
|
logError("swr_convert", result);
|
||||||
return result;
|
return AUDIO_DECODER_ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
int available = avresample_available(resampleContext);
|
int available = swr_get_out_samples(resampleContext, 0);
|
||||||
if (available != 0) {
|
if (available != 0) {
|
||||||
LOGE("Expected no samples remaining after resampling, but found %d.",
|
LOGE("Expected no samples remaining after resampling, but found %d.",
|
||||||
available);
|
available);
|
||||||
return -1;
|
return AUDIO_DECODER_ERROR_INVALID_DATA;
|
||||||
}
|
}
|
||||||
outputBuffer += bufferOutSize;
|
outputBuffer += bufferOutSize;
|
||||||
outSize += bufferOutSize;
|
outSize += bufferOutSize;
|
||||||
|
@ -330,6 +339,11 @@ int decodePacket(AVCodecContext *context, AVPacket *packet,
|
||||||
return outSize;
|
return outSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int transformError(int errorNumber) {
|
||||||
|
return errorNumber == AVERROR_INVALIDDATA ? AUDIO_DECODER_ERROR_INVALID_DATA
|
||||||
|
: AUDIO_DECODER_ERROR_OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
void logError(const char *functionName, int errorNumber) {
|
void logError(const char *functionName, int errorNumber) {
|
||||||
char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char));
|
char *buffer = (char *)malloc(ERROR_STRING_BUFFER_LENGTH * sizeof(char));
|
||||||
av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH);
|
av_strerror(errorNumber, buffer, ERROR_STRING_BUFFER_LENGTH);
|
||||||
|
@ -341,11 +355,10 @@ void releaseContext(AVCodecContext *context) {
|
||||||
if (!context) {
|
if (!context) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AVAudioResampleContext *resampleContext;
|
SwrContext *swrContext;
|
||||||
if ((resampleContext = (AVAudioResampleContext *) context->opaque)) {
|
if ((swrContext = (SwrContext *)context->opaque)) {
|
||||||
avresample_free(&resampleContext);
|
swr_free(&swrContext);
|
||||||
context->opaque = NULL;
|
context->opaque = NULL;
|
||||||
}
|
}
|
||||||
avcodec_free_context(&context);
|
avcodec_free_context(&context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
if (mid == NULL) {
|
if (mid == NULL) {
|
||||||
jclass cls = env->GetObjectClass(flacDecoderJni);
|
jclass cls = env->GetObjectClass(flacDecoderJni);
|
||||||
mid = env->GetMethodID(cls, "read", "(Ljava/nio/ByteBuffer;)I");
|
mid = env->GetMethodID(cls, "read", "(Ljava/nio/ByteBuffer;)I");
|
||||||
|
env->DeleteLocalRef(cls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +58,7 @@ public:
|
||||||
// Exception is thrown in Java when returning from the native call.
|
// Exception is thrown in Java when returning from the native call.
|
||||||
result = -1;
|
result = -1;
|
||||||
}
|
}
|
||||||
|
env->DeleteLocalRef(byteBuffer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +149,7 @@ DECODER_FUNC(jobject, flacDecodeMetadata, jlong jContext) {
|
||||||
context->parser->getStreamInfo();
|
context->parser->getStreamInfo();
|
||||||
|
|
||||||
jclass flacStreamMetadataClass = env->FindClass(
|
jclass flacStreamMetadataClass = env->FindClass(
|
||||||
"com/google/android/exoplayer2/util/"
|
"com/google/android/exoplayer2/extractor/"
|
||||||
"FlacStreamMetadata");
|
"FlacStreamMetadata");
|
||||||
jmethodID flacStreamMetadataConstructor =
|
jmethodID flacStreamMetadataConstructor =
|
||||||
env->GetMethodID(flacStreamMetadataClass, "<init>",
|
env->GetMethodID(flacStreamMetadataClass, "<init>",
|
||||||
|
|
|
@ -16,9 +16,8 @@
|
||||||
|
|
||||||
#include "include/flac_parser.h"
|
#include "include/flac_parser.h"
|
||||||
|
|
||||||
#include <jni.h>
|
|
||||||
|
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
|
@ -14,49 +14,60 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <android/log.h>
|
||||||
|
#endif
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
#include <android/log.h>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "opus.h" // NOLINT
|
#include "opus.h" // NOLINT
|
||||||
#include "opus_multistream.h" // NOLINT
|
#include "opus_multistream.h" // NOLINT
|
||||||
|
|
||||||
|
#ifdef __ANDROID__
|
||||||
#define LOG_TAG "opus_jni"
|
#define LOG_TAG "opus_jni"
|
||||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \
|
#define LOGE(...) \
|
||||||
__VA_ARGS__))
|
((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||||
|
#else // __ANDROID__
|
||||||
|
#define LOGE(...) \
|
||||||
|
do { \
|
||||||
|
} while (0)
|
||||||
|
#endif // __ANDROID__
|
||||||
|
|
||||||
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
|
#define DECODER_FUNC(RETURN_TYPE, NAME, ...) \
|
||||||
extern "C" { \
|
extern "C" { \
|
||||||
JNIEXPORT RETURN_TYPE \
|
JNIEXPORT RETURN_TYPE \
|
||||||
Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_ ## NAME \
|
Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_##NAME( \
|
||||||
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
|
JNIEnv* env, jobject thiz, ##__VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
JNIEXPORT RETURN_TYPE \
|
JNIEXPORT RETURN_TYPE \
|
||||||
Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_ ## NAME \
|
Java_com_google_android_exoplayer2_ext_opus_OpusDecoder_##NAME( \
|
||||||
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
|
JNIEnv* env, jobject thiz, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
|
#define LIBRARY_FUNC(RETURN_TYPE, NAME, ...) \
|
||||||
extern "C" { \
|
extern "C" { \
|
||||||
JNIEXPORT RETURN_TYPE \
|
JNIEXPORT RETURN_TYPE \
|
||||||
Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_ ## NAME \
|
Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_##NAME( \
|
||||||
(JNIEnv* env, jobject thiz, ##__VA_ARGS__);\
|
JNIEnv* env, jobject thiz, ##__VA_ARGS__); \
|
||||||
} \
|
} \
|
||||||
JNIEXPORT RETURN_TYPE \
|
JNIEXPORT RETURN_TYPE \
|
||||||
Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_ ## NAME \
|
Java_com_google_android_exoplayer2_ext_opus_OpusLibrary_##NAME( \
|
||||||
(JNIEnv* env, jobject thiz, ##__VA_ARGS__)\
|
JNIEnv* env, jobject thiz, ##__VA_ARGS__)
|
||||||
|
|
||||||
// JNI references for SimpleOutputBuffer class.
|
// JNI references for SimpleOutputBuffer class.
|
||||||
static jmethodID outputBufferInit;
|
static jmethodID outputBufferInit;
|
||||||
|
|
||||||
static const int kBytesPerSample = 2; // opus fixed point uses 16 bit samples.
|
static const int kBytesPerIntPcmSample = 2;
|
||||||
|
static const int kBytesPerFloatSample = 4;
|
||||||
static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
|
static const int kMaxOpusOutputPacketSizeSamples = 960 * 6;
|
||||||
static int channelCount;
|
static int channelCount;
|
||||||
static int errorCode;
|
static int errorCode;
|
||||||
|
static bool outputFloat = false;
|
||||||
|
|
||||||
DECODER_FUNC(jlong, opusInit, jint sampleRate, jint channelCount,
|
DECODER_FUNC(jlong, opusInit, jint sampleRate, jint channelCount,
|
||||||
jint numStreams, jint numCoupled, jint gain, jbyteArray jStreamMap) {
|
jint numStreams, jint numCoupled, jint gain,
|
||||||
|
jbyteArray jStreamMap) {
|
||||||
int status = OPUS_INVALID_STATE;
|
int status = OPUS_INVALID_STATE;
|
||||||
::channelCount = channelCount;
|
::channelCount = channelCount;
|
||||||
errorCode = 0;
|
errorCode = 0;
|
||||||
|
@ -77,9 +88,9 @@ DECODER_FUNC(jlong, opusInit, jint sampleRate, jint channelCount,
|
||||||
|
|
||||||
// Populate JNI References.
|
// Populate JNI References.
|
||||||
const jclass outputBufferClass = env->FindClass(
|
const jclass outputBufferClass = env->FindClass(
|
||||||
"com/google/android/exoplayer2/decoder/SimpleOutputBuffer");
|
"com/google/android/exoplayer2/decoder/SimpleDecoderOutputBuffer");
|
||||||
outputBufferInit = env->GetMethodID(outputBufferClass, "init",
|
outputBufferInit =
|
||||||
"(JI)Ljava/nio/ByteBuffer;");
|
env->GetMethodID(outputBufferClass, "init", "(JI)Ljava/nio/ByteBuffer;");
|
||||||
|
|
||||||
return reinterpret_cast<intptr_t>(decoder);
|
return reinterpret_cast<intptr_t>(decoder);
|
||||||
}
|
}
|
||||||
|
@ -87,40 +98,52 @@ DECODER_FUNC(jlong, opusInit, jint sampleRate, jint channelCount,
|
||||||
DECODER_FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs,
|
DECODER_FUNC(jint, opusDecode, jlong jDecoder, jlong jTimeUs,
|
||||||
jobject jInputBuffer, jint inputSize, jobject jOutputBuffer) {
|
jobject jInputBuffer, jint inputSize, jobject jOutputBuffer) {
|
||||||
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
|
OpusMSDecoder* decoder = reinterpret_cast<OpusMSDecoder*>(jDecoder);
|
||||||
const uint8_t* inputBuffer =
|
const uint8_t* inputBuffer = reinterpret_cast<const uint8_t*>(
|
||||||
reinterpret_cast<const uint8_t*>(
|
|
||||||
env->GetDirectBufferAddress(jInputBuffer));
|
env->GetDirectBufferAddress(jInputBuffer));
|
||||||
|
|
||||||
|
const int byteSizePerSample =
|
||||||
|
outputFloat ? kBytesPerFloatSample : kBytesPerIntPcmSample;
|
||||||
const jint outputSize =
|
const jint outputSize =
|
||||||
kMaxOpusOutputPacketSizeSamples * kBytesPerSample * channelCount;
|
kMaxOpusOutputPacketSizeSamples * byteSizePerSample * channelCount;
|
||||||
|
|
||||||
env->CallObjectMethod(jOutputBuffer, outputBufferInit, jTimeUs, outputSize);
|
env->CallObjectMethod(jOutputBuffer, outputBufferInit, jTimeUs, outputSize);
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
// Exception is thrown in Java when returning from the native call.
|
// Exception is thrown in Java when returning from the native call.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
const jobject jOutputBufferData = env->CallObjectMethod(jOutputBuffer,
|
const jobject jOutputBufferData = env->CallObjectMethod(
|
||||||
outputBufferInit, jTimeUs, outputSize);
|
jOutputBuffer, outputBufferInit, jTimeUs, outputSize);
|
||||||
if (env->ExceptionCheck()) {
|
if (env->ExceptionCheck()) {
|
||||||
// Exception is thrown in Java when returning from the native call.
|
// Exception is thrown in Java when returning from the native call.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sampleCount;
|
||||||
|
if (outputFloat) {
|
||||||
|
float* outputBufferData = reinterpret_cast<float*>(
|
||||||
|
env->GetDirectBufferAddress(jOutputBufferData));
|
||||||
|
sampleCount = opus_multistream_decode_float(
|
||||||
|
decoder, inputBuffer, inputSize, outputBufferData,
|
||||||
|
kMaxOpusOutputPacketSizeSamples, 0);
|
||||||
|
} else {
|
||||||
int16_t* outputBufferData = reinterpret_cast<int16_t*>(
|
int16_t* outputBufferData = reinterpret_cast<int16_t*>(
|
||||||
env->GetDirectBufferAddress(jOutputBufferData));
|
env->GetDirectBufferAddress(jOutputBufferData));
|
||||||
int sampleCount = opus_multistream_decode(decoder, inputBuffer, inputSize,
|
sampleCount = opus_multistream_decode(decoder, inputBuffer, inputSize,
|
||||||
outputBufferData, kMaxOpusOutputPacketSizeSamples, 0);
|
outputBufferData,
|
||||||
|
kMaxOpusOutputPacketSizeSamples, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// record error code
|
// record error code
|
||||||
errorCode = (sampleCount < 0) ? sampleCount : 0;
|
errorCode = (sampleCount < 0) ? sampleCount : 0;
|
||||||
return (sampleCount < 0) ? sampleCount
|
return (sampleCount < 0) ? sampleCount
|
||||||
: sampleCount * kBytesPerSample * channelCount;
|
: sampleCount * byteSizePerSample * channelCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECODER_FUNC(jint, opusSecureDecode, jlong jDecoder, jlong jTimeUs,
|
DECODER_FUNC(jint, opusSecureDecode, jlong jDecoder, jlong jTimeUs,
|
||||||
jobject jInputBuffer, jint inputSize, jobject jOutputBuffer,
|
jobject jInputBuffer, jint inputSize, jobject jOutputBuffer,
|
||||||
jint sampleRate, jobject mediaCrypto, jint inputMode, jbyteArray key,
|
jint sampleRate, jobject mediaCrypto, jint inputMode,
|
||||||
jbyteArray javaIv, jint inputNumSubSamples, jintArray numBytesOfClearData,
|
jbyteArray key, jbyteArray javaIv, jint inputNumSubSamples,
|
||||||
jintArray numBytesOfEncryptedData) {
|
jintArray numBytesOfClearData, jintArray numBytesOfEncryptedData) {
|
||||||
// Doesn't support
|
// Doesn't support
|
||||||
// Java client should have checked vpxSupportSecureDecode
|
// Java client should have checked vpxSupportSecureDecode
|
||||||
// and avoid calling this
|
// and avoid calling this
|
||||||
|
@ -142,9 +165,9 @@ DECODER_FUNC(jstring, opusGetErrorMessage, jlong jContext) {
|
||||||
return env->NewStringUTF(opus_strerror(errorCode));
|
return env->NewStringUTF(opus_strerror(errorCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
DECODER_FUNC(jint, opusGetErrorCode, jlong jContext) {
|
DECODER_FUNC(jint, opusGetErrorCode, jlong jContext) { return errorCode; }
|
||||||
return errorCode;
|
|
||||||
}
|
DECODER_FUNC(void, opusSetFloatOutput) { outputFloat = true; }
|
||||||
|
|
||||||
LIBRARY_FUNC(jstring, opusIsSecureDecodeSupported) {
|
LIBRARY_FUNC(jstring, opusIsSecureDecodeSupported) {
|
||||||
// Doesn't support
|
// Doesn't support
|
||||||
|
|
6
TMessagesProj/proguard-rules.pro
vendored
6
TMessagesProj/proguard-rules.pro
vendored
|
@ -23,9 +23,9 @@
|
||||||
-keep class org.telegram.tgnet.QuickAckDelegate { *; }
|
-keep class org.telegram.tgnet.QuickAckDelegate { *; }
|
||||||
-keep class org.telegram.tgnet.WriteToSocketDelegate { *; }
|
-keep class org.telegram.tgnet.WriteToSocketDelegate { *; }
|
||||||
-keep class com.google.android.exoplayer2.ext.** { *; }
|
-keep class com.google.android.exoplayer2.ext.** { *; }
|
||||||
-keep class com.google.android.exoplayer2.util.FlacStreamMetadata { *; }
|
-keep class com.google.android.exoplayer2.extractor.FlacStreamMetadata { *; }
|
||||||
-keep class com.google.android.exoplayer2.metadata.flac.PictureFrame { *; }
|
-keep class com.google.android.exoplayer2.metadata.flac.PictureFrame { *; }
|
||||||
-keep class com.google.android.exoplayer2.decoder.SimpleOutputBuffer { *; }
|
-keep class com.google.android.exoplayer2.decoder.SimpleDecoderOutputBuffer { *; }
|
||||||
|
|
||||||
# https://developers.google.com/ml-kit/known-issues#android_issues
|
# https://developers.google.com/ml-kit/known-issues#android_issues
|
||||||
-keep class com.google.mlkit.nl.languageid.internal.LanguageIdentificationJni { *; }
|
-keep class com.google.mlkit.nl.languageid.internal.LanguageIdentificationJni { *; }
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
# Some members of this class are being accessed from native methods. Keep them unobfuscated.
|
# Some members of this class are being accessed from native methods. Keep them unobfuscated.
|
||||||
-keep class com.google.android.exoplayer2.video.VideoDecoderOutputBuffer {
|
-keep class com.google.android.exoplayer2.decoder.VideoDecoderOutputBuffer {
|
||||||
*;
|
*;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2229,6 +2229,10 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasPendingScrollPosition() {
|
||||||
|
return mPendingScrollPosition >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class that keeps temporary state while {LayoutManager} is filling out the empty
|
* Helper class that keeps temporary state while {LayoutManager} is filling out the empty
|
||||||
* space.
|
* space.
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.google.android.exoplayer2.util.LibraryLoader;
|
||||||
import com.google.android.exoplayer2.util.Log;
|
import com.google.android.exoplayer2.util.Log;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
import org.telegram.messenger.NativeLoader;
|
||||||
|
|
||||||
/** Configures and queries the underlying native library. */
|
/** Configures and queries the underlying native library. */
|
||||||
public final class FfmpegLibrary {
|
public final class FfmpegLibrary {
|
||||||
|
@ -32,14 +33,6 @@ public final class FfmpegLibrary {
|
||||||
|
|
||||||
private static final String TAG = "FfmpegLibrary";
|
private static final String TAG = "FfmpegLibrary";
|
||||||
|
|
||||||
private static final LibraryLoader LOADER =
|
|
||||||
new LibraryLoader("ffmpegJNI") {
|
|
||||||
@Override
|
|
||||||
protected void loadLibrary(String name) {
|
|
||||||
System.loadLibrary(name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static @MonotonicNonNull String version;
|
private static @MonotonicNonNull String version;
|
||||||
private static int inputBufferPaddingSize = C.LENGTH_UNSET;
|
private static int inputBufferPaddingSize = C.LENGTH_UNSET;
|
||||||
|
|
||||||
|
@ -53,12 +46,12 @@ public final class FfmpegLibrary {
|
||||||
* @param libraries The names of the FFmpeg native libraries.
|
* @param libraries The names of the FFmpeg native libraries.
|
||||||
*/
|
*/
|
||||||
public static void setLibraries(String... libraries) {
|
public static void setLibraries(String... libraries) {
|
||||||
LOADER.setLibraries(libraries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the underlying library is available, loading it if necessary. */
|
/** Returns whether the underlying library is available, loading it if necessary. */
|
||||||
public static boolean isAvailable() {
|
public static boolean isAvailable() {
|
||||||
return LOADER.isAvailable();
|
return NativeLoader.loaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the version of the underlying library if available, or null otherwise. */
|
/** Returns the version of the underlying library if available, or null otherwise. */
|
||||||
|
|
|
@ -18,6 +18,8 @@ package com.google.android.exoplayer2.ext.flac;
|
||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.util.LibraryLoader;
|
import com.google.android.exoplayer2.util.LibraryLoader;
|
||||||
|
|
||||||
|
import org.telegram.messenger.NativeLoader;
|
||||||
|
|
||||||
/** Configures and queries the underlying native library. */
|
/** Configures and queries the underlying native library. */
|
||||||
public final class FlacLibrary {
|
public final class FlacLibrary {
|
||||||
|
|
||||||
|
@ -25,13 +27,6 @@ public final class FlacLibrary {
|
||||||
ExoPlayerLibraryInfo.registerModule("goog.exo.flac");
|
ExoPlayerLibraryInfo.registerModule("goog.exo.flac");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final LibraryLoader LOADER =
|
|
||||||
new LibraryLoader("flacJNI") {
|
|
||||||
@Override
|
|
||||||
protected void loadLibrary(String name) {
|
|
||||||
System.loadLibrary(name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private FlacLibrary() {}
|
private FlacLibrary() {}
|
||||||
|
|
||||||
|
@ -43,11 +38,10 @@ public final class FlacLibrary {
|
||||||
* @param libraries The names of the Flac native libraries.
|
* @param libraries The names of the Flac native libraries.
|
||||||
*/
|
*/
|
||||||
public static void setLibraries(String... libraries) {
|
public static void setLibraries(String... libraries) {
|
||||||
LOADER.setLibraries(libraries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the underlying library is available, loading it if necessary. */
|
/** Returns whether the underlying library is available, loading it if necessary. */
|
||||||
public static boolean isAvailable() {
|
public static boolean isAvailable() {
|
||||||
return LOADER.isAvailable();
|
return NativeLoader.loaded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
import com.google.android.exoplayer2.ExoPlayerLibraryInfo;
|
||||||
import com.google.android.exoplayer2.util.LibraryLoader;
|
import com.google.android.exoplayer2.util.LibraryLoader;
|
||||||
|
|
||||||
|
import org.telegram.messenger.NativeLoader;
|
||||||
|
|
||||||
/** Configures and queries the underlying native library. */
|
/** Configures and queries the underlying native library. */
|
||||||
public final class OpusLibrary {
|
public final class OpusLibrary {
|
||||||
|
|
||||||
|
@ -27,14 +29,6 @@ public final class OpusLibrary {
|
||||||
ExoPlayerLibraryInfo.registerModule("goog.exo.opus");
|
ExoPlayerLibraryInfo.registerModule("goog.exo.opus");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final LibraryLoader LOADER =
|
|
||||||
new LibraryLoader("opusV2JNI") {
|
|
||||||
@Override
|
|
||||||
protected void loadLibrary(String name) {
|
|
||||||
System.loadLibrary(name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static @C.CryptoType int cryptoType = C.CRYPTO_TYPE_UNSUPPORTED;
|
private static @C.CryptoType int cryptoType = C.CRYPTO_TYPE_UNSUPPORTED;
|
||||||
|
|
||||||
private OpusLibrary() {}
|
private OpusLibrary() {}
|
||||||
|
@ -51,12 +45,11 @@ public final class OpusLibrary {
|
||||||
*/
|
*/
|
||||||
public static void setLibraries(@C.CryptoType int cryptoType, String... libraries) {
|
public static void setLibraries(@C.CryptoType int cryptoType, String... libraries) {
|
||||||
OpusLibrary.cryptoType = cryptoType;
|
OpusLibrary.cryptoType = cryptoType;
|
||||||
LOADER.setLibraries(libraries);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether the underlying library is available, loading it if necessary. */
|
/** Returns whether the underlying library is available, loading it if necessary. */
|
||||||
public static boolean isAvailable() {
|
public static boolean isAvailable() {
|
||||||
return LOADER.isAvailable();
|
return NativeLoader.loaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the version of the underlying library if available, or null otherwise. */
|
/** Returns the version of the underlying library if available, or null otherwise. */
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.util;
|
package com.google.android.exoplayer2.util;
|
||||||
|
|
||||||
|
import static java.lang.System.loadLibrary;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/** Configurable loader for native libraries. */
|
/** Configurable loader for native libraries. */
|
||||||
|
@ -72,5 +74,5 @@ public abstract class LibraryLoader {
|
||||||
*
|
*
|
||||||
* @param name The name of the library to load.
|
* @param name The name of the library to load.
|
||||||
*/
|
*/
|
||||||
protected abstract void loadLibrary(String name);
|
protected abstract void oadLibrary(String name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,7 +256,11 @@ public class ApplicationLoader extends Application {
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeLoader.initNativeLibs(ApplicationLoader.applicationContext);
|
NativeLoader.initNativeLibs(ApplicationLoader.applicationContext);
|
||||||
|
try {
|
||||||
ConnectionsManager.native_setJava(false);
|
ConnectionsManager.native_setJava(false);
|
||||||
|
} catch (UnsatisfiedLinkError error) {
|
||||||
|
throw new RuntimeException("can't load native libraries " + Build.CPU_ABI + " lookup folder " + NativeLoader.getAbiFolder());
|
||||||
|
}
|
||||||
new ForegroundDetector(this) {
|
new ForegroundDetector(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onActivityStarted(Activity activity) {
|
public void onActivityStarted(Activity activity) {
|
||||||
|
|
|
@ -24,8 +24,8 @@ public class BuildVars {
|
||||||
public static boolean USE_CLOUD_STRINGS = true;
|
public static boolean USE_CLOUD_STRINGS = true;
|
||||||
public static boolean CHECK_UPDATES = true;
|
public static boolean CHECK_UPDATES = true;
|
||||||
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
|
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
|
||||||
public static int BUILD_VERSION = 3249;
|
public static int BUILD_VERSION = 3252;
|
||||||
public static String BUILD_VERSION_STRING = "9.5.7";
|
public static String BUILD_VERSION_STRING = "9.5.8";
|
||||||
public static int APP_ID = 4;
|
public static int APP_ID = 4;
|
||||||
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
|
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ public final class EmuInputDevicesDetector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
r.close();
|
||||||
return lines;
|
return lines;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
|
|
|
@ -2277,7 +2277,8 @@ public class ImageLoader {
|
||||||
newPath = ApplicationLoader.applicationContext.getExternalFilesDir(null);
|
newPath = ApplicationLoader.applicationContext.getExternalFilesDir(null);
|
||||||
telegramPath = new File(newPath, "Telegram");
|
telegramPath = new File(newPath, "Telegram");
|
||||||
} else {
|
} else {
|
||||||
if (!(path.exists() ? path.isDirectory() : path.mkdirs()) || !path.canWrite()) {
|
boolean isSdCard = !TextUtils.isEmpty(SharedConfig.storageCacheDir) && path.getAbsolutePath().startsWith(SharedConfig.storageCacheDir);
|
||||||
|
if (!isSdCard && !(path.exists() ? path.isDirectory() : path.mkdirs()) || !path.canWrite()) {
|
||||||
path = ApplicationLoader.applicationContext.getExternalFilesDir(null);
|
path = ApplicationLoader.applicationContext.getExternalFilesDir(null);
|
||||||
}
|
}
|
||||||
telegramPath = new File(path, "Telegram");
|
telegramPath = new File(path, "Telegram");
|
||||||
|
|
|
@ -22,7 +22,7 @@ import java.util.zip.ZipFile;
|
||||||
|
|
||||||
public class NativeLoader {
|
public class NativeLoader {
|
||||||
|
|
||||||
private final static int LIB_VERSION = 43;
|
private final static int LIB_VERSION = 44;
|
||||||
private final static String LIB_NAME = "tmessages." + LIB_VERSION;
|
private final static String LIB_NAME = "tmessages." + LIB_VERSION;
|
||||||
private final static String LIB_SO_NAME = "lib" + LIB_NAME + ".so";
|
private final static String LIB_SO_NAME = "lib" + LIB_NAME + ".so";
|
||||||
private final static String LOCALE_LIB_SO_NAME = "lib" + LIB_NAME + "loc.so";
|
private final static String LOCALE_LIB_SO_NAME = "lib" + LIB_NAME + "loc.so";
|
||||||
|
@ -127,36 +127,7 @@ public class NativeLoader {
|
||||||
FileLog.e(e);
|
FileLog.e(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
String folder;
|
String folder = getAbiFolder();
|
||||||
try {
|
|
||||||
String str = Build.CPU_ABI;
|
|
||||||
if (Build.CPU_ABI.equalsIgnoreCase("x86_64")) {
|
|
||||||
folder = "x86_64";
|
|
||||||
} else if (Build.CPU_ABI.equalsIgnoreCase("arm64-v8a")) {
|
|
||||||
folder = "arm64-v8a";
|
|
||||||
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi-v7a")) {
|
|
||||||
folder = "armeabi-v7a";
|
|
||||||
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi")) {
|
|
||||||
folder = "armeabi";
|
|
||||||
} else if (Build.CPU_ABI.equalsIgnoreCase("x86")) {
|
|
||||||
folder = "x86";
|
|
||||||
} else if (Build.CPU_ABI.equalsIgnoreCase("mips")) {
|
|
||||||
folder = "mips";
|
|
||||||
} else {
|
|
||||||
folder = "armeabi";
|
|
||||||
if (BuildVars.LOGS_ENABLED) {
|
|
||||||
FileLog.e("Unsupported arch: " + Build.CPU_ABI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
FileLog.e(e);
|
|
||||||
folder = "armeabi";
|
|
||||||
}
|
|
||||||
|
|
||||||
String javaArch = System.getProperty("os.arch");
|
|
||||||
if (javaArch != null && javaArch.contains("686")) {
|
|
||||||
folder = "x86";
|
|
||||||
}
|
|
||||||
|
|
||||||
/*File destFile = getNativeLibraryDir(context);
|
/*File destFile = getNativeLibraryDir(context);
|
||||||
if (destFile != null) {
|
if (destFile != null) {
|
||||||
|
@ -209,6 +180,40 @@ public class NativeLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getAbiFolder() {
|
||||||
|
String folder;
|
||||||
|
try {
|
||||||
|
String str = Build.CPU_ABI;
|
||||||
|
if (Build.CPU_ABI.equalsIgnoreCase("x86_64")) {
|
||||||
|
folder = "x86_64";
|
||||||
|
} else if (Build.CPU_ABI.equalsIgnoreCase("arm64-v8a")) {
|
||||||
|
folder = "arm64-v8a";
|
||||||
|
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi-v7a")) {
|
||||||
|
folder = "armeabi-v7a";
|
||||||
|
} else if (Build.CPU_ABI.equalsIgnoreCase("armeabi")) {
|
||||||
|
folder = "armeabi";
|
||||||
|
} else if (Build.CPU_ABI.equalsIgnoreCase("x86")) {
|
||||||
|
folder = "x86";
|
||||||
|
} else if (Build.CPU_ABI.equalsIgnoreCase("mips")) {
|
||||||
|
folder = "mips";
|
||||||
|
} else {
|
||||||
|
folder = "armeabi";
|
||||||
|
if (BuildVars.LOGS_ENABLED) {
|
||||||
|
FileLog.e("Unsupported arch: " + Build.CPU_ABI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
FileLog.e(e);
|
||||||
|
folder = "armeabi";
|
||||||
|
}
|
||||||
|
|
||||||
|
String javaArch = System.getProperty("os.arch");
|
||||||
|
if (javaArch != null && javaArch.contains("686")) {
|
||||||
|
folder = "x86";
|
||||||
|
}
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
private static native void init(String path, boolean enable);
|
private static native void init(String path, boolean enable);
|
||||||
|
|
||||||
public static boolean loaded() {
|
public static boolean loaded() {
|
||||||
|
|
|
@ -4837,7 +4837,7 @@ public class DialogCell extends BaseCell {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int messageHash = message == null ? 0 : message.getId();
|
int messageHash = message == null ? 0 : message.getId() + message.hashCode();
|
||||||
Integer printingType = null;
|
Integer printingType = null;
|
||||||
long readHash = dialog.read_inbox_max_id + ((long) dialog.read_outbox_max_id << 8) + ((long) (dialog.unread_count + (dialog.unread_mark ? -1 : 0)) << 16) +
|
long readHash = dialog.read_inbox_max_id + ((long) dialog.read_outbox_max_id << 8) + ((long) (dialog.unread_count + (dialog.unread_mark ? -1 : 0)) << 16) +
|
||||||
(dialog.unread_reactions_count > 0 ? (1 << 18) : 0) +
|
(dialog.unread_reactions_count > 0 ? (1 << 18) : 0) +
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class DialogsRequestedEmptyCell extends LinearLayout implements Notificat
|
||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow() {
|
protected void onDetachedFromWindow() {
|
||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.diceStickersDidLoad);
|
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.diceStickersDidLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3507,6 +3507,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthSpec, int heightSpec) {
|
||||||
|
saveScrollPosition();
|
||||||
|
super.onMeasure(widthSpec, heightSpec);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
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) {
|
||||||
super.onLayout(changed, l, t, r, b);
|
super.onLayout(changed, l, t, r, b);
|
||||||
|
@ -8748,28 +8754,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
|
|
||||||
if (chatListView != null && chatLayoutManager != null && chatAdapter != null) {
|
if (chatListView != null && chatLayoutManager != null && chatAdapter != null) {
|
||||||
if (chatListView.getPaddingTop() != p) {
|
if (chatListView.getPaddingTop() != p) {
|
||||||
int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition();
|
|
||||||
int lastVisPos = chatLayoutManager.findLastVisibleItemPosition();
|
|
||||||
int top = 0;
|
int top = 0;
|
||||||
MessageObject scrollToMessageObject = null;
|
MessageObject scrollToMessageObject = null;
|
||||||
if (firstVisPos != RecyclerView.NO_POSITION) {
|
for (int i = 0; i < chatListView.getChildCount(); i++) {
|
||||||
for (int i = firstVisPos; i <= lastVisPos; i++) {
|
View v = chatListView.getChildAt(i);
|
||||||
View v = chatLayoutManager.findViewByPosition(i);
|
|
||||||
if (v instanceof ChatMessageCell) {
|
if (v instanceof ChatMessageCell) {
|
||||||
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
|
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
|
||||||
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
|
top = getScrollingOffsetForView(v);
|
||||||
break;
|
break;
|
||||||
} else if (v instanceof ChatActionCell) {
|
} else if (v instanceof ChatActionCell) {
|
||||||
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
|
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
|
||||||
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
|
top = getScrollingOffsetForView(v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset);
|
chatListView.setPadding(0, p, 0, AndroidUtilities.dp(3) + blurredViewBottomOffset);
|
||||||
|
|
||||||
if (firstVisPos != RecyclerView.NO_POSITION && scrollToMessageObject != null) {
|
if (scrollToMessageObject != null) {
|
||||||
chatAdapter.updateRowsSafe();
|
chatAdapter.updateRowsSafe();
|
||||||
int index = messages.indexOf(scrollToMessageObject);
|
int index = messages.indexOf(scrollToMessageObject);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
|
@ -15843,24 +15845,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
startLoadFromMessageId = 0;
|
startLoadFromMessageId = 0;
|
||||||
}
|
}
|
||||||
if (newRowsCount > 0) {
|
if (newRowsCount > 0) {
|
||||||
int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition();
|
|
||||||
int lastVisPos = chatLayoutManager.findLastVisibleItemPosition();
|
|
||||||
int top = 0;
|
int top = 0;
|
||||||
MessageObject scrollToMessageObject = null;
|
MessageObject scrollToMessageObject = null;
|
||||||
if (firstVisPos != RecyclerView.NO_POSITION) {
|
for (int i = 0; i < chatListView.getChildCount(); i++) {
|
||||||
for (int i = firstVisPos; i <= lastVisPos; i++) {
|
View v = chatListView.getChildAt(i);
|
||||||
View v = chatLayoutManager.findViewByPosition(i);
|
|
||||||
if (v instanceof ChatMessageCell) {
|
if (v instanceof ChatMessageCell) {
|
||||||
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
|
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
|
||||||
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
|
top = getScrollingOffsetForView(v);
|
||||||
break;
|
break;
|
||||||
} else if (v instanceof ChatActionCell) {
|
} else if (v instanceof ChatActionCell) {
|
||||||
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
|
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
|
||||||
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
|
top = getScrollingOffsetForView(v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!postponedScroll) {
|
if (!postponedScroll) {
|
||||||
chatAdapter.notifyItemRangeInserted(1, newRowsCount);
|
chatAdapter.notifyItemRangeInserted(1, newRowsCount);
|
||||||
|
@ -15959,24 +15957,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (newRowsCount != 0) {
|
if (newRowsCount != 0) {
|
||||||
int firstVisPos = chatLayoutManager.findFirstVisibleItemPosition();
|
|
||||||
int lastVisPos = chatLayoutManager.findLastVisibleItemPosition();
|
|
||||||
int top = 0;
|
int top = 0;
|
||||||
MessageObject scrollToMessageObject = null;
|
MessageObject scrollToMessageObject = null;
|
||||||
if (firstVisPos != RecyclerView.NO_POSITION) {
|
for (int i = 0; i < chatListView.getChildCount(); i++) {
|
||||||
for (int i = firstVisPos; i <= lastVisPos; i++) {
|
View v = chatListView.getChildAt(i);
|
||||||
View v = chatLayoutManager.findViewByPosition(i);
|
|
||||||
if (v instanceof ChatMessageCell) {
|
if (v instanceof ChatMessageCell) {
|
||||||
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
|
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
|
||||||
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
|
top = getScrollingOffsetForView(v);
|
||||||
break;
|
break;
|
||||||
} else if (v instanceof ChatActionCell) {
|
} else if (v instanceof ChatActionCell) {
|
||||||
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
|
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
|
||||||
top = chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
|
top = getScrollingOffsetForView(v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
int insertStart = chatAdapter.messagesEndRow;
|
int insertStart = chatAdapter.messagesEndRow;
|
||||||
int loadingUpRow = chatAdapter.loadingUpRow;
|
int loadingUpRow = chatAdapter.loadingUpRow;
|
||||||
chatAdapter.updateRowsInternal();
|
chatAdapter.updateRowsInternal();
|
||||||
|
@ -18268,6 +18262,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getScrollingOffsetForView(View v) {
|
||||||
|
return chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean updateMessageTranslation(MessageObject messageObject) {
|
private boolean updateMessageTranslation(MessageObject messageObject) {
|
||||||
if (messageObject == null || messageObject.messageOwner == null) {
|
if (messageObject == null || messageObject.messageOwner == null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -19438,7 +19436,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (child != null) {
|
if (child != null) {
|
||||||
chatLayoutManager.scrollToPositionWithOffset(lastVisible + 1, chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom());
|
chatLayoutManager.scrollToPositionWithOffset(lastVisible + 1, getScrollingOffsetForView(child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newMentionsCount != 0 && mentiondownButtonCounter != null) {
|
if (newMentionsCount != 0 && mentiondownButtonCounter != null) {
|
||||||
|
@ -19488,6 +19486,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveScrollPosition() {
|
||||||
|
if (chatListView == null || chatLayoutManager == null || chatLayoutManager.hasPendingScrollPosition()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int top = 0;
|
||||||
|
MessageObject scrollToMessageObject = null;
|
||||||
|
for (int i = 0; i < chatListView.getChildCount(); i++) {
|
||||||
|
View v = chatListView.getChildAt(i);
|
||||||
|
if (v instanceof ChatMessageCell) {
|
||||||
|
scrollToMessageObject = ((ChatMessageCell) v).getMessageObject();
|
||||||
|
top = getScrollingOffsetForView(v);
|
||||||
|
break;
|
||||||
|
} else if (v instanceof ChatActionCell) {
|
||||||
|
scrollToMessageObject = ((ChatActionCell) v).getMessageObject();
|
||||||
|
top = getScrollingOffsetForView(v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scrollToMessageObject != null) {
|
||||||
|
int scrollToIndex = messages.indexOf(scrollToMessageObject);
|
||||||
|
if (scrollToIndex > 0) {
|
||||||
|
chatLayoutManager.scrollToPositionWithOffset(chatAdapter.messagesStartRow + scrollToIndex, top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int getSponsoredMessagesCount() {
|
private int getSponsoredMessagesCount() {
|
||||||
int sponsoredMessagesCount = 0;
|
int sponsoredMessagesCount = 0;
|
||||||
while (sponsoredMessagesCount < messages.size()) {
|
while (sponsoredMessagesCount < messages.size()) {
|
||||||
|
@ -26123,7 +26147,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
int unreadMessageIndex = messages.indexOf(unreadMessageObject);
|
int unreadMessageIndex = messages.indexOf(unreadMessageObject);
|
||||||
if (unreadMessageIndex >= 0) {
|
if (unreadMessageIndex >= 0) {
|
||||||
lastVisibleItem = chatAdapter.messagesStartRow + messages.indexOf(unreadMessageObject);
|
lastVisibleItem = chatAdapter.messagesStartRow + messages.indexOf(unreadMessageObject);
|
||||||
top = chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom();
|
top = getScrollingOffsetForView(child);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -26185,7 +26209,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (lastVisibleItem != RecyclerView.NO_POSITION) {
|
if (lastVisibleItem != RecyclerView.NO_POSITION) {
|
||||||
// chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top);
|
chatLayoutManager.scrollToPositionWithOffset(lastVisibleItem, top);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28288,7 +28312,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
|
||||||
int unreadMessageIndex = messages.indexOf(unreadMessageObject);
|
int unreadMessageIndex = messages.indexOf(unreadMessageObject);
|
||||||
if (unreadMessageIndex >= 0) {
|
if (unreadMessageIndex >= 0) {
|
||||||
lastVisibleItem = messagesStartRow + messages.indexOf(unreadMessageObject);
|
lastVisibleItem = messagesStartRow + messages.indexOf(unreadMessageObject);
|
||||||
top = chatListView.getMeasuredHeight() - child.getBottom() - chatListView.getPaddingBottom();
|
top = getScrollingOffsetForView(child);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import android.text.Layout;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextPaint;
|
import android.text.TextPaint;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.text.style.ClickableSpan;
|
import android.text.style.ClickableSpan;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
@ -357,11 +358,11 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
|
||||||
if (isOutboundGift) {
|
if (isOutboundGift) {
|
||||||
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
|
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
|
||||||
subtitleView.setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle, user != null ? user.first_name : ""), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
|
subtitleView.setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle, user != null ? user.first_name : ""), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
|
||||||
} else if (user != null && user.id == 777000) {
|
} else if (user == null || TextUtils.isEmpty(user.first_name) || user.id == 777000) {
|
||||||
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPluralSomeone, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
|
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPluralSomeone, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
|
||||||
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
|
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
|
||||||
} else {
|
} else {
|
||||||
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
|
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPlural, user.first_name, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
|
||||||
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
|
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -294,7 +294,6 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable, Bitma
|
||||||
if (onAnimationEndListener != null) {
|
if (onAnimationEndListener != null) {
|
||||||
onAnimationEndListener = null;
|
onAnimationEndListener = null;
|
||||||
}
|
}
|
||||||
invalidateInternal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnFinishCallback(Runnable callback, int frame) {
|
public void setOnFinishCallback(Runnable callback, int frame) {
|
||||||
|
|
|
@ -94,7 +94,7 @@ public class StickerCategoriesListView extends RecyclerListView {
|
||||||
|
|
||||||
public static void preload(int account, @CategoriesType int type) {
|
public static void preload(int account, @CategoriesType int type) {
|
||||||
fetcher.fetch(account, type, emojiGroups -> {
|
fetcher.fetch(account, type, emojiGroups -> {
|
||||||
if (emojiGroups.groups == null) {
|
if (emojiGroups == null || emojiGroups.groups == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (TLRPC.TL_emojiGroup group : emojiGroups.groups) {
|
for (TLRPC.TL_emojiGroup group : emojiGroups.groups) {
|
||||||
|
|
|
@ -8683,6 +8683,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
|
||||||
} else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) {
|
} else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) {
|
||||||
updateVisibleRows(0);
|
updateVisibleRows(0);
|
||||||
} else if (id == NotificationCenter.emojiLoaded) {
|
} else if (id == NotificationCenter.emojiLoaded) {
|
||||||
|
if (viewPages != null) {
|
||||||
for (int i = 0; i < viewPages.length; ++i) {
|
for (int i = 0; i < viewPages.length; ++i) {
|
||||||
final RecyclerListView listView = viewPages[i].listView;
|
final RecyclerListView listView = viewPages[i].listView;
|
||||||
if (listView != null) {
|
if (listView != null) {
|
||||||
|
@ -8694,6 +8695,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (filterTabsView != null) {
|
if (filterTabsView != null) {
|
||||||
filterTabsView.getTabsContainer().invalidateViews();
|
filterTabsView.getTabsContainer().invalidateViews();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1682,9 +1682,9 @@ public class LoginActivity extends BaseFragment {
|
||||||
|
|
||||||
if (obj.optBoolean("basicIntegrity") && obj.optBoolean("ctsProfileMatch")) {
|
if (obj.optBoolean("basicIntegrity") && obj.optBoolean("ctsProfileMatch")) {
|
||||||
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
|
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
|
||||||
|
if (response instanceof TLRPC.TL_boolTrue) {
|
||||||
needHideProgress(false);
|
needHideProgress(false);
|
||||||
isRequestingFirebaseSms = false;
|
isRequestingFirebaseSms = false;
|
||||||
if (response instanceof TLRPC.TL_boolTrue) {
|
|
||||||
res.type.verifiedFirebase = true;
|
res.type.verifiedFirebase = true;
|
||||||
AndroidUtilities.runOnUIThread(() -> fillNextCodeParams(params, res, animate));
|
AndroidUtilities.runOnUIThread(() -> fillNextCodeParams(params, res, animate));
|
||||||
} else {
|
} else {
|
||||||
|
@ -3654,19 +3654,6 @@ public class LoginActivity extends BaseFragment {
|
||||||
wrongCode.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4));
|
wrongCode.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4));
|
||||||
errorViewSwitcher.addView(wrongCode, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
|
errorViewSwitcher.addView(wrongCode, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER));
|
||||||
|
|
||||||
if (currentType != AUTH_TYPE_FRAGMENT_SMS) {
|
|
||||||
if (currentType == AUTH_TYPE_MESSAGE) {
|
|
||||||
if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) {
|
|
||||||
problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone));
|
|
||||||
} else if (nextType == 0) {
|
|
||||||
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
|
|
||||||
} else {
|
|
||||||
problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (centerContainer == null) {
|
if (centerContainer == null) {
|
||||||
bottomContainer = new FrameLayout(context);
|
bottomContainer = new FrameLayout(context);
|
||||||
bottomContainer.addView(errorViewSwitcher, LayoutHelper.createFrame(currentType == VIEW_CODE_FRAGMENT_SMS ? LayoutHelper.MATCH_PARENT : LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 32));
|
bottomContainer.addView(errorViewSwitcher, LayoutHelper.createFrame(currentType == VIEW_CODE_FRAGMENT_SMS ? LayoutHelper.MATCH_PARENT : LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 32));
|
||||||
|
@ -3998,6 +3985,20 @@ public class LoginActivity extends BaseFragment {
|
||||||
}
|
}
|
||||||
confirmTextView.setText(str);
|
confirmTextView.setText(str);
|
||||||
|
|
||||||
|
if (currentType != AUTH_TYPE_FRAGMENT_SMS) {
|
||||||
|
if (currentType == AUTH_TYPE_MESSAGE) {
|
||||||
|
if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) {
|
||||||
|
problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone));
|
||||||
|
} else if (nextType == 0) {
|
||||||
|
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
|
||||||
|
} else {
|
||||||
|
problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (currentType != AUTH_TYPE_FLASH_CALL) {
|
if (currentType != AUTH_TYPE_FLASH_CALL) {
|
||||||
showKeyboard(codeFieldContainer.codeField[0]);
|
showKeyboard(codeFieldContainer.codeField[0]);
|
||||||
codeFieldContainer.codeField[0].requestFocus();
|
codeFieldContainer.codeField[0].requestFocus();
|
||||||
|
@ -4015,7 +4016,8 @@ public class LoginActivity extends BaseFragment {
|
||||||
if (problemText != null) {
|
if (problemText != null) {
|
||||||
problemText.setVisibility(VISIBLE);
|
problemText.setVisibility(VISIBLE);
|
||||||
}
|
}
|
||||||
} else if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS)) {
|
} else if (currentType == AUTH_TYPE_FLASH_CALL) {
|
||||||
|
if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) {
|
||||||
setProblemTextVisible(false);
|
setProblemTextVisible(false);
|
||||||
timeText.setVisibility(VISIBLE);
|
timeText.setVisibility(VISIBLE);
|
||||||
problemText.setVisibility(GONE);
|
problemText.setVisibility(GONE);
|
||||||
|
@ -4024,12 +4026,13 @@ public class LoginActivity extends BaseFragment {
|
||||||
} else if (nextType == AUTH_TYPE_SMS) {
|
} else if (nextType == AUTH_TYPE_SMS) {
|
||||||
timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0));
|
timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
String callLogNumber = restore ? AndroidUtilities.obtainLoginPhoneCall(pattern) : null;
|
String callLogNumber = restore ? AndroidUtilities.obtainLoginPhoneCall(pattern) : null;
|
||||||
if (callLogNumber != null) {
|
if (callLogNumber != null) {
|
||||||
onNextPressed(callLogNumber);
|
onNextPressed(callLogNumber);
|
||||||
} else if (catchedPhone != null) {
|
} else if (catchedPhone != null) {
|
||||||
onNextPressed(catchedPhone);
|
onNextPressed(catchedPhone);
|
||||||
} else {
|
} else if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) {
|
||||||
createTimer();
|
createTimer();
|
||||||
}
|
}
|
||||||
} else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) {
|
} else if (currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL)) {
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
# org.gradle.parallel=true
|
# org.gradle.parallel=true
|
||||||
#Sat Mar 12 05:53:50 MSK 2016
|
#Sat Mar 12 05:53:50 MSK 2016
|
||||||
APP_VERSION_CODE=3249
|
APP_VERSION_CODE=3252
|
||||||
APP_VERSION_NAME=9.5.7
|
APP_VERSION_NAME=9.5.8
|
||||||
APP_PACKAGE=org.telegram.messenger
|
APP_PACKAGE=org.telegram.messenger
|
||||||
RELEASE_KEY_PASSWORD=android
|
RELEASE_KEY_PASSWORD=TelegramAndroidPswd
|
||||||
RELEASE_KEY_ALIAS=androidkey
|
RELEASE_KEY_ALIAS=tmessages
|
||||||
RELEASE_STORE_PASSWORD=android
|
RELEASE_STORE_PASSWORD=TelegramAndroidPswd
|
||||||
org.gradle.jvmargs=-Xmx4096M -XX:MaxPermSize=4096m
|
org.gradle.jvmargs=-Xmx4096M -XX:MaxPermSize=4096m
|
||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
|
Loading…
Reference in a new issue