Commit 2b8304eb authored by DrKLO's avatar DrKLO

Update to 2.8.1

Thanks to https://github.com/DrKLO/Telegram/issues/738 for smart
notifications
parent f6655078
...@@ -13,11 +13,10 @@ repositories { ...@@ -13,11 +13,10 @@ repositories {
} }
dependencies { dependencies {
compile 'com.android.support:support-v4:22.0.+' compile 'com.android.support:support-v4:22.1.+'
compile 'com.google.android.gms:play-services:3.2.+' compile 'com.google.android.gms:play-services:3.2.+'
compile 'net.hockeyapp.android:HockeySDK:3.5.+' compile 'net.hockeyapp.android:HockeySDK:3.5.+'
compile 'com.googlecode.mp4parser:isoparser:1.0.+' compile 'com.googlecode.mp4parser:isoparser:1.0.+'
compile 'com.android.support:recyclerview-v7:+'
} }
android { android {
...@@ -82,7 +81,7 @@ android { ...@@ -82,7 +81,7 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 8 minSdkVersion 8
targetSdkVersion 22 targetSdkVersion 22
versionCode 492 versionCode 521
versionName "2.7.0" versionName "2.8.1"
} }
} }
...@@ -104,7 +104,7 @@ include $(BUILD_STATIC_LIBRARY) ...@@ -104,7 +104,7 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false LOCAL_PRELINK_MODULE := false
LOCAL_STATIC_LIBRARIES := webp sqlite LOCAL_STATIC_LIBRARIES := webp sqlite
LOCAL_MODULE := tmessages.7 LOCAL_MODULE := tmessages.8
LOCAL_CFLAGS := -w -std=gnu99 -O2 -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 LOCAL_CFLAGS := -w -std=gnu99 -O2 -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 LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math
......
...@@ -288,7 +288,7 @@ METHODDEF(void) my_error_exit(j_common_ptr cinfo) { ...@@ -288,7 +288,7 @@ METHODDEF(void) my_error_exit(j_common_ptr cinfo) {
longjmp(myerr->setjmp_buffer, 1); longjmp(myerr->setjmp_buffer, 1);
} }
JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap, int radius) { JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jclass class, jobject bitmap, int radius, int unpin) {
if (!bitmap) { if (!bitmap) {
return; return;
} }
...@@ -312,7 +312,9 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jcl ...@@ -312,7 +312,9 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_blurBitmap(JNIEnv *env, jcl
} else { } else {
fastBlurMore(info.width, info.height, info.stride, pixels, radius); fastBlurMore(info.width, info.height, info.stride, pixels, radius);
} }
AndroidBitmap_unlockPixels(env, bitmap); if (unpin) {
AndroidBitmap_unlockPixels(env, bitmap);
}
} }
JNIEXPORT void Java_org_telegram_messenger_Utilities_calcCDT(JNIEnv *env, jclass class, jobject hsvBuffer, int width, int height, jobject buffer) { JNIEXPORT void Java_org_telegram_messenger_Utilities_calcCDT(JNIEnv *env, jclass class, jobject hsvBuffer, int width, int height, jobject buffer) {
......
...@@ -45,10 +45,10 @@ import org.telegram.messenger.R; ...@@ -45,10 +45,10 @@ import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC; import org.telegram.messenger.TLRPC;
import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.ui.AnimationCompat.AnimatorListenerAdapterProxy; import org.telegram.android.AnimationCompat.AnimatorListenerAdapterProxy;
import org.telegram.ui.AnimationCompat.AnimatorSetProxy; import org.telegram.android.AnimationCompat.AnimatorSetProxy;
import org.telegram.ui.AnimationCompat.ObjectAnimatorProxy; import org.telegram.android.AnimationCompat.ObjectAnimatorProxy;
import org.telegram.ui.AnimationCompat.ViewProxy; import org.telegram.android.AnimationCompat.ViewProxy;
import org.telegram.ui.Components.ForegroundDetector; import org.telegram.ui.Components.ForegroundDetector;
import org.telegram.ui.Components.NumberPicker; import org.telegram.ui.Components.NumberPicker;
import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.TypefaceSpan;
...@@ -72,6 +72,7 @@ public class AndroidUtilities { ...@@ -72,6 +72,7 @@ public class AndroidUtilities {
public static Integer photoSize = null; public static Integer photoSize = null;
public static DisplayMetrics displayMetrics = new DisplayMetrics(); public static DisplayMetrics displayMetrics = new DisplayMetrics();
public static int leftBaseline; public static int leftBaseline;
public static boolean usingHardwareInput;
private static Boolean isTablet = null; private static Boolean isTablet = null;
static { static {
...@@ -227,21 +228,38 @@ public class AndroidUtilities { ...@@ -227,21 +228,38 @@ public class AndroidUtilities {
} }
public static int dp(float value) { public static int dp(float value) {
if (value == 0) {
return 0;
}
return (int)Math.ceil(density * value); return (int)Math.ceil(density * value);
} }
public static int compare(int lhs, int rhs) {
if (lhs == rhs) {
return 0;
} else if (lhs > rhs) {
return 1;
}
return -1;
}
public static float dpf2(float value) { public static float dpf2(float value) {
if (value == 0) {
return 0;
}
return density * value; return density * value;
} }
public static void checkDisplaySize() { public static void checkDisplaySize() {
try { try {
WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE); Configuration configuration = ApplicationLoader.applicationContext.getResources().getConfiguration();
usingHardwareInput = configuration.keyboard != Configuration.KEYBOARD_NOKEYS && configuration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE);
if (manager != null) { if (manager != null) {
Display display = manager.getDefaultDisplay(); Display display = manager.getDefaultDisplay();
if (display != null) { if (display != null) {
display.getMetrics(displayMetrics); display.getMetrics(displayMetrics);
if(android.os.Build.VERSION.SDK_INT < 13) { if (android.os.Build.VERSION.SDK_INT < 13) {
displaySize.set(display.getWidth(), display.getHeight()); displaySize.set(display.getWidth(), display.getHeight());
} else { } else {
display.getSize(displaySize); display.getSize(displaySize);
...@@ -252,6 +270,38 @@ public class AndroidUtilities { ...@@ -252,6 +270,38 @@ public class AndroidUtilities {
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
} }
/*
keyboardHidden
public static final int KEYBOARDHIDDEN_NO = 1
Constant for keyboardHidden, value corresponding to the keysexposed resource qualifier.
public static final int KEYBOARDHIDDEN_UNDEFINED = 0
Constant for keyboardHidden: a value indicating that no value has been set.
public static final int KEYBOARDHIDDEN_YES = 2
Constant for keyboardHidden, value corresponding to the keyshidden resource qualifier.
hardKeyboardHidden
public static final int HARDKEYBOARDHIDDEN_NO = 1
Constant for hardKeyboardHidden, value corresponding to the physical keyboard being exposed.
public static final int HARDKEYBOARDHIDDEN_UNDEFINED = 0
Constant for hardKeyboardHidden: a value indicating that no value has been set.
public static final int HARDKEYBOARDHIDDEN_YES = 2
Constant for hardKeyboardHidden, value corresponding to the physical keyboard being hidden.
keyboard
public static final int KEYBOARD_12KEY = 3
Constant for keyboard, value corresponding to the 12key resource qualifier.
public static final int KEYBOARD_NOKEYS = 1
Constant for keyboard, value corresponding to the nokeys resource qualifier.
public static final int KEYBOARD_QWERTY = 2
Constant for keyboard, value corresponding to the qwerty resource qualifier.
*/
} }
public static float getPixelsInCM(float cm, boolean isX) { public static float getPixelsInCM(float cm, boolean isX) {
...@@ -562,6 +612,9 @@ public class AndroidUtilities { ...@@ -562,6 +612,9 @@ public class AndroidUtilities {
if (start != -1) { if (start != -1) {
stringBuilder.replace(start, start + 3, ""); stringBuilder.replace(start, start + 3, "");
end = stringBuilder.indexOf("</b>"); end = stringBuilder.indexOf("</b>");
if (end == -1) {
end = stringBuilder.indexOf("<b>");
}
stringBuilder.replace(end, end + 4, ""); stringBuilder.replace(end, end + 4, "");
bolds.add(start); bolds.add(start);
bolds.add(end); bolds.add(end);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
public abstract class AnimatorListenerAdapter10 implements Animator10.AnimatorListener, Animator10.AnimatorPauseListener { public abstract class AnimatorListenerAdapter10 implements Animator10.AnimatorListener, Animator10.AnimatorPauseListener {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
public class FloatEvaluator implements TypeEvaluator<Number> { public class FloatEvaluator implements TypeEvaluator<Number> {
public Float evaluate(float fraction, Number startValue, Number endValue) { public Float evaluate(float fraction, Number startValue, Number endValue) {
......
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import org.telegram.ui.Animation.Keyframe.FloatKeyframe; import org.telegram.android.Animation.Keyframe.FloatKeyframe;
import java.util.ArrayList; import java.util.ArrayList;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* 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.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
public abstract class FloatProperty10<T> extends Property<T, Float> { public abstract class FloatProperty10<T> extends Property<T, Float> {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
public class IntEvaluator implements TypeEvaluator<Integer> { public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) { public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
......
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import org.telegram.ui.Animation.Keyframe.IntKeyframe; import org.telegram.android.Animation.Keyframe.IntKeyframe;
import java.util.ArrayList; import java.util.ArrayList;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* 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.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
public abstract class IntProperty<T> extends Property<T, Integer> { public abstract class IntProperty<T> extends Property<T, Integer> {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
......
...@@ -14,16 +14,16 @@ ...@@ -14,16 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import android.util.Log; import android.util.Log;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import org.telegram.ui.Animation.Keyframe.IntKeyframe; import org.telegram.android.Animation.Keyframe.IntKeyframe;
import org.telegram.ui.Animation.Keyframe.FloatKeyframe; import org.telegram.android.Animation.Keyframe.FloatKeyframe;
import org.telegram.ui.Animation.Keyframe.ObjectKeyframe; import org.telegram.android.Animation.Keyframe.ObjectKeyframe;
class KeyframeSet { class KeyframeSet {
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* 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.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
public class NoSuchPropertyException extends RuntimeException { public class NoSuchPropertyException extends RuntimeException {
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import android.view.View; import android.view.View;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* 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.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
public abstract class Property<T, V> { public abstract class Property<T, V> {
......
...@@ -14,9 +14,8 @@ ...@@ -14,9 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* 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.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
public interface TypeEvaluator<T> { public interface TypeEvaluator<T> {
T evaluate(float fraction, T startValue, T endValue); T evaluate(float fraction, T startValue, T endValue);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import android.os.Looper; import android.os.Looper;
import android.util.AndroidRuntimeException; import android.util.AndroidRuntimeException;
......
...@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and ...@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package org.telegram.ui.Animation; package org.telegram.android.Animation;
import android.graphics.Camera; import android.graphics.Camera;
import android.graphics.Matrix; import android.graphics.Matrix;
......
...@@ -6,14 +6,14 @@ ...@@ -6,14 +6,14 @@
* Copyright Nikolai Kudashov, 2013-2014. * Copyright Nikolai Kudashov, 2013-2014.
*/ */
package org.telegram.ui.AnimationCompat; package org.telegram.android.AnimationCompat;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import org.telegram.ui.Animation.Animator10; import org.telegram.android.Animation.Animator10;
import org.telegram.ui.Animation.AnimatorListenerAdapter10; import org.telegram.android.Animation.AnimatorListenerAdapter10;
import org.telegram.ui.Animation.View10; import org.telegram.android.Animation.View10;
public class AnimatorListenerAdapterProxy { public class AnimatorListenerAdapterProxy {
protected Object animatorListenerAdapter; protected Object animatorListenerAdapter;
......
...@@ -6,17 +6,17 @@ ...@@ -6,17 +6,17 @@
* Copyright Nikolai Kudashov, 2013-2014. * Copyright Nikolai Kudashov, 2013-2014.
*/ */
package org.telegram.ui.AnimationCompat; package org.telegram.android.AnimationCompat;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import org.telegram.ui.Animation.Animator10; import org.telegram.android.Animation.Animator10;
import org.telegram.ui.Animation.AnimatorListenerAdapter10; import org.telegram.android.Animation.AnimatorListenerAdapter10;
import org.telegram.ui.Animation.AnimatorSet10; import org.telegram.android.Animation.AnimatorSet10;
import org.telegram.ui.Animation.View10; import org.telegram.android.Animation.View10;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.ArrayList; import java.util.ArrayList;
......
...@@ -6,15 +6,15 @@ ...@@ -6,15 +6,15 @@
* Copyright Nikolai Kudashov, 2013-2014. * Copyright Nikolai Kudashov, 2013-2014.
*/ */
package org.telegram.ui.AnimationCompat; package org.telegram.android.AnimationCompat;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import org.telegram.ui.Animation.AnimatorListenerAdapter10; import org.telegram.android.Animation.AnimatorListenerAdapter10;
import org.telegram.ui.Animation.ObjectAnimator10; import org.telegram.android.Animation.ObjectAnimator10;
import org.telegram.ui.Animation.View10; import org.telegram.android.Animation.View10;
public class ObjectAnimatorProxy { public class ObjectAnimatorProxy {
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
* Copyright Nikolai Kudashov, 2013-2014. * Copyright Nikolai Kudashov, 2013-2014.
*/ */
package org.telegram.ui.AnimationCompat; package org.telegram.android.AnimationCompat;
import android.view.View; import android.view.View;
import org.telegram.ui.Animation.View10; import org.telegram.android.Animation.View10;
public class ViewProxy { public class ViewProxy {
......
...@@ -14,6 +14,7 @@ import android.app.Activity; ...@@ -14,6 +14,7 @@ import android.app.Activity;
import android.content.ContentProviderOperation; import android.content.ContentProviderOperation;
import android.content.ContentProviderResult; import android.content.ContentProviderResult;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
...@@ -37,7 +38,6 @@ import java.util.ArrayList; ...@@ -37,7 +38,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
public class ContactsController { public class ContactsController {
...@@ -168,7 +168,7 @@ public class ContactsController { ...@@ -168,7 +168,7 @@ public class ContactsController {
if (!updatingInviteText && (inviteText == null || time + 86400 < (int)(System.currentTimeMillis() / 1000))) { if (!updatingInviteText && (inviteText == null || time + 86400 < (int)(System.currentTimeMillis() / 1000))) {
updatingInviteText = true; updatingInviteText = true;
TLRPC.TL_help_getInviteText req = new TLRPC.TL_help_getInviteText(); TLRPC.TL_help_getInviteText req = new TLRPC.TL_help_getInviteText();
req.lang_code = LocaleController.getLocaleString(Locale.getDefault()); req.lang_code = LocaleController.getLocaleString(LocaleController.getInstance().getSystemDefaultLocale());
if (req.lang_code == null || req.lang_code.length() == 0) { if (req.lang_code == null || req.lang_code.length() == 0) {
req.lang_code = "en"; req.lang_code = "en";
} }
...@@ -202,7 +202,19 @@ public class ContactsController { ...@@ -202,7 +202,19 @@ public class ContactsController {
public void checkAppAccount() { public void checkAppAccount() {
AccountManager am = AccountManager.get(ApplicationLoader.applicationContext); AccountManager am = AccountManager.get(ApplicationLoader.applicationContext);
Account[] accounts = am.getAccountsByType("org.telegram.account"); Account[] accounts;
try {
accounts = am.getAccountsByType("org.telegram.account");
if (accounts != null && accounts.length > 0) {
for (Account c : accounts) {
am.removeAccount(c, null, null);
}
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
accounts = am.getAccountsByType("org.telegram.messenger");
boolean recreateAccount = false; boolean recreateAccount = false;
if (UserConfig.isClientActivated()) { if (UserConfig.isClientActivated()) {
if (accounts.length == 1) { if (accounts.length == 1) {
...@@ -227,7 +239,7 @@ public class ContactsController { ...@@ -227,7 +239,7 @@ public class ContactsController {
} }
if (UserConfig.isClientActivated()) { if (UserConfig.isClientActivated()) {
try { try {
currentAccount = new Account(UserConfig.getCurrentUser().phone, "org.telegram.account"); currentAccount = new Account(UserConfig.getCurrentUser().phone, "org.telegram.messenger");
am.addAccountExplicitly(currentAccount, "", null); am.addAccountExplicitly(currentAccount, "", null);
} catch (Exception e) { } catch (Exception e) {
FileLog.e("tmessages", e); FileLog.e("tmessages", e);
...@@ -239,7 +251,7 @@ public class ContactsController { ...@@ -239,7 +251,7 @@ public class ContactsController {
public void deleteAllAppAccounts() { public void deleteAllAppAccounts() {
try { try {
AccountManager am = AccountManager.get(ApplicationLoader.applicationContext); AccountManager am = AccountManager.get(ApplicationLoader.applicationContext);
Account[] accounts = am.getAccountsByType("org.telegram.account"); Account[] accounts = am.getAccountsByType("org.telegram.messenger");
for (Account c : accounts) { for (Account c : accounts) {
am.removeAccount(c, null, null); am.removeAccount(c, null, null);
} }
...@@ -1246,7 +1258,7 @@ public class ContactsController { ...@@ -1246,7 +1258,7 @@ public class ContactsController {
private void performWriteContactsToPhoneBook() { private void performWriteContactsToPhoneBook() {
final ArrayList<TLRPC.TL_contact> contactsArray = new ArrayList<>(); final ArrayList<TLRPC.TL_contact> contactsArray = new ArrayList<>();
contactsArray.addAll(contacts); contactsArray.addAll(contacts);
Utilities.photoBookQueue.postRunnable(new Runnable() { Utilities.phoneBookQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
performWriteContactsToPhoneBookInternal(contactsArray); performWriteContactsToPhoneBookInternal(contactsArray);
...@@ -1303,7 +1315,7 @@ public class ContactsController { ...@@ -1303,7 +1315,7 @@ public class ContactsController {
} }
for (final Integer uid : contactsTD) { for (final Integer uid : contactsTD) {
Utilities.photoBookQueue.postRunnable(new Runnable() { Utilities.phoneBookQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
deleteContactFromPhoneBook(uid); deleteContactFromPhoneBook(uid);
...@@ -1463,7 +1475,7 @@ public class ContactsController { ...@@ -1463,7 +1475,7 @@ public class ContactsController {
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0); builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile"); builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile");
builder.withValue(ContactsContract.Data.DATA1, "+" + user.phone); builder.withValue(ContactsContract.Data.DATA1, user.id);
builder.withValue(ContactsContract.Data.DATA2, "Telegram Profile"); builder.withValue(ContactsContract.Data.DATA2, "Telegram Profile");
builder.withValue(ContactsContract.Data.DATA3, "+" + user.phone); builder.withValue(ContactsContract.Data.DATA3, "+" + user.phone);
builder.withValue(ContactsContract.Data.DATA4, user.id); builder.withValue(ContactsContract.Data.DATA4, user.id);
...@@ -1496,6 +1508,22 @@ public class ContactsController { ...@@ -1496,6 +1508,22 @@ public class ContactsController {
} }
} }
protected void markAsContacted(final String contactId) {
if (contactId == null) {
return;
}
Utilities.phoneBookQueue.postRunnable(new Runnable() {
@Override
public void run() {
Uri uri = Uri.parse(contactId);
ContentValues values = new ContentValues();
values.put(ContactsContract.Contacts.LAST_TIME_CONTACTED, System.currentTimeMillis());
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
cr.update(uri, values, null, null);
}
});
}
public void addContact(TLRPC.User user) { public void addContact(TLRPC.User user) {
if (user == null || user.phone == null) { if (user == null || user.phone == null) {
return; return;
...@@ -1533,7 +1561,7 @@ public class ContactsController { ...@@ -1533,7 +1561,7 @@ public class ContactsController {
// } // }
for (final TLRPC.User u : res.users) { for (final TLRPC.User u : res.users) {
Utilities.photoBookQueue.postRunnable(new Runnable() { Utilities.phoneBookQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
addContactToPhoneBook(u, true); addContactToPhoneBook(u, true);
...@@ -1546,7 +1574,7 @@ public class ContactsController { ...@@ -1546,7 +1574,7 @@ public class ContactsController {
MessagesStorage.getInstance().putContacts(arrayList, false); MessagesStorage.getInstance().putContacts(arrayList, false);
if (u.phone != null && u.phone.length() > 0) { if (u.phone != null && u.phone.length() > 0) {
String name = formatName(u.first_name, u.last_name); CharSequence name = formatName(u.first_name, u.last_name);
MessagesStorage.getInstance().applyPhoneBookUpdates(u.phone, ""); MessagesStorage.getInstance().applyPhoneBookUpdates(u.phone, "");
Contact contact = contactsBookSPhones.get(u.phone); Contact contact = contactsBookSPhones.get(u.phone);
if (contact != null) { if (contact != null) {
...@@ -1599,7 +1627,7 @@ public class ContactsController { ...@@ -1599,7 +1627,7 @@ public class ContactsController {
return; return;
} }
MessagesStorage.getInstance().deleteContacts(uids); MessagesStorage.getInstance().deleteContacts(uids);
Utilities.photoBookQueue.postRunnable(new Runnable() { Utilities.phoneBookQueue.postRunnable(new Runnable() {
@Override @Override
public void run() { public void run() {
for (TLRPC.User user : users) { for (TLRPC.User user : users) {
...@@ -1610,7 +1638,7 @@ public class ContactsController { ...@@ -1610,7 +1638,7 @@ public class ContactsController {
for (TLRPC.User user : users) { for (TLRPC.User user : users) {
if (user.phone != null && user.phone.length() > 0) { if (user.phone != null && user.phone.length() > 0) {
String name = ContactsController.formatName(user.first_name, user.last_name); CharSequence name = ContactsController.formatName(user.first_name, user.last_name);
MessagesStorage.getInstance().applyPhoneBookUpdates(user.phone, ""); MessagesStorage.getInstance().applyPhoneBookUpdates(user.phone, "");
Contact contact = contactsBookSPhones.get(user.phone); Contact contact = contactsBookSPhones.get(user.phone);
if (contact != null) { if (contact != null) {
...@@ -1772,22 +1800,37 @@ public class ContactsController { ...@@ -1772,22 +1800,37 @@ public class ContactsController {
} }
public static String formatName(String firstName, String lastName) { public static String formatName(String firstName, String lastName) {
String result = ""; /*if ((firstName == null || firstName.length() == 0) && (lastName == null || lastName.length() == 0)) {
return LocaleController.getString("HiddenName", R.string.HiddenName);
}*/
if (firstName != null) {
firstName = firstName.trim();
}
if (lastName != null) {
lastName = lastName.trim();
}
StringBuilder result = new StringBuilder((firstName != null ? firstName.length() : 0) + (lastName != null ? lastName.length() : 0) + 1);
if (LocaleController.nameDisplayOrder == 1) { if (LocaleController.nameDisplayOrder == 1) {
result = firstName; if (firstName != null && firstName.length() > 0) {
if (result == null || result.length() == 0) { result.append(firstName);
result = lastName; if (lastName != null && lastName.length() > 0) {
} else if (result.length() != 0 && lastName != null && lastName.length() != 0) { result.append(" ");
result += " " + lastName; result.append(lastName);
}
} else if (lastName != null && lastName.length() > 0) {
result.append(lastName);
} }
} else { } else {
result = lastName; if (lastName != null && lastName.length() > 0) {
if (result == null || result.length() == 0) { result.append(lastName);
result = firstName; if (firstName != null && firstName.length() > 0) {
} else if (result.length() != 0 && firstName != null && firstName.length() != 0) { result.append(" ");
result += " " + firstName; result.append(firstName);
}
} else if (firstName != null && firstName.length() > 0) {
result.append(firstName);
} }
} }
return result.trim(); return result.toString();
} }
} }
...@@ -33,7 +33,8 @@ import org.telegram.messenger.ApplicationLoader; ...@@ -33,7 +33,8 @@ import org.telegram.messenger.ApplicationLoader;
public class Emoji { public class Emoji {
private static HashMap<Long, DrawableInfo> rects = new HashMap<>(); private static HashMap<Long, DrawableInfo> rects = new HashMap<>();
private static int drawImgSize, bigImgSize; private static int drawImgSize;
private static int bigImgSize;
private static boolean inited = false; private static boolean inited = false;
private static Paint placeholderPaint; private static Paint placeholderPaint;
private static Bitmap emojiBmp[] = new Bitmap[5]; private static Bitmap emojiBmp[] = new Bitmap[5];
...@@ -193,19 +194,19 @@ public class Emoji { ...@@ -193,19 +194,19 @@ public class Emoji {
static { static {
int emojiFullSize; int emojiFullSize;
if (AndroidUtilities.density <= 1.0f) { if (AndroidUtilities.density <= 1.0f) {
emojiFullSize = 30; emojiFullSize = 32;
} else if (AndroidUtilities.density <= 1.5f) { } else if (AndroidUtilities.density <= 1.5f) {
emojiFullSize = 45; emojiFullSize = 48;
} else if (AndroidUtilities.density <= 2.0f) { } else if (AndroidUtilities.density <= 2.0f) {
emojiFullSize = 60; emojiFullSize = 64;
} else { } else {
emojiFullSize = 90; emojiFullSize = 96;
} }
drawImgSize = AndroidUtilities.dp(20); drawImgSize = AndroidUtilities.dp(20);
if (AndroidUtilities.isTablet()) { if (AndroidUtilities.isTablet()) {
bigImgSize = AndroidUtilities.dp(40); bigImgSize = AndroidUtilities.dp(40);
} else { } else {
bigImgSize = AndroidUtilities.dp(30); bigImgSize = AndroidUtilities.dp(32);
} }
for (int j = 1; j < data.length; j++) { for (int j = 1; j < data.length; j++) {
...@@ -234,8 +235,26 @@ public class Emoji { ...@@ -234,8 +235,26 @@ public class Emoji {
scale = 3.0f; scale = 3.0f;
} }
String imageName = String.format(Locale.US, "emoji%.01fx_%d.jpg", scale, page); String imageName;
File imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); File imageFile;
try {
imageName = String.format(Locale.US, "emoji%.01fx_%d.jpg", scale, page);
imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName);
if (imageFile.exists()) {
imageFile.delete();
}
imageName = String.format(Locale.US, "emoji%.01fx_a_%d.jpg", scale, page);
imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName);
if (imageFile.exists()) {
imageFile.delete();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
imageName = String.format(Locale.US, "v4_emoji%.01fx_%d.jpg", scale, page);
imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName);
if (!imageFile.exists()) { if (!imageFile.exists()) {
InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + imageName); InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + imageName);
Utilities.copyFile(is, imageFile); Utilities.copyFile(is, imageFile);
...@@ -253,7 +272,7 @@ public class Emoji { ...@@ -253,7 +272,7 @@ public class Emoji {
final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Utilities.loadBitmap(imageFile.getAbsolutePath(), bitmap, imageResize, width, height, stride); Utilities.loadBitmap(imageFile.getAbsolutePath(), bitmap, imageResize, width, height, stride);
imageName = String.format(Locale.US, "emoji%.01fx_a_%d.jpg", scale, page); imageName = String.format(Locale.US, "v4_emoji%.01fx_a_%d.jpg", scale, page);
imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName);
if (!imageFile.exists()) { if (!imageFile.exists()) {
InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + imageName); InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + imageName);
......
...@@ -309,6 +309,10 @@ public class LocaleController { ...@@ -309,6 +309,10 @@ public class LocaleController {
} }
} }
public Locale getSystemDefaultLocale() {
return systemDefaultLocale;
}
public static String getLocaleString(Locale locale) { public static String getLocaleString(Locale locale) {
if (locale == null) { if (locale == null) {
return "en"; return "en";
...@@ -607,11 +611,12 @@ public class LocaleController { ...@@ -607,11 +611,12 @@ public class LocaleController {
} }
public static String formatString(String key, int res, Object... args) { public static String formatString(String key, int res, Object... args) {
String value = getInstance().localeValues.get(key);
if (value == null) {
value = ApplicationLoader.applicationContext.getString(res);
}
try { try {
String value = getInstance().localeValues.get(key);
if (value == null) {
value = ApplicationLoader.applicationContext.getString(res);
}
if (getInstance().currentLocale != null) { if (getInstance().currentLocale != null) {
return String.format(getInstance().currentLocale, value, args); return String.format(getInstance().currentLocale, value, args);
} else { } else {
......
...@@ -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 = 7; private final static int LIB_VERSION = 8;
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";
......
...@@ -32,7 +32,7 @@ public class NotificationCenter { ...@@ -32,7 +32,7 @@ public class NotificationCenter {
public static final int mediaDidLoaded = totalEvents++; public static final int mediaDidLoaded = totalEvents++;
public static final int mediaCountDidLoaded = totalEvents++; public static final int mediaCountDidLoaded = totalEvents++;
public static final int encryptedChatUpdated = totalEvents++; public static final int encryptedChatUpdated = totalEvents++;
public static final int messagesReadedEncrypted = totalEvents++; public static final int messagesReadEncrypted = totalEvents++;
public static final int encryptedChatCreated = totalEvents++; public static final int encryptedChatCreated = totalEvents++;
public static final int userPhotosLoaded = totalEvents++; public static final int userPhotosLoaded = totalEvents++;
public static final int removeAllMessagesFromDialog = totalEvents++; public static final int removeAllMessagesFromDialog = totalEvents++;
...@@ -56,6 +56,9 @@ public class NotificationCenter { ...@@ -56,6 +56,9 @@ public class NotificationCenter {
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++;
public static final int stickersDidLoaded = totalEvents++;
public static final int didReplacedPhotoInMemCache = totalEvents++;
public static final int messagesReadContent = 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++;
......
...@@ -542,7 +542,7 @@ public class SecretChatHelper { ...@@ -542,7 +542,7 @@ public class SecretChatHelper {
File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg");
File cacheFile2 = FileLoader.getPathToAttach(size); File cacheFile2 = FileLoader.getPathToAttach(size);
cacheFile.renameTo(cacheFile2); cacheFile.renameTo(cacheFile2);
ImageLoader.getInstance().replaceImageInCache(fileName, fileName2); ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, size.location);
ArrayList<TLRPC.Message> arr = new ArrayList<>(); ArrayList<TLRPC.Message> arr = new ArrayList<>();
arr.add(newMsg); arr.add(newMsg);
MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); MessagesStorage.getInstance().putMessages(arr, false, true, false, 0);
...@@ -557,7 +557,7 @@ public class SecretChatHelper { ...@@ -557,7 +557,7 @@ public class SecretChatHelper {
newMsg.media.video.w = video.w; newMsg.media.video.w = video.w;
newMsg.media.video.h = video.h; newMsg.media.video.h = video.h;
newMsg.media.video.date = video.date; newMsg.media.video.date = video.date;
newMsg.media.video.caption = ""; newMsg.media.caption = video.caption != null ? video.caption : "";
newMsg.media.video.user_id = video.user_id; newMsg.media.video.user_id = video.user_id;
newMsg.media.video.size = file.size; newMsg.media.video.size = file.size;
newMsg.media.video.id = file.id; newMsg.media.video.id = file.id;
...@@ -565,6 +565,7 @@ public class SecretChatHelper { ...@@ -565,6 +565,7 @@ public class SecretChatHelper {
newMsg.media.video.key = decryptedMessage.media.key; newMsg.media.video.key = decryptedMessage.media.key;
newMsg.media.video.iv = decryptedMessage.media.iv; newMsg.media.video.iv = decryptedMessage.media.iv;
newMsg.media.video.mime_type = video.mime_type; newMsg.media.video.mime_type = video.mime_type;
newMsg.media.video.caption = video.caption != null ? video.caption : "";
if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) {
File cacheFile = new File(newMsg.attachPath); File cacheFile = new File(newMsg.attachPath);
...@@ -893,10 +894,10 @@ public class SecretChatHelper { ...@@ -893,10 +894,10 @@ public class SecretChatHelper {
return null; return null;
} }
newMessage.media = new TLRPC.TL_messageMediaPhoto(); newMessage.media = new TLRPC.TL_messageMediaPhoto();
newMessage.media.caption = "";
newMessage.media.photo = new TLRPC.TL_photo(); newMessage.media.photo = new TLRPC.TL_photo();
newMessage.media.photo.user_id = newMessage.from_id; newMessage.media.photo.user_id = newMessage.from_id;
newMessage.media.photo.date = newMessage.date; newMessage.media.photo.date = newMessage.date;
newMessage.media.photo.caption = "";
newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty(); newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty();
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) {
TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize(); TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize();
...@@ -926,6 +927,7 @@ public class SecretChatHelper { ...@@ -926,6 +927,7 @@ public class SecretChatHelper {
return null; return null;
} }
newMessage.media = new TLRPC.TL_messageMediaVideo(); newMessage.media = new TLRPC.TL_messageMediaVideo();
newMessage.media.caption = "";
newMessage.media.video = new TLRPC.TL_videoEncrypted(); newMessage.media.video = new TLRPC.TL_videoEncrypted();
if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) {
newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize(); newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize();
...@@ -943,7 +945,6 @@ public class SecretChatHelper { ...@@ -943,7 +945,6 @@ public class SecretChatHelper {
newMessage.media.video.w = decryptedMessage.media.w; newMessage.media.video.w = decryptedMessage.media.w;
newMessage.media.video.h = decryptedMessage.media.h; newMessage.media.video.h = decryptedMessage.media.h;
newMessage.media.video.date = date; newMessage.media.video.date = date;
newMessage.media.video.caption = "";
newMessage.media.video.user_id = from_id; newMessage.media.video.user_id = from_id;
newMessage.media.video.size = file.size; newMessage.media.video.size = file.size;
newMessage.media.video.id = file.id; newMessage.media.video.id = file.id;
...@@ -951,6 +952,7 @@ public class SecretChatHelper { ...@@ -951,6 +952,7 @@ public class SecretChatHelper {
newMessage.media.video.key = decryptedMessage.media.key; newMessage.media.video.key = decryptedMessage.media.key;
newMessage.media.video.iv = decryptedMessage.media.iv; newMessage.media.video.iv = decryptedMessage.media.iv;
newMessage.media.video.mime_type = decryptedMessage.media.mime_type; newMessage.media.video.mime_type = decryptedMessage.media.mime_type;
newMessage.media.video.caption = "";
if (newMessage.ttl != 0) { if (newMessage.ttl != 0) {
newMessage.ttl = Math.max(newMessage.media.video.duration + 1, newMessage.ttl); newMessage.ttl = Math.max(newMessage.media.video.duration + 1, newMessage.ttl);
} }
...@@ -1300,7 +1302,7 @@ public class SecretChatHelper { ...@@ -1300,7 +1302,7 @@ public class SecretChatHelper {
ByteBufferDesc is = BuffersStorage.getInstance().getFreeBuffer(message.bytes.length); ByteBufferDesc is = BuffersStorage.getInstance().getFreeBuffer(message.bytes.length);
is.writeRaw(message.bytes); is.writeRaw(message.bytes);
is.position(0); is.position(0);
long fingerprint = is.readInt64(); long fingerprint = is.readInt64(false);
byte[] keyToDecrypt = null; byte[] keyToDecrypt = null;
boolean new_key_used = false; boolean new_key_used = false;
if (chat.key_fingerprint == fingerprint) { if (chat.key_fingerprint == fingerprint) {
...@@ -1311,12 +1313,12 @@ public class SecretChatHelper { ...@@ -1311,12 +1313,12 @@ public class SecretChatHelper {
} }
if (keyToDecrypt != null) { if (keyToDecrypt != null) {
byte[] messageKey = is.readData(16); byte[] messageKey = is.readData(16, false);
MessageKeyData keyData = Utilities.generateMessageKeyData(keyToDecrypt, messageKey, false); MessageKeyData keyData = Utilities.generateMessageKeyData(keyToDecrypt, messageKey, false);
Utilities.aesIgeEncryption(is.buffer, keyData.aesKey, keyData.aesIv, false, false, 24, is.limit() - 24); Utilities.aesIgeEncryption(is.buffer, keyData.aesKey, keyData.aesIv, false, false, 24, is.limit() - 24);
int len = is.readInt32(); int len = is.readInt32(false);
if (len < 0 || len > is.limit() - 28) { if (len < 0 || len > is.limit() - 28) {
return null; return null;
} }
...@@ -1325,7 +1327,13 @@ public class SecretChatHelper { ...@@ -1325,7 +1327,13 @@ public class SecretChatHelper {
return null; return null;
} }
TLObject object = TLClassStore.Instance().TLdeserialize(is, is.readInt32()); TLObject object = null;
try {
object = TLClassStore.Instance().TLdeserialize(is, is.readInt32(true), true);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
BuffersStorage.getInstance().reuseFreeBuffer(is); BuffersStorage.getInstance().reuseFreeBuffer(is);
if (!new_key_used && AndroidUtilities.getPeerLayerVersion(chat.layer) >= 20) { if (!new_key_used && AndroidUtilities.getPeerLayerVersion(chat.layer) >= 20) {
chat.key_use_count_in++; chat.key_use_count_in++;
......
...@@ -21,7 +21,6 @@ import org.telegram.messenger.ByteBufferDesc; ...@@ -21,7 +21,6 @@ import org.telegram.messenger.ByteBufferDesc;
import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.RPCRequest; import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.TLClassStore;
import org.telegram.messenger.TLObject; import org.telegram.messenger.TLObject;
import org.telegram.messenger.TLRPC; import org.telegram.messenger.TLRPC;
...@@ -65,7 +64,7 @@ public class ReplyMessageQuery { ...@@ -65,7 +64,7 @@ public class ReplyMessageQuery {
while (cursor.next()) { while (cursor.next()) {
ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
TLRPC.Message message = (TLRPC.Message) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
message.id = cursor.intValue(1); message.id = cursor.intValue(1);
message.date = cursor.intValue(2); message.date = cursor.intValue(2);
message.dialog_id = dialog_id; message.dialog_id = dialog_id;
......
...@@ -20,7 +20,6 @@ import org.telegram.messenger.ByteBufferDesc; ...@@ -20,7 +20,6 @@ import org.telegram.messenger.ByteBufferDesc;
import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.RPCRequest; import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.TLClassStore;
import org.telegram.messenger.TLObject; import org.telegram.messenger.TLObject;
import org.telegram.messenger.TLRPC; import org.telegram.messenger.TLRPC;
...@@ -178,7 +177,7 @@ public class SharedMediaQuery { ...@@ -178,7 +177,7 @@ public class SharedMediaQuery {
} }
final ArrayList<MessageObject> objects = new ArrayList<>(); final ArrayList<MessageObject> objects = new ArrayList<>();
for (TLRPC.Message message : res.messages) { for (TLRPC.Message message : res.messages) {
objects.add(new MessageObject(message, usersLocal, false)); objects.add(new MessageObject(message, usersLocal, true));
} }
AndroidUtilities.runOnUIThread(new Runnable() { AndroidUtilities.runOnUIThread(new Runnable() {
...@@ -324,7 +323,7 @@ public class SharedMediaQuery { ...@@ -324,7 +323,7 @@ public class SharedMediaQuery {
while (cursor.next()) { while (cursor.next()) {
ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
TLRPC.Message message = (TLRPC.Message) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
message.id = cursor.intValue(1); message.id = cursor.intValue(1);
message.dialog_id = uid; message.dialog_id = uid;
if ((int)uid == 0) { if ((int)uid == 0) {
......
/*
* This is the source code of Telegram for Android v. 2.x
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013-2015.
*/
package org.telegram.android.query;
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLitePreparedStatement;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.MessagesStorage;
import org.telegram.android.NotificationCenter;
import org.telegram.messenger.ByteBufferDesc;
import org.telegram.messenger.ConnectionsManager;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.RPCRequest;
import org.telegram.messenger.TLObject;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.Utilities;
import java.util.ArrayList;
import java.util.HashMap;
public class StickersQuery {
private static String hash;
private static int loadDate;
private static ArrayList<TLRPC.Document> stickers = new ArrayList<>();
private static HashMap<String, ArrayList<TLRPC.Document>> allStickers = new HashMap<>();
private static boolean loadingStickers;
public static void checkStickers() {
if (!loadingStickers && (allStickers.isEmpty() || loadDate < (System.currentTimeMillis() / 1000 - 60 * 60))) {
loadStickers(true);
}
}
public static ArrayList<TLRPC.Document> getStickers() {
return stickers;
}
private static void loadStickers(boolean cache) {
if (loadingStickers) {
return;
}
loadingStickers = true;
if (cache) {
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
TLRPC.messages_AllStickers result = null;
int date = 0;
try {
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT data, date FROM stickers WHERE 1");
ArrayList<TLRPC.User> loadedUsers = new ArrayList<>();
if (cursor.next()) {
ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
result = TLRPC.messages_AllStickers.TLdeserialize(data, data.readInt32(false), false);
}
date = cursor.intValue(1);
MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data);
}
cursor.dispose();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
processLoadedStickers(result, true, date);
}
});
} else {
TLRPC.TL_messages_getAllStickers req = new TLRPC.TL_messages_getAllStickers();
req.hash = hash;
if (req.hash == null) {
req.hash = "";
}
ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(final TLObject response, final TLRPC.TL_error error) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
processLoadedStickers((TLRPC.messages_AllStickers) response, false, (int) (System.currentTimeMillis() / 1000));
}
});
}
});
}
}
private static void putStickersToCache(final TLRPC.TL_messages_allStickers stickers) {
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
@Override
public void run() {
try {
SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO stickers VALUES(?, ?, ?)");
state.requery();
ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(stickers.getObjectSize());
stickers.serializeToStream(data);
state.bindInteger(1, 1);
state.bindByteBuffer(2, data.buffer);
state.bindInteger(3, (int) (System.currentTimeMillis() / 1000));
state.step();
MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data);
state.dispose();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
}
});
}
private static void processLoadedStickers(final TLRPC.messages_AllStickers res, final boolean cache, final int date) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
loadingStickers = false;
}
});
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if ((res == null || date < (int) (System.currentTimeMillis() / 1000 - 60 * 60)) && cache) {
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
loadStickers(false);
}
});
if (res == null) {
return;
}
}
if (res instanceof TLRPC.TL_messages_allStickers) {
if (!cache) {
putStickersToCache((TLRPC.TL_messages_allStickers) res);
}
HashMap<Long, TLRPC.Document> documents = new HashMap<>();
for (TLRPC.Document document : res.documents) {
if (document == null) {
continue;
}
documents.put(document.id, document);
if (document.thumb != null && document.thumb.location != null) {
document.thumb.location.ext = "webp";
}
}
final HashMap<String, ArrayList<TLRPC.Document>> result = new HashMap<>();
for (TLRPC.TL_stickerPack stickerPack : res.packs) {
if (stickerPack != null && stickerPack.emoticon != null) {
stickerPack.emoticon = stickerPack.emoticon.replace("\uFE0F", "");
ArrayList<TLRPC.Document> arrayList = result.get(stickerPack.emoticon);
for (Long id : stickerPack.documents) {
TLRPC.Document document = documents.get(id);
if (document != null) {
if (arrayList == null) {
arrayList = new ArrayList<>();
result.put(stickerPack.emoticon, arrayList);
}
arrayList.add(document);
}
}
}
}
AndroidUtilities.runOnUIThread(new Runnable() {
@Override
public void run() {
allStickers = result;
stickers = res.documents;
hash = res.hash;
loadDate = date;
NotificationCenter.getInstance().postNotificationName(NotificationCenter.stickersDidLoaded);
}
});
}
}
});
}
}
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific languag`e governing permissions and
* limitations under the License.
*/
package org.telegram.android.support.widget;
import android.view.View;
/**
* Helper class that keeps temporary state while {LayoutManager} is filling out the empty
* space.
*/
class LayoutState {
final static String TAG = "LayoutState";
final static int LAYOUT_START = -1;
final static int LAYOUT_END = 1;
final static int INVALID_LAYOUT = Integer.MIN_VALUE;
final static int ITEM_DIRECTION_HEAD = -1;
final static int ITEM_DIRECTION_TAIL = 1;
final static int SCOLLING_OFFSET_NaN = Integer.MIN_VALUE;
/**
* Number of pixels that we should fill, in the layout direction.
*/
int mAvailable;
/**
* Current position on the adapter to get the next item.
*/
int mCurrentPosition;
/**
* Defines the direction in which the data adapter is traversed.
* Should be {@link #ITEM_DIRECTION_HEAD} or {@link #ITEM_DIRECTION_TAIL}
*/
int mItemDirection;
/**
* Defines the direction in which the layout is filled.
* Should be {@link #LAYOUT_START} or {@link #LAYOUT_END}
*/
int mLayoutDirection;
/**
* Used if you want to pre-layout items that are not yet visible.
* The difference with {@link #mAvailable} is that, when recycling, distance rendered for
* {@link #mExtra} is not considered not to recycle visible children.
*/
int mExtra = 0;
/**
* @return true if there are more items in the data adapter
*/
boolean hasMore(RecyclerView.State state) {
return mCurrentPosition >= 0 && mCurrentPosition < state.getItemCount();
}
/**
* Gets the view for the next element that we should render.
* Also updates current item index to the next item, based on {@link #mItemDirection}
*
* @return The next element that we should render.
*/
View next(RecyclerView.Recycler recycler) {
final View view = recycler.getViewForPosition(mCurrentPosition);
mCurrentPosition += mItemDirection;
return view;
}
}
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.telegram.android.support.widget;
import java.util.List;
import org.telegram.android.support.widget.AdapterHelper.UpdateOp;
import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.ADD;
import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.MOVE;
import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.REMOVE;
import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.UPDATE;
class OpReorderer {
final Callback mCallback;
public OpReorderer(Callback callback) {
mCallback = callback;
}
void reorderOps(List<UpdateOp> ops) {
// since move operations breaks continuity, their effects on ADD/RM are hard to handle.
// we push them to the end of the list so that they can be handled easily.
int badMove;
while ((badMove = getLastMoveOutOfOrder(ops)) != -1) {
swapMoveOp(ops, badMove, badMove + 1);
}
}
private void swapMoveOp(List<UpdateOp> list, int badMove, int next) {
final UpdateOp moveOp = list.get(badMove);
final UpdateOp nextOp = list.get(next);
switch (nextOp.cmd) {
case REMOVE:
swapMoveRemove(list, badMove, moveOp, next, nextOp);
break;
case ADD:
swapMoveAdd(list, badMove, moveOp, next, nextOp);
break;
case UPDATE:
swapMoveUpdate(list, badMove, moveOp, next, nextOp);
break;
}
}
void swapMoveRemove(List<UpdateOp> list, int movePos, UpdateOp moveOp,
int removePos, UpdateOp removeOp) {
UpdateOp extraRm = null;
// check if move is nulled out by remove
boolean revertedMove = false;
final boolean moveIsBackwards;
if (moveOp.positionStart < moveOp.itemCount) {
moveIsBackwards = false;
if (removeOp.positionStart == moveOp.positionStart
&& removeOp.itemCount == moveOp.itemCount - moveOp.positionStart) {
revertedMove = true;
}
} else {
moveIsBackwards = true;
if (removeOp.positionStart == moveOp.itemCount + 1 &&
removeOp.itemCount == moveOp.positionStart - moveOp.itemCount) {
revertedMove = true;
}
}
// going in reverse, first revert the effect of add
if (moveOp.itemCount < removeOp.positionStart) {
removeOp.positionStart--;
} else if (moveOp.itemCount < removeOp.positionStart + removeOp.itemCount) {
// move is removed.
removeOp.itemCount --;
moveOp.cmd = REMOVE;
moveOp.itemCount = 1;
if (removeOp.itemCount == 0) {
list.remove(removePos);
mCallback.recycleUpdateOp(removeOp);
}
// no need to swap, it is already a remove
return;
}
// now affect of add is consumed. now apply effect of first remove
if (moveOp.positionStart <= removeOp.positionStart) {
removeOp.positionStart++;
} else if (moveOp.positionStart < removeOp.positionStart + removeOp.itemCount) {
final int remaining = removeOp.positionStart + removeOp.itemCount
- moveOp.positionStart;
extraRm = mCallback.obtainUpdateOp(REMOVE, moveOp.positionStart + 1, remaining);
removeOp.itemCount = moveOp.positionStart - removeOp.positionStart;
}
// if effects of move is reverted by remove, we are done.
if (revertedMove) {
list.set(movePos, removeOp);
list.remove(removePos);
mCallback.recycleUpdateOp(moveOp);
return;
}
// now find out the new locations for move actions
if (moveIsBackwards) {
if (extraRm != null) {
if (moveOp.positionStart > extraRm.positionStart) {
moveOp.positionStart -= extraRm.itemCount;
}
if (moveOp.itemCount > extraRm.positionStart) {
moveOp.itemCount -= extraRm.itemCount;
}
}
if (moveOp.positionStart > removeOp.positionStart) {
moveOp.positionStart -= removeOp.itemCount;
}
if (moveOp.itemCount > removeOp.positionStart) {
moveOp.itemCount -= removeOp.itemCount;
}
} else {
if (extraRm != null) {
if (moveOp.positionStart >= extraRm.positionStart) {
moveOp.positionStart -= extraRm.itemCount;
}
if (moveOp.itemCount >= extraRm.positionStart) {
moveOp.itemCount -= extraRm.itemCount;
}
}
if (moveOp.positionStart >= removeOp.positionStart) {
moveOp.positionStart -= removeOp.itemCount;
}
if (moveOp.itemCount >= removeOp.positionStart) {
moveOp.itemCount -= removeOp.itemCount;
}
}
list.set(movePos, removeOp);
if (moveOp.positionStart != moveOp.itemCount) {
list.set(removePos, moveOp);
} else {
list.remove(removePos);
}
if (extraRm != null) {
list.add(movePos, extraRm);
}
}
private void swapMoveAdd(List<UpdateOp> list, int move, UpdateOp moveOp, int add,
UpdateOp addOp) {
int offset = 0;
// going in reverse, first revert the effect of add
if (moveOp.itemCount < addOp.positionStart) {
offset--;
}
if (moveOp.positionStart < addOp.positionStart) {
offset++;
}
if (addOp.positionStart <= moveOp.positionStart) {
moveOp.positionStart += addOp.itemCount;
}
if (addOp.positionStart <= moveOp.itemCount) {
moveOp.itemCount += addOp.itemCount;
}
addOp.positionStart += offset;
list.set(move, addOp);
list.set(add, moveOp);
}
void swapMoveUpdate(List<UpdateOp> list, int move, UpdateOp moveOp, int update,
UpdateOp updateOp) {
UpdateOp extraUp1 = null;
UpdateOp extraUp2 = null;
// going in reverse, first revert the effect of add
if (moveOp.itemCount < updateOp.positionStart) {
updateOp.positionStart--;
} else if (moveOp.itemCount < updateOp.positionStart + updateOp.itemCount) {
// moved item is updated. add an update for it
updateOp.itemCount--;
extraUp1 = mCallback.obtainUpdateOp(UPDATE, moveOp.positionStart, 1);
}
// now affect of add is consumed. now apply effect of first remove
if (moveOp.positionStart <= updateOp.positionStart) {
updateOp.positionStart++;
} else if (moveOp.positionStart < updateOp.positionStart + updateOp.itemCount) {
final int remaining = updateOp.positionStart + updateOp.itemCount
- moveOp.positionStart;
extraUp2 = mCallback.obtainUpdateOp(UPDATE, moveOp.positionStart + 1, remaining);
updateOp.itemCount -= remaining;
}
list.set(update, moveOp);
if (updateOp.itemCount > 0) {
list.set(move, updateOp);
} else {
list.remove(move);
mCallback.recycleUpdateOp(updateOp);
}
if (extraUp1 != null) {
list.add(move, extraUp1);
}
if (extraUp2 != null) {
list.add(move, extraUp2);
}
}
private int getLastMoveOutOfOrder(List<UpdateOp> list) {
boolean foundNonMove = false;
for (int i = list.size() - 1; i >= 0; i--) {
final UpdateOp op1 = list.get(i);
if (op1.cmd == MOVE) {
if (foundNonMove) {
return i;
}
} else {
foundNonMove = true;
}
}
return -1;
}
static interface Callback {
UpdateOp obtainUpdateOp(int cmd, int startPosition, int itemCount);
void recycleUpdateOp(UpdateOp op);
}
}
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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