Commit a7513b3b authored by DrKLO's avatar DrKLO

Update to 3.7.0

parent 6154c891
## Telegram messenger for Android ## Telegram messenger for Android
[Telegram](http://telegram.org) is a messaging app with a focus on speed and security. It’s superfast, simple and free. [Telegram](https://telegram.org) is a messaging app with a focus on speed and security. It’s superfast, simple and free.
This repo contains the official source code for [Telegram App for Android](https://play.google.com/store/apps/details?id=org.telegram.messenger). This repo contains the official source code for [Telegram App for Android](https://play.google.com/store/apps/details?id=org.telegram.messenger).
##Creating your Telegram Application ##Creating your Telegram Application
...@@ -16,9 +16,9 @@ There are several things we require from **all developers** for the moment. ...@@ -16,9 +16,9 @@ There are several things we require from **all developers** for the moment.
### API, Protocol documentation ### API, Protocol documentation
Telegram API manuals: http://core.telegram.org/api Telegram API manuals: https://core.telegram.org/api
MTproto protocol manuals: http://core.telegram.org/mtproto MTproto protocol manuals: https://core.telegram.org/mtproto
### Usage ### Usage
......
...@@ -5,7 +5,7 @@ repositories { ...@@ -5,7 +5,7 @@ repositories {
} }
dependencies { dependencies {
compile 'com.android.support:support-v4:23.1.+' compile 'com.android.support:support-v4:23.2.1'
compile "com.google.android.gms:play-services-gcm:8.4.0" compile "com.google.android.gms:play-services-gcm:8.4.0"
compile "com.google.android.gms:play-services-maps:8.4.0" compile "com.google.android.gms:play-services-maps:8.4.0"
compile 'net.hockeyapp.android:HockeySDK:3.6.+' compile 'net.hockeyapp.android:HockeySDK:3.6.+'
...@@ -63,6 +63,8 @@ android { ...@@ -63,6 +63,8 @@ android {
} }
} }
defaultConfig.versionCode = 767
sourceSets.main { sourceSets.main {
jniLibs.srcDir 'libs' jniLibs.srcDir 'libs'
jni.srcDirs = [] //disable automatic ndk-build call jni.srcDirs = [] //disable automatic ndk-build call
...@@ -80,10 +82,38 @@ android { ...@@ -80,10 +82,38 @@ android {
manifest.srcFile 'config/foss/AndroidManifest.xml' manifest.srcFile 'config/foss/AndroidManifest.xml'
} }
productFlavors {
x86 {
ndk {
abiFilter "x86"
}
versionCode = 2
}
arm {
ndk {
abiFilter "armeabi"
}
versionCode = 0
}
armv7 {
ndk {
abiFilter "armeabi-v7a"
}
versionCode = 1
}
fat {
versionCode = 3
}
}
applicationVariants.all { variant ->
def abiVersion = variant.productFlavors.get(0).versionCode
variant.mergedFlavor.versionCode = defaultConfig.versionCode * 10 + abiVersion;
}
defaultConfig { defaultConfig {
minSdkVersion 9 minSdkVersion 9
targetSdkVersion 23 targetSdkVersion 23
versionCode 755 versionName "3.7.0"
versionName "3.6.1"
} }
} }
...@@ -235,7 +235,7 @@ include $(BUILD_STATIC_LIBRARY) ...@@ -235,7 +235,7 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := tmessages.19 LOCAL_MODULE := tmessages.20
LOCAL_CFLAGS := -w -std=c11 -Os -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 LOCAL_CFLAGS := -w -std=c11 -Os -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno
LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math -D__STDC_CONSTANT_MACROS LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math -D__STDC_CONSTANT_MACROS
......
APP_PLATFORM := android-9 APP_PLATFORM := android-9
APP_ABI := armeabi armeabi-v7a x86 APP_ABI := armeabi armeabi-v7a x86
NDK_TOOLCHAIN_VERSION := 4.8 NDK_TOOLCHAIN_VERSION := 4.9
APP_STL := gnustl_static APP_STL := gnustl_static
\ No newline at end of file
...@@ -671,8 +671,7 @@ JNIEXPORT int Java_org_telegram_messenger_MediaController_isOpusFile(JNIEnv *env ...@@ -671,8 +671,7 @@ JNIEXPORT int Java_org_telegram_messenger_MediaController_isOpusFile(JNIEnv *env
return result; return result;
} }
static inline void set_bits(uint8_t *bytes, int32_t bitOffset, int32_t numBits, int32_t value) { static inline void set_bits(uint8_t *bytes, int32_t bitOffset, int32_t value) {
numBits = (unsigned int) (2 << (numBits - 1)) - 1;
bytes += bitOffset / 8; bytes += bitOffset / 8;
bitOffset %= 8; bitOffset %= 8;
*((int32_t *) bytes) |= (value << bitOffset); *((int32_t *) bytes) |= (value << bitOffset);
...@@ -727,7 +726,7 @@ JNIEXPORT jbyteArray Java_org_telegram_messenger_MediaController_getWaveform2(JN ...@@ -727,7 +726,7 @@ JNIEXPORT jbyteArray Java_org_telegram_messenger_MediaController_getWaveform2(JN
for (int i = 0; i < resultSamples; i++) { for (int i = 0; i < resultSamples; i++) {
int32_t value = min(31, abs((int32_t) samples[i]) * 31 / peak); int32_t value = min(31, abs((int32_t) samples[i]) * 31 / peak);
set_bits(bytes, i * 5, 5, value & 31); set_bits(bytes, i * 5, value & 31);
} }
(*env)->ReleaseByteArrayElements(env, result, bytes, JNI_COMMIT); (*env)->ReleaseByteArrayElements(env, result, bytes, JNI_COMMIT);
...@@ -805,7 +804,7 @@ JNIEXPORT jbyteArray Java_org_telegram_messenger_MediaController_getWaveform(JNI ...@@ -805,7 +804,7 @@ JNIEXPORT jbyteArray Java_org_telegram_messenger_MediaController_getWaveform(JNI
for (int i = 0; i < resultSamples; i++) { for (int i = 0; i < resultSamples; i++) {
int32_t value = min(31, abs((int32_t) samples[i]) * 31 / peak); int32_t value = min(31, abs((int32_t) samples[i]) * 31 / peak);
set_bits(bytes, i * 5, 5, value & 31); set_bits(bytes, i * 5, value & 31);
} }
(*env)->ReleaseByteArrayElements(env, result, bytes, JNI_COMMIT); (*env)->ReleaseByteArrayElements(env, result, bytes, JNI_COMMIT);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <stdlib.h> #include <stdlib.h>
#include <openssl/aes.h> #include <openssl/aes.h>
#include <unistd.h>
#include "utils.h" #include "utils.h"
#include "sqlite.h" #include "sqlite.h"
#include "image.h" #include "image.h"
......
...@@ -8,8 +8,8 @@ jint sqliteOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env) { ...@@ -8,8 +8,8 @@ jint sqliteOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env) {
return JNI_VERSION_1_6; return JNI_VERSION_1_6;
} }
int Java_org_telegram_SQLite_SQLitePreparedStatement_step(JNIEnv* env, jobject object, int statementHandle) { int Java_org_telegram_SQLite_SQLitePreparedStatement_step(JNIEnv *env, jobject object, int statementHandle) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle; sqlite3_stmt *handle = (sqlite3_stmt *) statementHandle;
int errcode = sqlite3_step(handle); int errcode = sqlite3_step(handle);
if (errcode == SQLITE_ROW) { if (errcode == SQLITE_ROW) {
...@@ -23,7 +23,7 @@ int Java_org_telegram_SQLite_SQLitePreparedStatement_step(JNIEnv* env, jobject o ...@@ -23,7 +23,7 @@ int Java_org_telegram_SQLite_SQLitePreparedStatement_step(JNIEnv* env, jobject o
} }
int Java_org_telegram_SQLite_SQLitePreparedStatement_prepare(JNIEnv *env, jobject object, int sqliteHandle, jstring sql) { int Java_org_telegram_SQLite_SQLitePreparedStatement_prepare(JNIEnv *env, jobject object, int sqliteHandle, jstring sql) {
sqlite3* handle = (sqlite3 *)sqliteHandle; sqlite3 *handle = (sqlite3 *) sqliteHandle;
char const *sqlStr = (*env)->GetStringUTFChars(env, sql, 0); char const *sqlStr = (*env)->GetStringUTFChars(env, sql, 0);
...@@ -41,11 +41,11 @@ int Java_org_telegram_SQLite_SQLitePreparedStatement_prepare(JNIEnv *env, jobjec ...@@ -41,11 +41,11 @@ int Java_org_telegram_SQLite_SQLitePreparedStatement_prepare(JNIEnv *env, jobjec
(*env)->ReleaseStringUTFChars(env, sql, sqlStr); (*env)->ReleaseStringUTFChars(env, sql, sqlStr);
} }
return (int)stmt_handle; return (int) stmt_handle;
} }
void Java_org_telegram_SQLite_SQLitePreparedStatement_reset(JNIEnv *env, jobject object, int statementHandle) { void Java_org_telegram_SQLite_SQLitePreparedStatement_reset(JNIEnv *env, jobject object, int statementHandle) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle; sqlite3_stmt *handle = (sqlite3_stmt *) statementHandle;
int errcode = sqlite3_reset(handle); int errcode = sqlite3_reset(handle);
if (SQLITE_OK != errcode) { if (SQLITE_OK != errcode) {
...@@ -54,16 +54,11 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_reset(JNIEnv *env, jobject ...@@ -54,16 +54,11 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_reset(JNIEnv *env, jobject
} }
void Java_org_telegram_SQLite_SQLitePreparedStatement_finalize(JNIEnv *env, jobject object, int statementHandle) { void Java_org_telegram_SQLite_SQLitePreparedStatement_finalize(JNIEnv *env, jobject object, int statementHandle) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle; sqlite3_finalize((sqlite3_stmt *) statementHandle);
int errcode = sqlite3_finalize (handle);
if (SQLITE_OK != errcode) {
throw_sqlite3_exception(env, sqlite3_db_handle(handle), errcode);
}
} }
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindByteBuffer(JNIEnv *env, jobject object, int statementHandle, int index, jobject value, int length) { void Java_org_telegram_SQLite_SQLitePreparedStatement_bindByteBuffer(JNIEnv *env, jobject object, int statementHandle, int index, jobject value, int length) {
sqlite3_stmt *handle = (sqlite3_stmt *)statementHandle; sqlite3_stmt *handle = (sqlite3_stmt *) statementHandle;
jbyte *buf = (*env)->GetDirectBufferAddress(env, value); jbyte *buf = (*env)->GetDirectBufferAddress(env, value);
int errcode = sqlite3_bind_blob(handle, index, buf, length, SQLITE_STATIC); int errcode = sqlite3_bind_blob(handle, index, buf, length, SQLITE_STATIC);
...@@ -73,7 +68,7 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindByteBuffer(JNIEnv *env ...@@ -73,7 +68,7 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindByteBuffer(JNIEnv *env
} }
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindString(JNIEnv *env, jobject object, int statementHandle, int index, jstring value) { void Java_org_telegram_SQLite_SQLitePreparedStatement_bindString(JNIEnv *env, jobject object, int statementHandle, int index, jstring value) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle; sqlite3_stmt *handle = (sqlite3_stmt *) statementHandle;
char const *valueStr = (*env)->GetStringUTFChars(env, value, 0); char const *valueStr = (*env)->GetStringUTFChars(env, value, 0);
...@@ -88,7 +83,7 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindString(JNIEnv *env, jo ...@@ -88,7 +83,7 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindString(JNIEnv *env, jo
} }
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindInt(JNIEnv *env, jobject object, int statementHandle, int index, int value) { void Java_org_telegram_SQLite_SQLitePreparedStatement_bindInt(JNIEnv *env, jobject object, int statementHandle, int index, int value) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle; sqlite3_stmt *handle = (sqlite3_stmt *) statementHandle;
int errcode = sqlite3_bind_int(handle, index, value); int errcode = sqlite3_bind_int(handle, index, value);
if (SQLITE_OK != errcode) { if (SQLITE_OK != errcode) {
...@@ -97,7 +92,7 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindInt(JNIEnv *env, jobje ...@@ -97,7 +92,7 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindInt(JNIEnv *env, jobje
} }
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindLong(JNIEnv *env, jobject object, int statementHandle, int index, long long value) { void Java_org_telegram_SQLite_SQLitePreparedStatement_bindLong(JNIEnv *env, jobject object, int statementHandle, int index, long long value) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle; sqlite3_stmt *handle = (sqlite3_stmt *) statementHandle;
int errcode = sqlite3_bind_int64(handle, index, value); int errcode = sqlite3_bind_int64(handle, index, value);
if (SQLITE_OK != errcode) { if (SQLITE_OK != errcode) {
...@@ -105,8 +100,8 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindLong(JNIEnv *env, jobj ...@@ -105,8 +100,8 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindLong(JNIEnv *env, jobj
} }
} }
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindDouble(JNIEnv* env, jobject object, int statementHandle, int index, double value) { void Java_org_telegram_SQLite_SQLitePreparedStatement_bindDouble(JNIEnv *env, jobject object, int statementHandle, int index, double value) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle; sqlite3_stmt *handle = (sqlite3_stmt *) statementHandle;
int errcode = sqlite3_bind_double(handle, index, value); int errcode = sqlite3_bind_double(handle, index, value);
if (SQLITE_OK != errcode) { if (SQLITE_OK != errcode) {
...@@ -114,8 +109,8 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindDouble(JNIEnv* env, jo ...@@ -114,8 +109,8 @@ void Java_org_telegram_SQLite_SQLitePreparedStatement_bindDouble(JNIEnv* env, jo
} }
} }
void Java_org_telegram_SQLite_SQLitePreparedStatement_bindNull(JNIEnv* env, jobject object, int statementHandle, int index) { void Java_org_telegram_SQLite_SQLitePreparedStatement_bindNull(JNIEnv *env, jobject object, int statementHandle, int index) {
sqlite3_stmt *handle = (sqlite3_stmt*)statementHandle; sqlite3_stmt *handle = (sqlite3_stmt *) statementHandle;
int errcode = sqlite3_bind_null(handle, index); int errcode = sqlite3_bind_null(handle, index);
if (SQLITE_OK != errcode) { if (SQLITE_OK != errcode) {
......
...@@ -57,7 +57,7 @@ void Connection::suspendConnection() { ...@@ -57,7 +57,7 @@ void Connection::suspendConnection() {
} }
void Connection::onReceivedData(NativeByteBuffer *buffer) { void Connection::onReceivedData(NativeByteBuffer *buffer) {
//AES_ctr128_encrypt(buffer->bytes(), buffer->bytes(), buffer->limit(), &decryptKey, decryptIv, decryptCount, &decryptNum); AES_ctr128_encrypt(buffer->bytes(), buffer->bytes(), buffer->limit(), &decryptKey, decryptIv, decryptCount, &decryptNum);
failedConnectionCount = 0; failedConnectionCount = 0;
...@@ -323,11 +323,11 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck) { ...@@ -323,11 +323,11 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck) {
uint32_t val = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0]); uint32_t val = (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | (bytes[0]);
uint32_t val2 = (bytes[7] << 24) | (bytes[6] << 16) | (bytes[5] << 8) | (bytes[4]); uint32_t val2 = (bytes[7] << 24) | (bytes[6] << 16) | (bytes[5] << 8) | (bytes[4]);
if (bytes[0] != 0xef && val != 0x44414548 && val != 0x54534f50 && val != 0x20544547 && val != 0x4954504f && val != 0xeeeeeeee && val2 != 0x00000000) { if (bytes[0] != 0xef && val != 0x44414548 && val != 0x54534f50 && val != 0x20544547 && val != 0x4954504f && val != 0xeeeeeeee && val2 != 0x00000000) {
//bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xef; bytes[56] = bytes[57] = bytes[58] = bytes[59] = 0xef;
break; break;
} }
} }
/*for (int a = 0; a < 48; a++) { for (int a = 0; a < 48; a++) {
temp[a] = bytes[55 - a]; temp[a] = bytes[55 - a];
} }
...@@ -348,7 +348,7 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck) { ...@@ -348,7 +348,7 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck) {
memcpy(decryptIv, temp + 32, 16); memcpy(decryptIv, temp + 32, 16);
AES_ctr128_encrypt(bytes, temp, 64, &encryptKey, encryptIv, encryptCount, &encryptNum); AES_ctr128_encrypt(bytes, temp, 64, &encryptKey, encryptIv, encryptCount, &encryptNum);
memcpy(bytes + 56, temp + 56, 8);*/ memcpy(bytes + 56, temp + 56, 8);
firstPacketSent = true; firstPacketSent = true;
} }
...@@ -358,7 +358,7 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck) { ...@@ -358,7 +358,7 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck) {
} }
buffer->writeByte((uint8_t) packetLength); buffer->writeByte((uint8_t) packetLength);
bytes += (buffer->limit() - 1); bytes += (buffer->limit() - 1);
//AES_ctr128_encrypt(bytes, bytes, 1, &encryptKey, encryptIv, encryptCount, &encryptNum); AES_ctr128_encrypt(bytes, bytes, 1, &encryptKey, encryptIv, encryptCount, &encryptNum);
} else { } else {
packetLength = (packetLength << 8) + 0x7f; packetLength = (packetLength << 8) + 0x7f;
if (reportAck) { if (reportAck) {
...@@ -366,13 +366,13 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck) { ...@@ -366,13 +366,13 @@ void Connection::sendData(NativeByteBuffer *buff, bool reportAck) {
} }
buffer->writeInt32(packetLength); buffer->writeInt32(packetLength);
bytes += (buffer->limit() - 4); bytes += (buffer->limit() - 4);
//AES_ctr128_encrypt(bytes, bytes, 4, &encryptKey, encryptIv, encryptCount, &encryptNum); AES_ctr128_encrypt(bytes, bytes, 4, &encryptKey, encryptIv, encryptCount, &encryptNum);
} }
buffer->rewind(); buffer->rewind();
writeBuffer(buffer); writeBuffer(buffer);
buff->rewind(); buff->rewind();
//AES_ctr128_encrypt(buff->bytes(), buff->bytes(), buff->limit(), &encryptKey, encryptIv, encryptCount, &encryptNum); AES_ctr128_encrypt(buff->bytes(), buff->bytes(), buff->limit(), &encryptKey, encryptIv, encryptCount, &encryptNum);
writeBuffer(buff); writeBuffer(buff);
} }
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#define USE_DEBUG_SESSION false #define USE_DEBUG_SESSION false
#define READ_BUFFER_SIZE 1024 * 128 #define READ_BUFFER_SIZE 1024 * 128
//#define DEBUG_VERSION #define DEBUG_VERSION
#define DEFAULT_DATACENTER_ID INT_MAX #define DEFAULT_DATACENTER_ID INT_MAX
#define DC_UPDATE_TIME 60 * 60 #define DC_UPDATE_TIME 60 * 60
#define DOWNLOAD_CONNECTIONS_COUNT 2 #define DOWNLOAD_CONNECTIONS_COUNT 2
......
...@@ -99,6 +99,8 @@ ...@@ -99,6 +99,8 @@
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:host="telegram.me" android:scheme="http" /> <data android:host="telegram.me" android:scheme="http" />
<data android:host="telegram.me" android:scheme="https" /> <data android:host="telegram.me" android:scheme="https" />
<data android:host="telegram.dog" android:scheme="http" />
<data android:host="telegram.dog" android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter android:icon="@drawable/ic_launcher" android:priority="1"> <intent-filter android:icon="@drawable/ic_launcher" android:priority="1">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
......
...@@ -11,6 +11,7 @@ package org.telegram.messenger; ...@@ -11,6 +11,7 @@ package org.telegram.messenger;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.ContentUris; import android.content.ContentUris;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
...@@ -19,6 +20,7 @@ import android.content.pm.ActivityInfo; ...@@ -19,6 +20,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.database.Cursor; import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
...@@ -26,6 +28,7 @@ import android.graphics.Typeface; ...@@ -26,6 +28,7 @@ import android.graphics.Typeface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.Parcelable; import android.os.Parcelable;
import android.provider.Browser; import android.provider.Browser;
...@@ -84,7 +87,9 @@ public class AndroidUtilities { ...@@ -84,7 +87,9 @@ public class AndroidUtilities {
private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>(); private static final Hashtable<String, Typeface> typefaceCache = new Hashtable<>();
private static int prevOrientation = -10; private static int prevOrientation = -10;
private static boolean waitingForSms = false; private static boolean waitingForSms = false;
private static boolean waitingForCall = false;
private static final Object smsLock = new Object(); private static final Object smsLock = new Object();
private static final Object callLock = new Object();
public static int statusBarHeight = 0; public static int statusBarHeight = 0;
public static float density = 1; public static float density = 1;
...@@ -240,6 +245,20 @@ public class AndroidUtilities { ...@@ -240,6 +245,20 @@ public class AndroidUtilities {
} }
} }
public static boolean isWaitingForCall() {
boolean value;
synchronized (callLock) {
value = waitingForCall;
}
return value;
}
public static void setWaitingForCall(boolean value) {
synchronized (callLock) {
waitingForCall = value;
}
}
public static void showKeyboard(View view) { public static void showKeyboard(View view) {
if (view == null) { if (view == null) {
return; return;
...@@ -422,11 +441,28 @@ public class AndroidUtilities { ...@@ -422,11 +441,28 @@ public class AndroidUtilities {
if (context == null || uri == null) { if (context == null || uri == null) {
return; return;
} }
try { try {
Intent intent = new Intent(Intent.ACTION_VIEW, uri); Intent intent = new Intent(Intent.ACTION_VIEW, uri);
if (MediaController.getInstance().canCustomTabs()) {
intent.putExtra("android.support.customtabs.extra.SESSION", (Parcelable) null); intent.putExtra("android.support.customtabs.extra.SESSION", (Parcelable) null);
intent.putExtra("android.support.customtabs.extra.TOOLBAR_COLOR", 0xff54759e); intent.putExtra("android.support.customtabs.extra.TOOLBAR_COLOR", 0xff54759e);
intent.putExtra("android.support.customtabs.extra.TITLE_VISIBILITY", 1); intent.putExtra("android.support.customtabs.extra.TITLE_VISIBILITY", 1);
Intent actionIntent = new Intent(Intent.ACTION_SEND);
actionIntent.setType("text/plain");
actionIntent.putExtra(Intent.EXTRA_TEXT, uri.toString());
actionIntent.putExtra(Intent.EXTRA_SUBJECT, "");
PendingIntent pendingIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, actionIntent, PendingIntent.FLAG_ONE_SHOT);
Bundle bundle = new Bundle();
bundle.putInt("android.support.customtabs.customaction.ID", 0);
bundle.putParcelable("android.support.customtabs.customaction.ICON", BitmapFactory.decodeResource(context.getResources(), R.drawable.abc_ic_menu_share_mtrl_alpha));
bundle.putString("android.support.customtabs.customaction.DESCRIPTION", LocaleController.getString("ShareFile", R.string.ShareFile));
bundle.putParcelable("android.support.customtabs.customaction.PENDING_INTENT", pendingIntent);
intent.putExtra("android.support.customtabs.extra.ACTION_BUTTON_BUNDLE", bundle);
intent.putExtra("android.support.customtabs.extra.TINT_ACTION_BUTTON", false);
}
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
context.startActivity(intent); context.startActivity(intent);
} catch (Exception e) { } catch (Exception e) {
...@@ -917,7 +953,11 @@ public class AndroidUtilities { ...@@ -917,7 +953,11 @@ public class AndroidUtilities {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null); cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column); final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index); String value = cursor.getString(column_index);
if (value.startsWith("content://") || !value.startsWith("/") && !value.startsWith("file://")) {
return null;
}
return value;
} }
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
......
...@@ -37,6 +37,8 @@ import org.telegram.ui.Components.ForegroundDetector; ...@@ -37,6 +37,8 @@ import org.telegram.ui.Components.ForegroundDetector;
import java.io.File; import java.io.File;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Locale;
public class ApplicationLoader extends Application { public class ApplicationLoader extends Application {
......
...@@ -10,8 +10,8 @@ package org.telegram.messenger; ...@@ -10,8 +10,8 @@ package org.telegram.messenger;
public class BuildVars { public class BuildVars {
public static boolean DEBUG_VERSION = false; public static boolean DEBUG_VERSION = false;
public static int BUILD_VERSION = 753; public static int BUILD_VERSION = 767;
public static String BUILD_VERSION_STRING = "3.6"; public static String BUILD_VERSION_STRING = "3.7";
public static int APP_ID = 0; //obtain your own APP_ID at https://core.telegram.org/api/obtaining_api_id public static int APP_ID = 0; //obtain your own APP_ID at https://core.telegram.org/api/obtaining_api_id
public static String APP_HASH = ""; //obtain your own APP_HASH at https://core.telegram.org/api/obtaining_api_id public static String APP_HASH = ""; //obtain your own APP_HASH at https://core.telegram.org/api/obtaining_api_id
public static String HOCKEY_APP_HASH = "your-hockeyapp-api-key-here"; public static String HOCKEY_APP_HASH = "your-hockeyapp-api-key-here";
......
...@@ -11,20 +11,24 @@ package org.telegram.messenger; ...@@ -11,20 +11,24 @@ package org.telegram.messenger;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import org.telegram.PhoneFormat.PhoneFormat;
public class CallReceiver extends BroadcastReceiver { public class CallReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(final Context context, Intent intent) { public void onReceive(final Context context, Intent intent) {
/*TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new PhoneStateListener() { telephony.listen(new PhoneStateListener() {
@Override @Override
public void onCallStateChanged(int state, String incomingNumber) { public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber); super.onCallStateChanged(state, incomingNumber);
if (state == 1 && incomingNumber != null && incomingNumber.length() > 0) { if (state == 1 && incomingNumber != null && incomingNumber.length() > 0) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceiveCall, incomingNumber); NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceiveCall, PhoneFormat.stripExceptNumbers(incomingNumber));
} }
} }
}, PhoneStateListener.LISTEN_CALL_STATE);*/ }, PhoneStateListener.LISTEN_CALL_STATE);
} }
} }
...@@ -265,9 +265,9 @@ public class Emoji { ...@@ -265,9 +265,9 @@ public class Emoji {
b = getBounds(); b = getBounds();
} }
if (!canvas.quickReject(b.left, b.top, b.right, b.bottom, Canvas.EdgeType.AA)) { //if (!canvas.quickReject(b.left, b.top, b.right, b.bottom, Canvas.EdgeType.AA)) {
canvas.drawBitmap(emojiBmp[info.page][info.page2], info.rect, b, paint); canvas.drawBitmap(emojiBmp[info.page][info.page2], info.rect, b, paint);
} //}
} }
@Override @Override
......
...@@ -550,7 +550,8 @@ public class FileLoader { ...@@ -550,7 +550,8 @@ public class FileLoader {
return getAttachFileName(sizeFull); return getAttachFileName(sizeFull);
} }
} }
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage && message.media.webpage.photo != null) { } else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = message.media.webpage.photo.sizes; ArrayList<TLRPC.PhotoSize> sizes = message.media.webpage.photo.sizes;
if (sizes.size() > 0) { if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize()); TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize());
...@@ -558,6 +559,9 @@ public class FileLoader { ...@@ -558,6 +559,9 @@ public class FileLoader {
return getAttachFileName(sizeFull); return getAttachFileName(sizeFull);
} }
} }
} else if (message.media.webpage.document != null) {
return getAttachFileName(message.media.webpage.document);
}
} }
} }
return ""; return "";
...@@ -588,7 +592,8 @@ public class FileLoader { ...@@ -588,7 +592,8 @@ public class FileLoader {
return getPathToAttach(sizeFull); return getPathToAttach(sizeFull);
} }
} }
} else if (message.media instanceof TLRPC.TL_messageMediaWebPage && message.media.webpage.photo != null) { } else if (message.media instanceof TLRPC.TL_messageMediaWebPage) {
if (message.media.webpage.photo != null) {
ArrayList<TLRPC.PhotoSize> sizes = message.media.webpage.photo.sizes; ArrayList<TLRPC.PhotoSize> sizes = message.media.webpage.photo.sizes;
if (sizes.size() > 0) { if (sizes.size() > 0) {
TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize()); TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize());
...@@ -596,6 +601,9 @@ public class FileLoader { ...@@ -596,6 +601,9 @@ public class FileLoader {
return getPathToAttach(sizeFull); return getPathToAttach(sizeFull);
} }
} }
} else if (message.media.webpage.document != null) {
return getPathToAttach(message.media.webpage.document);
}
} }
} }
return new File(""); return new File("");
...@@ -704,6 +712,23 @@ public class FileLoader { ...@@ -704,6 +712,23 @@ public class FileLoader {
return ""; return "";
} }
public static String getDocumentExtension(TLRPC.Document document) {
String fileName = getDocumentFileName(document);
int idx = fileName.lastIndexOf(".");
String ext = null;
if (idx != -1) {
ext = fileName.substring(idx + 1);
}
if (ext == null || ext.length() == 0) {
ext = document.mime_type;
}
if (ext == null) {
ext = "";
}
ext = ext.toUpperCase();
return ext;
}
public static String getAttachFileName(TLObject attach) { public static String getAttachFileName(TLObject attach) {
return getAttachFileName(attach, null); return getAttachFileName(attach, null);
} }
......
...@@ -196,7 +196,9 @@ public class FileLog { ...@@ -196,7 +196,9 @@ public class FileLog {
File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null); File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null);
File dir = new File (sdCard.getAbsolutePath() + "/logs"); File dir = new File (sdCard.getAbsolutePath() + "/logs");
File[] files = dir.listFiles(); File[] files = dir.listFiles();
for (File file : files) { if (files != null) {
for (int a = 0; a < files.length; a++) {
File file = files[a];
if (getInstance().currentFile != null && file.getAbsolutePath().equals(getInstance().currentFile.getAbsolutePath())) { if (getInstance().currentFile != null && file.getAbsolutePath().equals(getInstance().currentFile.getAbsolutePath())) {
continue; continue;
} }
...@@ -206,4 +208,5 @@ public class FileLog { ...@@ -206,4 +208,5 @@ public class FileLog {
file.delete(); file.delete();
} }
} }
}
} }
...@@ -23,7 +23,6 @@ import android.net.Uri; ...@@ -23,7 +23,6 @@ import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore; import android.provider.MediaStore;
import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ConnectionsManager;
...@@ -33,7 +32,6 @@ import org.telegram.ui.Components.AnimatedFileDrawable; ...@@ -33,7 +32,6 @@ import org.telegram.ui.Components.AnimatedFileDrawable;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
...@@ -2031,8 +2029,7 @@ public class ImageLoader { ...@@ -2031,8 +2029,7 @@ public class ImageLoader {
public static Bitmap loadBitmap(String path, Uri uri, float maxWidth, float maxHeight, boolean useMaxScale) { public static Bitmap loadBitmap(String path, Uri uri, float maxWidth, float maxHeight, boolean useMaxScale) {
BitmapFactory.Options bmOptions = new BitmapFactory.Options(); BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true; bmOptions.inJustDecodeBounds = true;
FileDescriptor fileDescriptor = null; InputStream inputStream = null;
ParcelFileDescriptor parcelFD = null;
if (path == null && uri != null && uri.getScheme() != null) { if (path == null && uri != null && uri.getScheme() != null) {
String imageFilePath = null; String imageFilePath = null;
...@@ -2052,9 +2049,10 @@ public class ImageLoader { ...@@ -2052,9 +2049,10 @@ public class ImageLoader {
} else if (uri != null) { } else if (uri != null) {
boolean error = false; boolean error = false;
try { try {
parcelFD = ApplicationLoader.applicationContext.getContentResolver().openFileDescriptor(uri, "r"); inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri);
fileDescriptor = parcelFD.getFileDescriptor(); BitmapFactory.decodeStream(inputStream, null, bmOptions);
BitmapFactory.decodeFileDescriptor(fileDescriptor, null, bmOptions); inputStream.close();
inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri);
} catch (Throwable e) { } catch (Throwable e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
return null; return null;
...@@ -2138,7 +2136,7 @@ public class ImageLoader { ...@@ -2138,7 +2136,7 @@ public class ImageLoader {
} }
} else if (uri != null) { } else if (uri != null) {
try { try {
b = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, bmOptions); b = BitmapFactory.decodeStream(inputStream, null, bmOptions);
if (b != null) { if (b != null) {
if (bmOptions.inPurgeable) { if (bmOptions.inPurgeable) {
Utilities.pinBitmap(b); Utilities.pinBitmap(b);
...@@ -2153,7 +2151,7 @@ public class ImageLoader { ...@@ -2153,7 +2151,7 @@ public class ImageLoader {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
} finally { } finally {
try { try {
parcelFD.close(); inputStream.close();
} catch (Throwable e) { } catch (Throwable e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
} }
......
...@@ -322,7 +322,7 @@ public class LocaleController { ...@@ -322,7 +322,7 @@ public class LocaleController {
StringBuilder result = new StringBuilder(11); StringBuilder result = new StringBuilder(11);
result.append(languageCode); result.append(languageCode);
if (countryCode.length() > 0 || variantCode.length() > 0) { if (countryCode.length() > 0 || variantCode.length() > 0) {
result.append('_'); result.append('-');
} }
result.append(countryCode); result.append(countryCode);
if (variantCode.length() > 0) { if (variantCode.length() > 0) {
...@@ -664,6 +664,7 @@ public class LocaleController { ...@@ -664,6 +664,7 @@ public class LocaleController {
} }
public static String formatDateChat(long date) { public static String formatDateChat(long date) {
try {
Calendar rightNow = Calendar.getInstance(); Calendar rightNow = Calendar.getInstance();
int year = rightNow.get(Calendar.YEAR); int year = rightNow.get(Calendar.YEAR);
...@@ -674,6 +675,10 @@ public class LocaleController { ...@@ -674,6 +675,10 @@ public class LocaleController {
return getInstance().chatDate.format(date * 1000); return getInstance().chatDate.format(date * 1000);
} }
return getInstance().chatFullDate.format(date * 1000); return getInstance().chatFullDate.format(date * 1000);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
return "LOC_ERR: formatDateChat";
} }
public static String formatDate(long date) { public static String formatDate(long date) {
...@@ -697,7 +702,7 @@ public class LocaleController { ...@@ -697,7 +702,7 @@ public class LocaleController {
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
} }
return "LOC_ERR"; return "LOC_ERR: formatDate";
} }
public static String formatDateAudio(long date) { public static String formatDateAudio(long date) {
......
...@@ -23,7 +23,7 @@ import java.util.zip.ZipFile; ...@@ -23,7 +23,7 @@ import java.util.zip.ZipFile;
public class NativeLoader { public class NativeLoader {
private final static int LIB_VERSION = 19; private final static int LIB_VERSION = 20;
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";
......
...@@ -53,6 +53,7 @@ public class NotificationCenter { ...@@ -53,6 +53,7 @@ public class NotificationCenter {
public static final int didSetTwoStepPassword = totalEvents++; public static final int didSetTwoStepPassword = totalEvents++;
public static final int screenStateChanged = totalEvents++; public static final int screenStateChanged = totalEvents++;
public static final int didLoadedReplyMessages = totalEvents++; public static final int didLoadedReplyMessages = totalEvents++;
public static final int didLoadedPinnedMessage = totalEvents++;
public static final int newSessionReceived = totalEvents++; public static final int newSessionReceived = totalEvents++;
public static final int didReceivedWebpages = totalEvents++; public static final int didReceivedWebpages = totalEvents++;
public static final int didReceivedWebpagesInUpdates = totalEvents++; public static final int didReceivedWebpagesInUpdates = totalEvents++;
...@@ -60,6 +61,7 @@ public class NotificationCenter { ...@@ -60,6 +61,7 @@ public class NotificationCenter {
public static final int didReplacedPhotoInMemCache = totalEvents++; public static final int didReplacedPhotoInMemCache = totalEvents++;
public static final int messagesReadContent = totalEvents++; public static final int messagesReadContent = totalEvents++;
public static final int botInfoDidLoaded = totalEvents++; public static final int botInfoDidLoaded = totalEvents++;
public static final int userInfoDidLoaded = totalEvents++;
public static final int botKeyboardDidLoaded = totalEvents++; public static final int botKeyboardDidLoaded = totalEvents++;
public static final int chatSearchResultsAvailable = totalEvents++; public static final int chatSearchResultsAvailable = totalEvents++;
public static final int musicDidLoaded = totalEvents++; public static final int musicDidLoaded = totalEvents++;
...@@ -67,6 +69,7 @@ public class NotificationCenter { ...@@ -67,6 +69,7 @@ public class NotificationCenter {
public static final int didUpdatedMessagesViews = totalEvents++; public static final int didUpdatedMessagesViews = totalEvents++;
public static final int needReloadRecentDialogsSearch = totalEvents++; public static final int needReloadRecentDialogsSearch = totalEvents++;
public static final int locationPermissionGranted = totalEvents++; public static final int locationPermissionGranted = totalEvents++;
public static final int peerSettingsDidLoaded = totalEvents++;
public static final int httpFileDidLoaded = totalEvents++; public static final int httpFileDidLoaded = totalEvents++;
public static final int httpFileDidFailedLoad = totalEvents++; public static final int httpFileDidFailedLoad = totalEvents++;
......
...@@ -820,6 +820,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ...@@ -820,6 +820,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
req.message = message; req.message = message;
req.id = messageObject.getId(); req.id = messageObject.getId();
req.no_webpage = !searchLinks; req.no_webpage = !searchLinks;
FileLog.d("tmessages", "try to edit message " + req.id + " in channel " + req.channel.channel_id + " hash " + req.channel.access_hash + " message " + req.message);
final int reqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { final int reqId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() {
@Override @Override
public void run(TLObject response, TLRPC.TL_error error) { public void run(TLObject response, TLRPC.TL_error error) {
...@@ -2002,6 +2003,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ...@@ -2002,6 +2003,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
if (!isSentError) { if (!isSentError) {
newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, (isBroadcast ? oldId : newMsgObj.id), newMsgObj, newMsgObj.dialog_id); //TODO remove later?
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
...@@ -2274,7 +2276,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ...@@ -2274,7 +2276,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
if (extension == null) { if (extension == null) {
extension = "txt"; extension = "txt";
} }
path = MediaController.copyDocumentToCache(uri, extension); path = MediaController.copyFileToCache(uri, extension);
if (path == null) { if (path == null) {
return false; return false;
} }
...@@ -2923,12 +2925,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ...@@ -2923,12 +2925,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
if (MediaController.isGif(uri)) { if (MediaController.isGif(uri)) {
isDocument = true; isDocument = true;
originalPath = uri.toString(); originalPath = uri.toString();
tempPath = MediaController.copyDocumentToCache(uri, "gif"); tempPath = MediaController.copyFileToCache(uri, "gif");
extension = "gif"; extension = "gif";
} else if (MediaController.isWebp(uri)) { } else if (MediaController.isWebp(uri)) {
isDocument = true; isDocument = true;
originalPath = uri.toString(); originalPath = uri.toString();
tempPath = MediaController.copyDocumentToCache(uri, "webp"); tempPath = MediaController.copyFileToCache(uri, "webp");
extension = "webp"; extension = "webp";
} }
} }
...@@ -3009,8 +3011,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ...@@ -3009,8 +3011,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter
} }
TLRPC.TL_document document = null; TLRPC.TL_document document = null;
if (!isEncrypted) { if (!isEncrypted) {
TLObject object = MessagesStorage.getInstance().getSentFile(originalPath, !isEncrypted ? 2 : 5); //document = (TLRPC.TL_document) MessagesStorage.getInstance().getSentFile(originalPath, !isEncrypted ? 2 : 5);
document = (TLRPC.TL_document) object;
} }
if (document == null) { if (document == null) {
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND); Bitmap thumb = ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND);
......
...@@ -9,8 +9,10 @@ ...@@ -9,8 +9,10 @@
package org.telegram.messenger; package org.telegram.messenger;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.BitmapShader; import android.graphics.BitmapShader;
...@@ -48,6 +50,11 @@ public class TgChooserTargetService extends ChooserTargetService { ...@@ -48,6 +50,11 @@ public class TgChooserTargetService extends ChooserTargetService {
if (!UserConfig.isClientActivated()) { if (!UserConfig.isClientActivated()) {
return targets; return targets;
} }
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
if (!preferences.getBoolean("direct_share", true)) {
return targets;
}
ImageLoader imageLoader = ImageLoader.getInstance(); ImageLoader imageLoader = ImageLoader.getInstance();
final Semaphore semaphore = new Semaphore(0); final Semaphore semaphore = new Semaphore(0);
final ComponentName componentName = new ComponentName(getPackageName(), LaunchActivity.class.getCanonicalName()); final ComponentName componentName = new ComponentName(getPackageName(), LaunchActivity.class.getCanonicalName());
......
...@@ -179,7 +179,7 @@ public class BotQuery { ...@@ -179,7 +179,7 @@ public class BotQuery {
} }
public static void putBotInfo(final TLRPC.BotInfo botInfo) { public static void putBotInfo(final TLRPC.BotInfo botInfo) {
if (botInfo == null || botInfo instanceof TLRPC.TL_botInfoEmpty) { if (botInfo == null) {
return; return;
} }
botInfos.put(botInfo.user_id, botInfo); botInfos.put(botInfo.user_id, botInfo);
......
...@@ -22,9 +22,6 @@ import android.util.Log; ...@@ -22,9 +22,6 @@ import android.util.Log;
import android.util.SparseBooleanArray; import android.util.SparseBooleanArray;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import org.telegram.messenger.support.util.ThreadUtil;
import org.telegram.messenger.support.util.TileList;
/** /**
* A utility class that supports asynchronous content loading. * A utility class that supports asynchronous content loading.
* <p> * <p>
...@@ -42,7 +39,7 @@ import org.telegram.messenger.support.util.TileList; ...@@ -42,7 +39,7 @@ import org.telegram.messenger.support.util.TileList;
* Note that this class uses a single thread to load the data, so it suitable to load data from * Note that this class uses a single thread to load the data, so it suitable to load data from
* secondary storage such as disk, but not from network. * secondary storage such as disk, but not from network.
* <p> * <p>
* This class is designed to work with {@link org.telegram.messenger.support.widget.RecyclerView}, but it does * This class is designed to work with {@link android.support.v7.widget.RecyclerView}, but it does
* not depend on it and can be used with other list views. * not depend on it and can be used with other list views.
* *
*/ */
...@@ -113,7 +110,7 @@ public class AsyncListUtil<T> { ...@@ -113,7 +110,7 @@ public class AsyncListUtil<T> {
* <p> * <p>
* Identifies the data items that have not been loaded yet and initiates loading them in the * Identifies the data items that have not been loaded yet and initiates loading them in the
* background. Should be called from the view's scroll listener (such as * background. Should be called from the view's scroll listener (such as
* {@link org.telegram.messenger.support.widget.RecyclerView.OnScrollListener#onScrolled}). * {@link android.support.v7.widget.RecyclerView.OnScrollListener#onScrolled}).
*/ */
public void onRangeChanged() { public void onRangeChanged() {
if (isRefreshPending()) { if (isRefreshPending()) {
......
...@@ -18,10 +18,11 @@ package org.telegram.messenger.support.util; ...@@ -18,10 +18,11 @@ package org.telegram.messenger.support.util;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.support.v4.content.ParallelExecutorCompat;
import android.util.Log; import android.util.Log;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean;
class MessageThreadUtil<T> implements ThreadUtil<T> { class MessageThreadUtil<T> implements ThreadUtil<T> {
...@@ -83,7 +84,8 @@ class MessageThreadUtil<T> implements ThreadUtil<T> { ...@@ -83,7 +84,8 @@ class MessageThreadUtil<T> implements ThreadUtil<T> {
public BackgroundCallback<T> getBackgroundProxy(final BackgroundCallback<T> callback) { public BackgroundCallback<T> getBackgroundProxy(final BackgroundCallback<T> callback) {
return new BackgroundCallback<T>() { return new BackgroundCallback<T>() {
final private MessageQueue mQueue = new MessageQueue(); final private MessageQueue mQueue = new MessageQueue();
final private Executor mExecutor = Executors.newSingleThreadExecutor(); final private Executor mExecutor = ParallelExecutorCompat.getParallelExecutor();
AtomicBoolean mBackgroundRunning = new AtomicBoolean(false);
private static final int REFRESH = 1; private static final int REFRESH = 1;
private static final int UPDATE_RANGE = 2; private static final int UPDATE_RANGE = 2;
...@@ -114,20 +116,27 @@ class MessageThreadUtil<T> implements ThreadUtil<T> { ...@@ -114,20 +116,27 @@ class MessageThreadUtil<T> implements ThreadUtil<T> {
private void sendMessage(SyncQueueItem msg) { private void sendMessage(SyncQueueItem msg) {
mQueue.sendMessage(msg); mQueue.sendMessage(msg);
mExecutor.execute(mBackgroundRunnable); maybeExecuteBackgroundRunnable();
} }
private void sendMessageAtFrontOfQueue(SyncQueueItem msg) { private void sendMessageAtFrontOfQueue(SyncQueueItem msg) {
mQueue.sendMessageAtFrontOfQueue(msg); mQueue.sendMessageAtFrontOfQueue(msg);
maybeExecuteBackgroundRunnable();
}
private void maybeExecuteBackgroundRunnable() {
if (mBackgroundRunning.compareAndSet(false, true)) {
mExecutor.execute(mBackgroundRunnable); mExecutor.execute(mBackgroundRunnable);
} }
}
private Runnable mBackgroundRunnable = new Runnable() { private Runnable mBackgroundRunnable = new Runnable() {
@Override @Override
public void run() { public void run() {
while (true) {
SyncQueueItem msg = mQueue.next(); SyncQueueItem msg = mQueue.next();
if (msg == null) { if (msg == null) {
return; break;
} }
switch (msg.what) { switch (msg.what) {
case REFRESH: case REFRESH:
...@@ -151,6 +160,8 @@ class MessageThreadUtil<T> implements ThreadUtil<T> { ...@@ -151,6 +160,8 @@ class MessageThreadUtil<T> implements ThreadUtil<T> {
Log.e("ThreadUtil", "Unsupported message, what=" + msg.what); Log.e("ThreadUtil", "Unsupported message, what=" + msg.what);
} }
} }
mBackgroundRunning.set(false);
}
}; };
}; };
} }
......
...@@ -24,7 +24,7 @@ import java.util.Comparator; ...@@ -24,7 +24,7 @@ import java.util.Comparator;
/** /**
* A Sorted list implementation that can keep items in order and also notify for changes in the * A Sorted list implementation that can keep items in order and also notify for changes in the
* list * list
* such that it can be bound to a {@link org.telegram.messenger.support.widget.RecyclerView.Adapter * such that it can be bound to a {@link android.support.v7.widget.RecyclerView.Adapter
* RecyclerView.Adapter}. * RecyclerView.Adapter}.
* <p> * <p>
* It keeps items ordered using the {@link Callback#compare(Object, Object)} method and uses * It keeps items ordered using the {@link Callback#compare(Object, Object)} method and uses
...@@ -737,7 +737,7 @@ public class SortedList<T> { ...@@ -737,7 +737,7 @@ public class SortedList<T> {
* so * so
* that you can change its behavior depending on your UI. * that you can change its behavior depending on your UI.
* <p> * <p>
* For example, if you are using SortedList with a {@link org.telegram.messenger.support.widget.RecyclerView.Adapter * For example, if you are using SortedList with a {@link android.support.v7.widget.RecyclerView.Adapter
* RecyclerView.Adapter}, you should * RecyclerView.Adapter}, you should
* return whether the items' visual representations are the same or not. * return whether the items' visual representations are the same or not.
* *
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
package org.telegram.messenger.support.util; package org.telegram.messenger.support.util;
import org.telegram.messenger.support.util.TileList;
interface ThreadUtil<T> { interface ThreadUtil<T> {
interface MainThreadCallback<T> { interface MainThreadCallback<T> {
......
...@@ -19,9 +19,6 @@ package org.telegram.messenger.support.widget; ...@@ -19,9 +19,6 @@ package org.telegram.messenger.support.widget;
import android.support.v4.util.Pools; import android.support.v4.util.Pools;
import android.util.Log; import android.util.Log;
import org.telegram.messenger.support.widget.OpReorderer;
import org.telegram.messenger.support.widget.RecyclerView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
...@@ -70,6 +67,8 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -70,6 +67,8 @@ class AdapterHelper implements OpReorderer.Callback {
final OpReorderer mOpReorderer; final OpReorderer mOpReorderer;
private int mExistingUpdateTypes = 0;
AdapterHelper(Callback callback) { AdapterHelper(Callback callback) {
this(callback, false); this(callback, false);
} }
...@@ -88,6 +87,7 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -88,6 +87,7 @@ class AdapterHelper implements OpReorderer.Callback {
void reset() { void reset() {
recycleUpdateOpsAndClearList(mPendingUpdates); recycleUpdateOpsAndClearList(mPendingUpdates);
recycleUpdateOpsAndClearList(mPostponedList); recycleUpdateOpsAndClearList(mPostponedList);
mExistingUpdateTypes = 0;
} }
void preProcess() { void preProcess() {
...@@ -122,6 +122,7 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -122,6 +122,7 @@ class AdapterHelper implements OpReorderer.Callback {
mCallback.onDispatchSecondPass(mPostponedList.get(i)); mCallback.onDispatchSecondPass(mPostponedList.get(i));
} }
recycleUpdateOpsAndClearList(mPostponedList); recycleUpdateOpsAndClearList(mPostponedList);
mExistingUpdateTypes = 0;
} }
private void applyMove(UpdateOp op) { private void applyMove(UpdateOp op) {
...@@ -460,6 +461,10 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -460,6 +461,10 @@ class AdapterHelper implements OpReorderer.Callback {
return mPendingUpdates.size() > 0; return mPendingUpdates.size() > 0;
} }
boolean hasAnyUpdateTypes(int updateTypes) {
return (mExistingUpdateTypes & updateTypes) != 0;
}
int findPositionOffset(int position) { int findPositionOffset(int position) {
return findPositionOffset(position, 0); return findPositionOffset(position, 0);
} }
...@@ -498,6 +503,7 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -498,6 +503,7 @@ class AdapterHelper implements OpReorderer.Callback {
*/ */
boolean onItemRangeChanged(int positionStart, int itemCount, Object payload) { boolean onItemRangeChanged(int positionStart, int itemCount, Object payload) {
mPendingUpdates.add(obtainUpdateOp(UpdateOp.UPDATE, positionStart, itemCount, payload)); mPendingUpdates.add(obtainUpdateOp(UpdateOp.UPDATE, positionStart, itemCount, payload));
mExistingUpdateTypes |= UpdateOp.UPDATE;
return mPendingUpdates.size() == 1; return mPendingUpdates.size() == 1;
} }
...@@ -506,6 +512,7 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -506,6 +512,7 @@ class AdapterHelper implements OpReorderer.Callback {
*/ */
boolean onItemRangeInserted(int positionStart, int itemCount) { boolean onItemRangeInserted(int positionStart, int itemCount) {
mPendingUpdates.add(obtainUpdateOp(UpdateOp.ADD, positionStart, itemCount, null)); mPendingUpdates.add(obtainUpdateOp(UpdateOp.ADD, positionStart, itemCount, null));
mExistingUpdateTypes |= UpdateOp.ADD;
return mPendingUpdates.size() == 1; return mPendingUpdates.size() == 1;
} }
...@@ -514,6 +521,7 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -514,6 +521,7 @@ class AdapterHelper implements OpReorderer.Callback {
*/ */
boolean onItemRangeRemoved(int positionStart, int itemCount) { boolean onItemRangeRemoved(int positionStart, int itemCount) {
mPendingUpdates.add(obtainUpdateOp(UpdateOp.REMOVE, positionStart, itemCount, null)); mPendingUpdates.add(obtainUpdateOp(UpdateOp.REMOVE, positionStart, itemCount, null));
mExistingUpdateTypes |= UpdateOp.REMOVE;
return mPendingUpdates.size() == 1; return mPendingUpdates.size() == 1;
} }
...@@ -522,12 +530,13 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -522,12 +530,13 @@ class AdapterHelper implements OpReorderer.Callback {
*/ */
boolean onItemRangeMoved(int from, int to, int itemCount) { boolean onItemRangeMoved(int from, int to, int itemCount) {
if (from == to) { if (from == to) {
return false;//no-op return false; // no-op
} }
if (itemCount != 1) { if (itemCount != 1) {
throw new IllegalArgumentException("Moving more than 1 item is not supported yet"); throw new IllegalArgumentException("Moving more than 1 item is not supported yet");
} }
mPendingUpdates.add(obtainUpdateOp(UpdateOp.MOVE, from, to, null)); mPendingUpdates.add(obtainUpdateOp(UpdateOp.MOVE, from, to, null));
mExistingUpdateTypes |= UpdateOp.MOVE;
return mPendingUpdates.size() == 1; return mPendingUpdates.size() == 1;
} }
...@@ -564,6 +573,7 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -564,6 +573,7 @@ class AdapterHelper implements OpReorderer.Callback {
} }
} }
recycleUpdateOpsAndClearList(mPendingUpdates); recycleUpdateOpsAndClearList(mPendingUpdates);
mExistingUpdateTypes = 0;
} }
public int applyPendingUpdatesToPosition(int position) { public int applyPendingUpdatesToPosition(int position) {
...@@ -602,18 +612,22 @@ class AdapterHelper implements OpReorderer.Callback { ...@@ -602,18 +612,22 @@ class AdapterHelper implements OpReorderer.Callback {
return position; return position;
} }
boolean hasUpdates() {
return !mPostponedList.isEmpty() && !mPendingUpdates.isEmpty();
}
/** /**
* Queued operation to happen when child views are updated. * Queued operation to happen when child views are updated.
*/ */
static class UpdateOp { static class UpdateOp {
static final int ADD = 0; static final int ADD = 1;
static final int REMOVE = 1; static final int REMOVE = 1 << 1;
static final int UPDATE = 2; static final int UPDATE = 1 << 2;
static final int MOVE = 3; static final int MOVE = 1 << 3;
static final int POOL_SIZE = 30; static final int POOL_SIZE = 30;
......
...@@ -208,8 +208,8 @@ class ChildHelper { ...@@ -208,8 +208,8 @@ class ChildHelper {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
final View view = mHiddenViews.get(i); final View view = mHiddenViews.get(i);
RecyclerView.ViewHolder holder = mCallback.getChildViewHolder(view); RecyclerView.ViewHolder holder = mCallback.getChildViewHolder(view);
if (holder.getLayoutPosition() == position && !holder.isInvalid() && if (holder.getLayoutPosition() == position && !holder.isInvalid() && !holder.isRemoved()
(type == RecyclerView.INVALID_TYPE || holder.getItemViewType() == type)) { && (type == RecyclerView.INVALID_TYPE || holder.getItemViewType() == type)) {
return view; return view;
} }
} }
...@@ -339,6 +339,25 @@ class ChildHelper { ...@@ -339,6 +339,25 @@ class ChildHelper {
} }
} }
/**
* Moves a child view from hidden list to regular list.
* Calling this method should probably be followed by a detach, otherwise, it will suddenly
* show up in LayoutManager's children list.
*
* @param view The hidden View to unhide
*/
void unhide(View view) {
final int offset = mCallback.indexOfChild(view);
if (offset < 0) {
throw new IllegalArgumentException("view is not a child, cannot hide " + view);
}
if (!mBucket.get(offset)) {
throw new RuntimeException("trying to unhide a view that was not hidden" + view);
}
mBucket.clear(offset);
unhideViewInternal(view);
}
@Override @Override
public String toString() { public String toString() {
return mBucket.toString() + ", hidden list:" + mHiddenViews.size(); return mBucket.toString() + ", hidden list:" + mHiddenViews.size();
......
...@@ -15,12 +15,11 @@ ...@@ -15,12 +15,11 @@
*/ */
package org.telegram.messenger.support.widget; package org.telegram.messenger.support.widget;
import android.support.annotation.NonNull;
import android.support.v4.animation.AnimatorCompatHelper; import android.support.v4.animation.AnimatorCompatHelper;
import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat; import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListener; import android.support.v4.view.ViewPropertyAnimatorListener;
import org.telegram.messenger.support.widget.RecyclerView;
import org.telegram.messenger.support.widget.RecyclerView.ViewHolder; import org.telegram.messenger.support.widget.RecyclerView.ViewHolder;
import android.view.View; import android.view.View;
...@@ -34,23 +33,22 @@ import java.util.List; ...@@ -34,23 +33,22 @@ import java.util.List;
* *
* @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator) * @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator)
*/ */
public class DefaultItemAnimator extends RecyclerView.ItemAnimator { public class DefaultItemAnimator extends SimpleItemAnimator {
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<ViewHolder>(); private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<>();
private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<ViewHolder>(); private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<>();
private ArrayList<MoveInfo> mPendingMoves = new ArrayList<MoveInfo>(); private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<ChangeInfo>(); private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();
private ArrayList<ArrayList<ViewHolder>> mAdditionsList = private ArrayList<ArrayList<ViewHolder>> mAdditionsList = new ArrayList<>();
new ArrayList<ArrayList<ViewHolder>>(); private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<ArrayList<MoveInfo>>(); private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();
private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<ArrayList<ChangeInfo>>();
private ArrayList<ViewHolder> mAddAnimations = new ArrayList<ViewHolder>(); private ArrayList<ViewHolder> mAddAnimations = new ArrayList<>();
private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<ViewHolder>(); private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<>();
private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<ViewHolder>(); private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<>();
private ArrayList<ViewHolder> mChangeAnimations = new ArrayList<ViewHolder>(); private ArrayList<ViewHolder> mChangeAnimations = new ArrayList<>();
private static class MoveInfo { private static class MoveInfo {
public ViewHolder holder; public ViewHolder holder;
...@@ -112,7 +110,7 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator { ...@@ -112,7 +110,7 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
mPendingRemovals.clear(); mPendingRemovals.clear();
// Next, move stuff // Next, move stuff
if (movesPending) { if (movesPending) {
final ArrayList<MoveInfo> moves = new ArrayList<MoveInfo>(); final ArrayList<MoveInfo> moves = new ArrayList<>();
moves.addAll(mPendingMoves); moves.addAll(mPendingMoves);
mMovesList.add(moves); mMovesList.add(moves);
mPendingMoves.clear(); mPendingMoves.clear();
...@@ -136,7 +134,7 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator { ...@@ -136,7 +134,7 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
} }
// Next, change stuff, to run in parallel with move animations // Next, change stuff, to run in parallel with move animations
if (changesPending) { if (changesPending) {
final ArrayList<ChangeInfo> changes = new ArrayList<ChangeInfo>(); final ArrayList<ChangeInfo> changes = new ArrayList<>();
changes.addAll(mPendingChanges); changes.addAll(mPendingChanges);
mChangesList.add(changes); mChangesList.add(changes);
mPendingChanges.clear(); mPendingChanges.clear();
...@@ -159,7 +157,7 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator { ...@@ -159,7 +157,7 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
} }
// Next, add stuff // Next, add stuff
if (additionsPending) { if (additionsPending) {
final ArrayList<ViewHolder> additions = new ArrayList<ViewHolder>(); final ArrayList<ViewHolder> additions = new ArrayList<>();
additions.addAll(mPendingAdditions); additions.addAll(mPendingAdditions);
mAdditionsList.add(additions); mAdditionsList.add(additions);
mPendingAdditions.clear(); mPendingAdditions.clear();
...@@ -312,6 +310,11 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator { ...@@ -312,6 +310,11 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
@Override @Override
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) { int fromX, int fromY, int toX, int toY) {
if (oldHolder == newHolder) {
// Don't know how to run change animations when the same view holder is re-used.
// run a move animation to handle position changes.
return animateMove(oldHolder, fromX, fromY, toX, toY);
}
final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView); final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView);
final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView); final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView);
final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView); final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
...@@ -322,7 +325,7 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator { ...@@ -322,7 +325,7 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX); ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX);
ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY); ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY);
ViewCompat.setAlpha(oldHolder.itemView, prevAlpha); ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
if (newHolder != null && newHolder.itemView != null) { if (newHolder != null) {
// carry over translation values // carry over translation values
resetAnimation(newHolder); resetAnimation(newHolder);
ViewCompat.setTranslationX(newHolder.itemView, -deltaX); ViewCompat.setTranslationX(newHolder.itemView, -deltaX);
...@@ -481,21 +484,25 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator { ...@@ -481,21 +484,25 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
} }
// animations should be ended by the cancel above. // animations should be ended by the cancel above.
//noinspection PointlessBooleanExpression,ConstantConditions
if (mRemoveAnimations.remove(item) && DEBUG) { if (mRemoveAnimations.remove(item) && DEBUG) {
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
if (mAddAnimations.remove(item) && DEBUG) { if (mAddAnimations.remove(item) && DEBUG) {
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
if (mChangeAnimations.remove(item) && DEBUG) { if (mChangeAnimations.remove(item) && DEBUG) {
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
if (mMoveAnimations.remove(item) && DEBUG) { if (mMoveAnimations.remove(item) && DEBUG) {
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");
...@@ -626,6 +633,28 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator { ...@@ -626,6 +633,28 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
} }
} }
/**
* {@inheritDoc}
* <p>
* If the payload list is not empty, DefaultItemAnimator returns <code>true</code>.
* When this is the case:
* <ul>
* <li>If you override {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)}, both
* ViewHolder arguments will be the same instance.
* </li>
* <li>
* If you are not overriding {@link #animateChange(ViewHolder, ViewHolder, int, int, int, int)},
* then DefaultItemAnimator will call {@link #animateMove(ViewHolder, int, int, int, int)} and
* run a move animation instead.
* </li>
* </ul>
*/
@Override
public boolean canReuseUpdatedViewHolder(@NonNull ViewHolder viewHolder,
@NonNull List<Object> payloads) {
return !payloads.isEmpty() || super.canReuseUpdatedViewHolder(viewHolder, payloads);
}
private static class VpaListenerAdapter implements ViewPropertyAnimatorListener { private static class VpaListenerAdapter implements ViewPropertyAnimatorListener {
@Override @Override
public void onAnimationStart(View view) {} public void onAnimationStart(View view) {}
...@@ -635,5 +664,5 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator { ...@@ -635,5 +664,5 @@ public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
@Override @Override
public void onAnimationCancel(View view) {} public void onAnimationCancel(View view) {}
}; }
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package org.telegram.messenger.support.widget; package org.telegram.messenger.support.widget;
import android.view.View; import android.view.View;
/** /**
...@@ -35,7 +36,10 @@ class LayoutState { ...@@ -35,7 +36,10 @@ class LayoutState {
final static int ITEM_DIRECTION_TAIL = 1; final static int ITEM_DIRECTION_TAIL = 1;
final static int SCOLLING_OFFSET_NaN = Integer.MIN_VALUE; /**
* We may not want to recycle children in some cases (e.g. layout)
*/
boolean mRecycle = true;
/** /**
* Number of pixels that we should fill, in the layout direction. * Number of pixels that we should fill, in the layout direction.
...@@ -69,6 +73,16 @@ class LayoutState { ...@@ -69,6 +73,16 @@ class LayoutState {
*/ */
int mEndLine = 0; int mEndLine = 0;
/**
* If true, layout should stop if a focusable view is added
*/
boolean mStopInFocusable;
/**
* If the content is not wrapped with any value
*/
boolean mInfinite;
/** /**
* @return true if there are more items in the data adapter * @return true if there are more items in the data adapter
*/ */
......
...@@ -24,8 +24,6 @@ import android.view.View; ...@@ -24,8 +24,6 @@ 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.support.widget.RecyclerView;
/** /**
* {@link RecyclerView.SmoothScroller} implementation which uses * {@link RecyclerView.SmoothScroller} implementation which uses
* {@link android.view.animation.LinearInterpolator} until the target position becames a child of * {@link android.view.animation.LinearInterpolator} until the target position becames a child of
...@@ -124,6 +122,7 @@ abstract public class LinearSmoothScroller extends RecyclerView.SmoothScroller { ...@@ -124,6 +122,7 @@ abstract public class LinearSmoothScroller extends RecyclerView.SmoothScroller {
stop(); stop();
return; return;
} }
//noinspection PointlessBooleanExpression
if (DEBUG && mTargetVector != null if (DEBUG && mTargetVector != null
&& ((mTargetVector.x * dx < 0 || mTargetVector.y * dy < 0))) { && ((mTargetVector.x * dx < 0 || mTargetVector.y * dy < 0))) {
throw new IllegalStateException("Scroll happened in the opposite direction" throw new IllegalStateException("Scroll happened in the opposite direction"
...@@ -293,13 +292,13 @@ abstract public class LinearSmoothScroller extends RecyclerView.SmoothScroller { ...@@ -293,13 +292,13 @@ abstract public class LinearSmoothScroller extends RecyclerView.SmoothScroller {
* @param view The view which we want to make fully visible * @param view The view which we want to make fully visible
* @param snapPreference The edge which the view should snap to when entering the visible * @param snapPreference The edge which the view should snap to when entering the visible
* area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or * area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or
* {@link #SNAP_TO_END}. * {@link #SNAP_TO_ANY}.
* @return The vertical scroll amount necessary to make the view visible with the given * @return The vertical scroll amount necessary to make the view visible with the given
* snap preference. * snap preference.
*/ */
public int calculateDyToMakeVisible(View view, int snapPreference) { public int calculateDyToMakeVisible(View view, int snapPreference) {
final RecyclerView.LayoutManager layoutManager = getLayoutManager(); final RecyclerView.LayoutManager layoutManager = getLayoutManager();
if (!layoutManager.canScrollVertically()) { if (layoutManager == null || !layoutManager.canScrollVertically()) {
return 0; return 0;
} }
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
...@@ -324,7 +323,7 @@ abstract public class LinearSmoothScroller extends RecyclerView.SmoothScroller { ...@@ -324,7 +323,7 @@ abstract public class LinearSmoothScroller extends RecyclerView.SmoothScroller {
*/ */
public int calculateDxToMakeVisible(View view, int snapPreference) { public int calculateDxToMakeVisible(View view, int snapPreference) {
final RecyclerView.LayoutManager layoutManager = getLayoutManager(); final RecyclerView.LayoutManager layoutManager = getLayoutManager();
if (!layoutManager.canScrollHorizontally()) { if (layoutManager == null || !layoutManager.canScrollHorizontally()) {
return 0; return 0;
} }
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
......
...@@ -19,8 +19,6 @@ package org.telegram.messenger.support.widget; ...@@ -19,8 +19,6 @@ package org.telegram.messenger.support.widget;
import android.view.View; import android.view.View;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import org.telegram.messenger.support.widget.RecyclerView;
/** /**
* Helper class for LayoutManagers to abstract measurements depending on the View's orientation. * Helper class for LayoutManagers to abstract measurements depending on the View's orientation.
* <p> * <p>
...@@ -167,6 +165,28 @@ public abstract class OrientationHelper { ...@@ -167,6 +165,28 @@ public abstract class OrientationHelper {
*/ */
public abstract int getEndPadding(); public abstract int getEndPadding();
/**
* Returns the MeasureSpec mode for the current orientation from the LayoutManager.
*
* @return The current measure spec mode.
*
* @see View.MeasureSpec
* @see RecyclerView.LayoutManager#getWidthMode()
* @see RecyclerView.LayoutManager#getHeightMode()
*/
public abstract int getMode();
/**
* Returns the MeasureSpec mode for the perpendicular orientation from the LayoutManager.
*
* @return The current measure spec mode.
*
* @see View.MeasureSpec
* @see RecyclerView.LayoutManager#getWidthMode()
* @see RecyclerView.LayoutManager#getHeightMode()
*/
public abstract int getModeInOther();
/** /**
* Creates an OrientationHelper for the given LayoutManager and orientation. * Creates an OrientationHelper for the given LayoutManager and orientation.
* *
...@@ -259,6 +279,16 @@ public abstract class OrientationHelper { ...@@ -259,6 +279,16 @@ public abstract class OrientationHelper {
public int getEndPadding() { public int getEndPadding() {
return mLayoutManager.getPaddingRight(); return mLayoutManager.getPaddingRight();
} }
@Override
public int getMode() {
return mLayoutManager.getWidthMode();
}
@Override
public int getModeInOther() {
return mLayoutManager.getHeightMode();
}
}; };
} }
...@@ -335,6 +365,16 @@ public abstract class OrientationHelper { ...@@ -335,6 +365,16 @@ public abstract class OrientationHelper {
public int getEndPadding() { public int getEndPadding() {
return mLayoutManager.getPaddingBottom(); return mLayoutManager.getPaddingBottom();
} }
@Override
public int getMode() {
return mLayoutManager.getHeightMode();
}
@Override
public int getModeInOther() {
return mLayoutManager.getWidthMode();
}
}; };
} }
} }
\ No newline at end of file
...@@ -22,8 +22,6 @@ import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; ...@@ -22,8 +22,6 @@ import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.view.View; import android.view.View;
import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent;
import org.telegram.messenger.support.widget.RecyclerView;
/** /**
* The AccessibilityDelegate used by RecyclerView. * The AccessibilityDelegate used by RecyclerView.
* <p> * <p>
......
...@@ -17,8 +17,6 @@ package org.telegram.messenger.support.widget; ...@@ -17,8 +17,6 @@ package org.telegram.messenger.support.widget;
import android.view.View; import android.view.View;
import org.telegram.messenger.support.widget.RecyclerView;
/** /**
* A helper class to do scroll offset calculations. * A helper class to do scroll offset calculations.
*/ */
......
...@@ -21,12 +21,12 @@ import android.support.v4.view.ViewCompat; ...@@ -21,12 +21,12 @@ import android.support.v4.view.ViewCompat;
import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.support.widget.RecyclerView;
import android.view.View; import android.view.View;
/** /**
* Package private class to keep implementations. Putting them inside ItemTouchUIUtil makes them * Package private class to keep implementations. Putting them inside ItemTouchUIUtil makes them
* public API, which is not desired in this case. * public API, which is not desired in this case.
*/ */
class ItemTouchUIUtilImpl { class ItemTouchUIUtilImpl {
static class Lollipop extends Honeycomb { static class Lollipop extends Honeycomb {
@Override @Override
public void onDraw(Canvas c, RecyclerView recyclerView, View view, public void onDraw(Canvas c, RecyclerView recyclerView, View view,
......
...@@ -238,7 +238,7 @@ public class ContactsAdapter extends BaseSectionsAdapter { ...@@ -238,7 +238,7 @@ public class ContactsAdapter extends BaseSectionsAdapter {
} }
} else if (type == 0) { } else if (type == 0) {
if (convertView == null) { if (convertView == null) {
convertView = new UserCell(mContext, 58, 1); convertView = new UserCell(mContext, 58, 1, false);
((UserCell) convertView).setStatusColors(0xffa8a8a8, 0xff3b84c0); ((UserCell) convertView).setStatusColors(0xffa8a8a8, 0xff3b84c0);
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment