diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 165f3ce06..1d10d14f7 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -5,7 +5,7 @@ repositories { } dependencies { - compile 'com.android.support:support-v4:23.0.+' + compile 'com.android.support:support-v4:23.1.+' compile 'com.google.android.gms:play-services:3.2.+' compile 'net.hockeyapp.android:HockeySDK:3.5.+' compile 'com.googlecode.mp4parser:isoparser:1.0.+' @@ -13,9 +13,11 @@ dependencies { } android { - compileSdkVersion 22 + compileSdkVersion 23 buildToolsVersion '23.0.1' + useLibrary 'org.apache.http.legacy' + packagingOptions { exclude 'META-INF/NOTICE.txt' exclude 'META-INF/LICENSE.txt' @@ -78,8 +80,8 @@ android { defaultConfig { minSdkVersion 8 - targetSdkVersion 22 - versionCode 627 - versionName "3.2.2" + targetSdkVersion 23 + versionCode 654 + versionName "3.2.6" } } diff --git a/TMessagesProj/jni/Android.mk b/TMessagesProj/jni/Android.mk index bd054413d..7953965a6 100755 --- a/TMessagesProj/jni/Android.mk +++ b/TMessagesProj/jni/Android.mk @@ -187,7 +187,7 @@ include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false LOCAL_STATIC_LIBRARIES := webp sqlite tgnet breakpad -LOCAL_MODULE := tmessages.12 +LOCAL_MODULE := tmessages.14 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 += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -ffast-math diff --git a/TMessagesProj/jni/NativeLoader.cpp b/TMessagesProj/jni/NativeLoader.cpp index 546fe1379..d18f4912e 100644 --- a/TMessagesProj/jni/NativeLoader.cpp +++ b/TMessagesProj/jni/NativeLoader.cpp @@ -12,6 +12,7 @@ bool callback(const google_breakpad::MinidumpDescriptor &descriptor, void *conte extern "C" { void Java_org_telegram_messenger_NativeLoader_init(JNIEnv* env, jobject obj, jstring filepath, bool enable) { + return; if (enable) { const char *path = env->GetStringUTFChars(filepath, 0); google_breakpad::MinidumpDescriptor descriptor(path); diff --git a/TMessagesProj/jni/TgNetWrapper.cpp b/TMessagesProj/jni/TgNetWrapper.cpp index 84304c4a6..15591be98 100644 --- a/TMessagesProj/jni/TgNetWrapper.cpp +++ b/TMessagesProj/jni/TgNetWrapper.cpp @@ -194,17 +194,15 @@ class Delegate : public ConnectiosManagerDelegate { } }; -void init(JNIEnv *env, jclass c, jint version, jint layer, jint apiId, jstring deviceModel, jstring systemVersion, jstring appVersion, jstring langCode, jstring configPath, jint userId) { - - - +void init(JNIEnv *env, jclass c, jint version, jint layer, jint apiId, jstring deviceModel, jstring systemVersion, jstring appVersion, jstring langCode, jstring configPath, jstring logPath, jint userId) { const char *deviceModelStr = env->GetStringUTFChars(deviceModel, 0); const char *systemVersionStr = env->GetStringUTFChars(systemVersion, 0); const char *appVersionStr = env->GetStringUTFChars(appVersion, 0); const char *langCodeStr = env->GetStringUTFChars(langCode, 0); const char *configPathStr = env->GetStringUTFChars(configPath, 0); + const char *logPathStr = env->GetStringUTFChars(logPath, 0); - ConnectionsManager::getInstance().init(version, layer, apiId, std::string(deviceModelStr), std::string(systemVersionStr), std::string(appVersionStr), std::string(langCodeStr), std::string(configPathStr), userId, true); + ConnectionsManager::getInstance().init(version, layer, apiId, std::string(deviceModelStr), std::string(systemVersionStr), std::string(appVersionStr), std::string(langCodeStr), std::string(configPathStr), std::string(logPathStr), userId, true); if (deviceModelStr != 0) { env->ReleaseStringUTFChars(deviceModel, deviceModelStr); @@ -221,6 +219,9 @@ void init(JNIEnv *env, jclass c, jint version, jint layer, jint apiId, jstring d if (configPathStr != 0) { env->ReleaseStringUTFChars(configPath, configPathStr); } + if (logPathStr != 0) { + env->ReleaseStringUTFChars(logPath, logPathStr); + } } void setJava(JNIEnv *env, jclass c, jboolean useJavaByteBuffers) { @@ -241,7 +242,7 @@ static JNINativeMethod ConnectionsManagerMethods[] = { {"native_applyDatacenterAddress", "(ILjava/lang/String;I)V", (void *) applyDatacenterAddress}, {"native_getConnectionState", "()I", (void *) getConnectionState}, {"native_setUserId", "(I)V", (void *) setUserId}, - {"native_init", "(IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V", (void *) init}, + {"native_init", "(IIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V", (void *) init}, {"native_switchBackend", "()V", (void *) switchBackend}, {"native_pauseNetwork", "()V", (void *) pauseNetwork}, {"native_resumeNetwork", "(Z)V", (void *) resumeNetwork}, diff --git a/TMessagesProj/jni/boringssl/crypto/.gitignore b/TMessagesProj/jni/boringssl/crypto/.gitignore new file mode 100644 index 000000000..086334327 --- /dev/null +++ b/TMessagesProj/jni/boringssl/crypto/.gitignore @@ -0,0 +1 @@ +*.txt~ diff --git a/TMessagesProj/jni/breakpad/LICENSE b/TMessagesProj/jni/breakpad/LICENSE new file mode 100644 index 000000000..95207bdf6 --- /dev/null +++ b/TMessagesProj/jni/breakpad/LICENSE @@ -0,0 +1,50 @@ +Copyright (c) 2006, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-------------------------------------------------------------------- + +Copyright 2001-2004 Unicode, Inc. + +Disclaimer + +This source code is provided as is by Unicode, Inc. No claims are +made as to fitness for any particular purpose. No warranties of any +kind are expressed or implied. The recipient agrees to determine +applicability of information provided. If this file has been +purchased on magnetic or optical media from Unicode, Inc., the +sole remedy for any claim will be exchange of defective media +within 90 days of receipt. + +Limitations on Rights to Redistribute This Code + +Unicode, Inc. hereby grants the right to freely use the information +supplied in this file in the creation of products supporting the +Unicode Standard, and to make copies of this file in any form +for internal or external distribution as long as this notice +remains attached. diff --git a/TMessagesProj/jni/giflib/COPYING b/TMessagesProj/jni/giflib/COPYING new file mode 100644 index 000000000..b9c0b5012 --- /dev/null +++ b/TMessagesProj/jni/giflib/COPYING @@ -0,0 +1,19 @@ +The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/TMessagesProj/jni/image.c b/TMessagesProj/jni/image.c index a2cc1dfb8..5445075b7 100644 --- a/TMessagesProj/jni/image.c +++ b/TMessagesProj/jni/image.c @@ -16,11 +16,6 @@ jfieldID jclass_Options_inJustDecodeBounds; jfieldID jclass_Options_outHeight; jfieldID jclass_Options_outWidth; -jclass jclass_Bitmap; -jmethodID jclass_Bitmap_createBitmap; -jclass jclass_Config; -jfieldID jclass_Config_ARGB_8888; - const uint32_t PGPhotoEnhanceHistogramBins = 256; const uint32_t PGPhotoEnhanceSegments = 4; @@ -58,24 +53,6 @@ jint imageOnJNILoad(JavaVM *vm, void *reserved, JNIEnv *env) { return -1; } - jclass_Bitmap = createGlobarRef(env, (*env)->FindClass(env, "android/graphics/Bitmap")); - if (jclass_Bitmap == 0) { - return -1; - } - jclass_Bitmap_createBitmap = (*env)->GetStaticMethodID(env, jclass_Bitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;"); - if (jclass_Bitmap_createBitmap == 0) { - return -1; - } - - jclass_Config = createGlobarRef(env, (*env)->FindClass(env, "android/graphics/Bitmap$Config")); - if (jclass_Config == 0) { - return -1; - } - jclass_Config_ARGB_8888 = (*env)->GetStaticFieldID(env, jclass_Config, "ARGB_8888", "Landroid/graphics/Bitmap$Config;"); - if (jclass_Config_ARGB_8888 == 0) { - return -1; - } - return JNI_VERSION_1_6; } @@ -511,7 +488,7 @@ JNIEXPORT void Java_org_telegram_messenger_Utilities_loadBitmap(JNIEnv *env, jcl } } -JNIEXPORT jobject Java_org_telegram_messenger_Utilities_loadWebpImage(JNIEnv *env, jclass class, jobject buffer, int len, jobject options) { +JNIEXPORT jboolean Java_org_telegram_messenger_Utilities_loadWebpImage(JNIEnv *env, jclass class, jobject outputBitmap, jobject buffer, jint len, jobject options, jboolean unpin) { if (!buffer) { (*env)->ThrowNew(env, jclass_NullPointerException, "Input buffer can not be null"); return 0; @@ -529,43 +506,36 @@ JNIEXPORT jobject Java_org_telegram_messenger_Utilities_loadWebpImage(JNIEnv *en if (options && (*env)->GetBooleanField(env, options, jclass_Options_inJustDecodeBounds) == JNI_TRUE) { (*env)->SetIntField(env, options, jclass_Options_outWidth, bitmapWidth); (*env)->SetIntField(env, options, jclass_Options_outHeight, bitmapHeight); - return 0; + return 1; } - - jobject value__ARGB_8888 = (*env)->GetStaticObjectField(env, jclass_Config, jclass_Config_ARGB_8888); - jobject outputBitmap = (*env)->CallStaticObjectMethod(env, jclass_Bitmap, jclass_Bitmap_createBitmap, (jint)bitmapWidth, (jint)bitmapHeight, value__ARGB_8888); + if (!outputBitmap) { - (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to allocate Bitmap"); + (*env)->ThrowNew(env, jclass_NullPointerException, "output bitmap can not be null"); return 0; } - outputBitmap = (*env)->NewLocalRef(env, outputBitmap); AndroidBitmapInfo bitmapInfo; if (AndroidBitmap_getInfo(env, outputBitmap, &bitmapInfo) != ANDROID_BITMAP_RESUT_SUCCESS) { - (*env)->DeleteLocalRef(env, outputBitmap); (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to get Bitmap information"); return 0; } void *bitmapPixels = 0; if (AndroidBitmap_lockPixels(env, outputBitmap, &bitmapPixels) != ANDROID_BITMAP_RESUT_SUCCESS) { - (*env)->DeleteLocalRef(env, outputBitmap); (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to lock Bitmap pixels"); return 0; } if (!WebPDecodeRGBAInto((uint8_t*)inputBuffer, len, (uint8_t*)bitmapPixels, bitmapInfo.height * bitmapInfo.stride, bitmapInfo.stride)) { AndroidBitmap_unlockPixels(env, outputBitmap); - (*env)->DeleteLocalRef(env, outputBitmap); (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to decode webp image"); return 0; } - if (AndroidBitmap_unlockPixels(env, outputBitmap) != ANDROID_BITMAP_RESUT_SUCCESS) { - (*env)->DeleteLocalRef(env, outputBitmap); + if (unpin && AndroidBitmap_unlockPixels(env, outputBitmap) != ANDROID_BITMAP_RESUT_SUCCESS) { (*env)->ThrowNew(env, jclass_RuntimeException, "Failed to unlock Bitmap pixels"); return 0; } - return outputBitmap; + return 1; } diff --git a/TMessagesProj/jni/libjpeg/NOTICE b/TMessagesProj/jni/libjpeg/NOTICE new file mode 100644 index 000000000..70e356f72 --- /dev/null +++ b/TMessagesProj/jni/libjpeg/NOTICE @@ -0,0 +1,94 @@ +This software is based in part on the work of the Independent JPEG Group. + +---------------------- + +The authors make NO WARRANTY or representation, either express or implied, +with respect to this software, its quality, accuracy, merchantability, or +fitness for a particular purpose. This software is provided "AS IS", and you, +its user, assume the entire risk as to its quality and accuracy. + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + + +---------------------- + + + ARM NEON optimizations for libjpeg-turbo + + Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). + All rights reserved. + Contact: Alexander Bokovoy + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + + ---------------------- + + + Copyright (c) 2011, NVIDIA CORPORATION. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the NVIDIA CORPORATION nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. diff --git a/TMessagesProj/jni/libwebp/AUTHORS b/TMessagesProj/jni/libwebp/AUTHORS new file mode 100644 index 000000000..f0a85f9b9 --- /dev/null +++ b/TMessagesProj/jni/libwebp/AUTHORS @@ -0,0 +1,24 @@ +Contributors: +- Charles Munger (clm at google dot com) +- Christian Duvivier (cduvivier at google dot com) +- Djordje Pesut (djordje dot pesut at imgtec dot com) +- James Zern (jzern at google dot com) +- Jan Engelhardt (jengelh at medozas dot de) +- Johann (johann dot koenig at duck dot com) +- Jovan Zelincevic (jovan dot zelincevic at imgtec dot com) +- Jyrki Alakuijala (jyrki at google dot com) +- levytamar82 (tamar dot levy at intel dot com) +- Lou Quillio (louquillio at google dot com) +- Mans Rullgard (mans at mansr dot com) +- Martin Olsson (mnemo at minimum dot se) +- Mikołaj Zalewski (mikolajz at google dot com) +- Noel Chromium (noel at chromium dot org) +- Pascal Massimino (pascal dot massimino at gmail dot com) +- Paweł Hajdan, Jr (phajdan dot jr at chromium dot org) +- Pierre Joye (pierre dot php at gmail dot com) +- Scott LaVarnway (slavarnway at google dot com) +- Scott Talbot (s at chikachow dot org) +- Slobodan Prijic (slobodan dot prijic at imgtec dot com) +- Somnath Banerjee (somnath dot banerjee at gmail dot com) +- Urvang Joshi (urvang at google dot com) +- Vikas Arora (vikasa at google dot com) diff --git a/TMessagesProj/jni/libwebp/COPYING b/TMessagesProj/jni/libwebp/COPYING new file mode 100644 index 000000000..7a6f99547 --- /dev/null +++ b/TMessagesProj/jni/libwebp/COPYING @@ -0,0 +1,30 @@ +Copyright (c) 2010, Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/TMessagesProj/jni/libwebp/PATENTS b/TMessagesProj/jni/libwebp/PATENTS new file mode 100644 index 000000000..caedf607e --- /dev/null +++ b/TMessagesProj/jni/libwebp/PATENTS @@ -0,0 +1,23 @@ +Additional IP Rights Grant (Patents) +------------------------------------ + +"These implementations" means the copyrightable works that implement the WebM +codecs distributed by Google as part of the WebM Project. + +Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge, +royalty-free, irrevocable (except as stated in this section) patent license to +make, have made, use, offer to sell, sell, import, transfer, and otherwise +run, modify and propagate the contents of these implementations of WebM, where +such license applies only to those patent claims, both currently owned by +Google and acquired in the future, licensable by Google that are necessarily +infringed by these implementations of WebM. This grant does not include claims +that would be infringed only as a consequence of further modification of these +implementations. If you or your agent or exclusive licensee institute or order +or agree to the institution of patent litigation or any other patent +enforcement activity against any entity (including a cross-claim or +counterclaim in a lawsuit) alleging that any of these implementations of WebM +or any code incorporated within any of these implementations of WebM +constitute direct or contributory patent infringement, or inducement of +patent infringement, then any patent rights granted to you under this License +for these implementations of WebM shall terminate as of the date such +litigation is filed. diff --git a/TMessagesProj/jni/libyuv/AUTHORS b/TMessagesProj/jni/libyuv/AUTHORS new file mode 100644 index 000000000..9686ac13e --- /dev/null +++ b/TMessagesProj/jni/libyuv/AUTHORS @@ -0,0 +1,4 @@ +# Names should be added to this file like so: +# Name or Organization + +Google Inc. diff --git a/TMessagesProj/jni/libyuv/LICENSE b/TMessagesProj/jni/libyuv/LICENSE new file mode 100644 index 000000000..c911747a6 --- /dev/null +++ b/TMessagesProj/jni/libyuv/LICENSE @@ -0,0 +1,29 @@ +Copyright 2011 The LibYuv Project Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name of Google nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/TMessagesProj/jni/libyuv/LICENSE_THIRD_PARTY b/TMessagesProj/jni/libyuv/LICENSE_THIRD_PARTY new file mode 100644 index 000000000..a71591e77 --- /dev/null +++ b/TMessagesProj/jni/libyuv/LICENSE_THIRD_PARTY @@ -0,0 +1,8 @@ +This source tree contains third party source code which is governed by third +party licenses. This file contains references to files which are under other +licenses than the one provided in the LICENSE file in the root of the source +tree. + +Files governed by third party licenses: +source/x86inc.asm + diff --git a/TMessagesProj/jni/libyuv/PATENTS b/TMessagesProj/jni/libyuv/PATENTS new file mode 100644 index 000000000..64aa5c90d --- /dev/null +++ b/TMessagesProj/jni/libyuv/PATENTS @@ -0,0 +1,24 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the LibYuv code package. + +Google hereby grants to you a perpetual, worldwide, non-exclusive, +no-charge, irrevocable (except as stated in this section) patent +license to make, have made, use, offer to sell, sell, import, +transfer, and otherwise run, modify and propagate the contents of this +implementation of the LibYuv code package, where such license applies +only to those patent claims, both currently owned by Google and +acquired in the future, licensable by Google that are necessarily +infringed by this implementation of the LibYuv code package. This +grant does not include claims that would be infringed only as a +consequence of further modification of this implementation. If you or +your agent or exclusive licensee institute or order or agree to the +institution of patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that this +implementation of the LibYuv code package or any code incorporated +within this implementation of the LibYuv code package constitutes +direct or contributory patent infringement, or inducement of patent +infringement, then any patent rights granted to you under this License +for this implementation of the LibYuv code package shall terminate as +of the date such litigation is filed. \ No newline at end of file diff --git a/TMessagesProj/jni/opus/AUTHORS b/TMessagesProj/jni/opus/AUTHORS new file mode 100644 index 000000000..b3d22a20c --- /dev/null +++ b/TMessagesProj/jni/opus/AUTHORS @@ -0,0 +1,6 @@ +Jean-Marc Valin (jmvalin@jmvalin.ca) +Koen Vos (koenvos74@gmail.com) +Timothy Terriberry (tterribe@xiph.org) +Karsten Vandborg Sorensen (karsten.vandborg.sorensen@skype.net) +Soren Skak Jensen (ssjensen@gn.com) +Gregory Maxwell (greg@xiph.org) diff --git a/TMessagesProj/jni/opus/COPYING b/TMessagesProj/jni/opus/COPYING new file mode 100644 index 000000000..9c739c34a --- /dev/null +++ b/TMessagesProj/jni/opus/COPYING @@ -0,0 +1,44 @@ +Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic, + Jean-Marc Valin, Timothy B. Terriberry, + CSIRO, Gregory Maxwell, Mark Borgerding, + Erik de Castro Lopo + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +- Neither the name of Internet Society, IETF or IETF Trust, nor the +names of specific contributors, may be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Opus is subject to the royalty-free patent licenses which are +specified at: + +Xiph.Org Foundation: +https://datatracker.ietf.org/ipr/1524/ + +Microsoft Corporation: +https://datatracker.ietf.org/ipr/1914/ + +Broadcom Corporation: +https://datatracker.ietf.org/ipr/1526/ diff --git a/TMessagesProj/jni/tgnet/Connection.cpp b/TMessagesProj/jni/tgnet/Connection.cpp index cd6041462..16a544f25 100644 --- a/TMessagesProj/jni/tgnet/Connection.cpp +++ b/TMessagesProj/jni/tgnet/Connection.cpp @@ -266,7 +266,11 @@ void Connection::connect() { if (isTryingNextPort) { setTimeout(8); } else { - setTimeout(15); + if (connectionType == ConnectionTypeUpload) { + setTimeout(25); + } else { + setTimeout(15); + } } } } diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index 6825dee04..fc6567d2f 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -220,7 +220,7 @@ void ConnectionsManager::select() { return; } else { lastPauseTime = now; - DEBUG_D("don't sleep 30 seconds because of salt, upload or download request"); + DEBUG_D("don't sleep 10 seconds because of salt, upload or download request"); } } if (networkPaused) { @@ -595,7 +595,7 @@ void ConnectionsManager::onConnectionConnected(Connection *connection) { } else { if (networkPaused && lastPauseTime != 0) { lastPauseTime = getCurrentTimeMillis(); - nextSleepTimeout = 30000; + nextSleepTimeout = 10000; } processRequestQueue(connection->getConnectionType(), datacenter->getDatacenterId()); } @@ -819,7 +819,8 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag for (requestsIter iter = runningRequests.begin(); iter != runningRequests.end(); iter++) { Request *request = iter->get(); - if (request->messageId < response->first_msg_id && request->connectionType & connection->getConnectionType() && request->datacenterId == datacenter->getDatacenterId()) { + Datacenter *requestDatacenter = getDatacenterWithId(request->datacenterId); + if (request->messageId < response->first_msg_id && request->connectionType & connection->getConnectionType() && requestDatacenter != nullptr && requestDatacenter->getDatacenterId() == datacenter->getDatacenterId()) { request->clear(true); } } @@ -908,8 +909,9 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag RpcError *error = hasResult ? dynamic_cast(response->result.get()) : nullptr; if (error != nullptr) { DEBUG_E("connection(%p, dc%u, type %d) rpc error %d: %s", connection, datacenter->getDatacenterId(), connection->getConnectionType(), error->error_code, error->error_message.c_str()); - uint32_t migrateToDatacenterId = DEFAULT_DATACENTER_ID; if (error->error_code == 303) { + uint32_t migrateToDatacenterId = DEFAULT_DATACENTER_ID; + static std::vector migrateErrors; if (migrateErrors.empty()) { migrateErrors.push_back("NETWORK_MIGRATE_"); @@ -926,11 +928,11 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag migrateToDatacenterId = val; } } - } - - if (migrateToDatacenterId != DEFAULT_DATACENTER_ID) { - ignoreResult = true; - moveToDatacenter(migrateToDatacenterId); + + if (migrateToDatacenterId != DEFAULT_DATACENTER_ID) { + ignoreResult = true; + moveToDatacenter(migrateToDatacenterId); + } } } @@ -950,7 +952,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag NativeByteBuffer *unpacked_data = nullptr; TLObject *result = response->result.get(); if (typeid(*result) == typeid(TL_gzip_packed)) { - TL_gzip_packed *innerResponse = (TL_gzip_packed *) response->result.get(); + TL_gzip_packed *innerResponse = (TL_gzip_packed *) result; unpacked_data = decompressGZip(innerResponse->packed_data.get()); TLObject *object = TLdeserialize(request->rawRequest, unpacked_data->limit(), unpacked_data); if (object != nullptr) { @@ -963,16 +965,14 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag TL_error *error2 = hasResult ? dynamic_cast(response->result.get()) : nullptr; if (error != nullptr) { allowInitConnection = false; - DEBUG_E("rpc error %d: %s", error->error_code, error->error_message.c_str()); + DEBUG_E("request %p rpc error %d: %s", request, error->error_code, error->error_message.c_str()); - if (error->error_code == 500 || error->error_code < 0) { - if (!(request->requestFlags & RequestFlagFailOnServerErrors)) { - request->serverFailureCount++; + if ((request->requestFlags & RequestFlagFailOnServerErrors) == 0) { + if (error->error_code == 500 || error->error_code < 0) { discardResponse = true; - request->minStartTime = request->startTime + request->serverFailureCount > 10 ? 10 : request->serverFailureCount; - } - } else if (error->error_code == 420) { - if (!(request->requestFlags & RequestFlagFailOnServerErrors)) { + request->minStartTime = request->startTime + (request->serverFailureCount > 10 ? 10 : request->serverFailureCount); + request->serverFailureCount++; + } else if (error->error_code == 420) { int32_t waitTime = 2; static std::string floodWait = "FLOOD_WAIT_"; if (error->error_message.find(floodWait) != std::string::npos) { @@ -988,10 +988,11 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag request->minStartTime = (int32_t) (getCurrentTimeMillis() / 1000 + waitTime); } } - - implicitError = new TL_error(); - implicitError->code = error->error_code; - implicitError->text = error->error_message; + if (!discardResponse) { + implicitError = new TL_error(); + implicitError->code = error->error_code; + implicitError->text = error->error_message; + } } else if (error2 == nullptr) { if (request->rawRequest == nullptr || response->result == nullptr) { allowInitConnection = false; @@ -1114,7 +1115,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag int64_t time = (int64_t) (messageId / 4294967296.0 * 1000); int64_t currentTime = getCurrentTimeMillis(); timeDifference = (int32_t) ((time - currentTime) / 1000 - currentPingTime / 2); - lastOutgoingMessageId = messageId > lastOutgoingMessageId ? messageId : lastOutgoingMessageId; + lastOutgoingMessageId = messageId > (lastOutgoingMessageId ? messageId : lastOutgoingMessageId); } int64_t resultMid = response->bad_msg_id; if (resultMid != 0) { @@ -1207,7 +1208,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag } else if (connection->connectionType == ConnectionTypePush && typeInfo == typeid(TL_updatesTooLong)) { if (networkPaused) { lastPauseTime = getCurrentTimeMillis(); - nextSleepTimeout = 30000; + nextSleepTimeout = 10000; DEBUG_D("received internal push: wakeup network in background"); } else if (lastPauseTime != 0) { lastPauseTime = getCurrentTimeMillis(); @@ -1389,11 +1390,13 @@ void ConnectionsManager::sendRequest(TLObject *object, onCompleteFunc onComplete return; } scheduleTask([&, requestToken, object, onComplete, onQuickAck, flags, datacenterId, connetionType, immediate, ptr1, ptr2] { + DEBUG_D("send request %p - %s", object, typeid(*object).name()); Request *request = new Request(requestToken, connetionType, flags, datacenterId, onComplete, onQuickAck); request->rawRequest = object; request->ptr1 = ptr1; request->ptr2 = ptr2; request->rpcRequest = wrapInLayer(object, getDatacenterWithId(datacenterId), request); + DEBUG_D("send request wrapped %p - %s", request->rpcRequest.get(), typeid(*request->rpcRequest.get()).name()); requestsQueue.push_back(std::unique_ptr(request)); if (immediate) { processRequestQueue(0, 0); @@ -1780,7 +1783,9 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t continue; } - bool forceThisRequest = request->connectionType & connectionTypes && request->datacenterId == dc; + uint32_t requestConnectionType = request->connectionType & 0x0000ffff; + + bool forceThisRequest = (connectionTypes & requestConnectionType) && requestDatacenter->getDatacenterId() == dc; if (typeInfo == typeid(TL_get_future_salts) || typeInfo == typeid(TL_destroy_session)) { if (request->messageId != 0) { @@ -1790,7 +1795,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t forceThisRequest = false; } - if (((abs(currentTime - request->startTime) > maxTimeout) && (currentTime > request->minStartTime || abs(currentTime - request->minStartTime) > 60)) || forceThisRequest) { + if (forceThisRequest || (abs(currentTime - request->startTime) > maxTimeout && (currentTime > request->minStartTime || abs(currentTime - request->minStartTime) > 60))) { if (!forceThisRequest && request->connectionToken > 0) { if (request->connectionType & ConnectionTypeGeneric && request->connectionToken == connection->getConnectionToken()) { DEBUG_D("request token is valid, not retrying %s", typeInfo.name()); @@ -1849,7 +1854,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t networkMessage->needQuickAck = (request->requestFlags & RequestFlagNeedQuickAck) != 0; request->connectionToken = connection->getConnectionToken(); - switch (request->connectionType & 0x0000ffff) { + switch (requestConnectionType) { case ConnectionTypeGeneric: addMessageToDatacenter(requestDatacenter->getDatacenterId(), networkMessage, genericMessagesToDatacenters); break; @@ -2369,7 +2374,7 @@ void ConnectionsManager::setDelegate(ConnectiosManagerDelegate *connectiosManage delegate = connectiosManagerDelegate; } -void ConnectionsManager::init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string configPath, int32_t userId, bool isPaused) { +void ConnectionsManager::init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string configPath, std::string logPath, int32_t userId, bool isPaused) { currentVersion = version; currentLayer = layer; currentApiId = apiId; @@ -2379,6 +2384,7 @@ void ConnectionsManager::init(uint32_t version, int32_t layer, int32_t apiId, st currentAppVersion = appVersion; currentLangCode = langCode; currentUserId = userId; + currentLogPath = logPath; if (isPaused) { lastPauseTime = getCurrentTimeMillis(); } @@ -2386,6 +2392,10 @@ void ConnectionsManager::init(uint32_t version, int32_t layer, int32_t apiId, st if (!currentConfigPath.empty() && currentConfigPath.find_last_of('/') != currentConfigPath.size() - 1) { currentConfigPath += "/"; } + + if (!logPath.empty()) { + FileLog::init(logPath); + } loadConfig(); @@ -2397,7 +2407,7 @@ void ConnectionsManager::resumeNetwork(bool partial) { if (partial) { if (networkPaused) { lastPauseTime = getCurrentTimeMillis(); - nextSleepTimeout = 30000; + nextSleepTimeout = 10000; networkPaused = false; DEBUG_D("wakeup network in background"); } else if (lastPauseTime != 0) { diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.h b/TMessagesProj/jni/tgnet/ConnectionsManager.h index 32f9476ec..549a4644f 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.h +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.h @@ -59,7 +59,7 @@ public: void pauseNetwork(); void setNetworkAvailable(bool value); void setUseIpv6(bool value); - void init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string configPath, int32_t userId, bool isPaused); + void init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string configPath, std::string logPath, int32_t userId, bool isPaused); void updateDcSettings(uint32_t datacenterId); #ifdef ANDROID @@ -169,6 +169,7 @@ private: std::string currentAppVersion; std::string currentLangCode; std::string currentConfigPath; + std::string currentLogPath; int32_t currentUserId = 0; bool registeredForInternalPush = false; diff --git a/TMessagesProj/jni/tgnet/Datacenter.cpp b/TMessagesProj/jni/tgnet/Datacenter.cpp index 5dd14406c..7b9c7e7ce 100644 --- a/TMessagesProj/jni/tgnet/Datacenter.cpp +++ b/TMessagesProj/jni/tgnet/Datacenter.cpp @@ -37,7 +37,7 @@ Datacenter::Datacenter(uint32_t id) { Datacenter::Datacenter(NativeByteBuffer *data) { for (uint32_t a = 0; a < DOWNLOAD_CONNECTIONS_COUNT; a++) { - downloadConnections[a] = nullptr; + downloadConnections[a] = nullptr; } uint32_t currentVersion = data->readUint32(nullptr); if (currentVersion >= 2 && currentVersion <= 5) { @@ -1377,7 +1377,7 @@ NativeByteBuffer *Datacenter::createRequestsData(std::vectormessage->body.get(); } - DEBUG_D("connection(%p, dc%u, type %d) send message (session: 0x%llx, seqno: %d, messageid: 0x%llx): %s", connection, datacenterId, connection->getConnectionType(), (uint64_t) connection->getSissionId(), networkMessage->message->seqno, (uint64_t) networkMessage->message->msg_id, typeid(*messageBody).name()); + DEBUG_D("connection(%p, dc%u, type %d) send message (session: 0x%llx, seqno: %d, messageid: 0x%llx): %s(%p)", connection, datacenterId, connection->getConnectionType(), (uint64_t) connection->getSissionId(), networkMessage->message->seqno, (uint64_t) networkMessage->message->msg_id, typeid(*messageBody).name(), messageBody); int64_t messageTime = (int64_t) (networkMessage->message->msg_id / 4294967296.0 * 1000); int64_t currentTime = ConnectionsManager::getInstance().getCurrentTimeMillis() + (int64_t) timeDifference * 1000; @@ -1404,7 +1404,7 @@ NativeByteBuffer *Datacenter::createRequestsData(std::vectormessage->body.get(); } - DEBUG_D("connection(%p, dc%u, type %d) send message (session: 0x%llx, seqno: %d, messageid: 0x%llx): %s", connection, datacenterId, connection->getConnectionType(), (uint64_t) connection->getSissionId(), networkMessage->message->seqno, (uint64_t) networkMessage->message->msg_id, typeid(*messageBody).name()); + DEBUG_D("connection(%p, dc%u, type %d) send message (session: 0x%llx, seqno: %d, messageid: 0x%llx): %s(%p)", connection, datacenterId, connection->getConnectionType(), (uint64_t) connection->getSissionId(), networkMessage->message->seqno, (uint64_t) networkMessage->message->msg_id, typeid(*messageBody).name(), messageBody); messageContainer->messages.push_back(std::unique_ptr(std::move(networkMessage->message))); } messageId = ConnectionsManager::getInstance().generateMessageId(); diff --git a/TMessagesProj/jni/tgnet/FileLog.cpp b/TMessagesProj/jni/tgnet/FileLog.cpp index 2827986f9..9bb1df99c 100644 --- a/TMessagesProj/jni/tgnet/FileLog.cpp +++ b/TMessagesProj/jni/tgnet/FileLog.cpp @@ -8,50 +8,84 @@ #include #include +#include #include "FileLog.h" #ifdef ANDROID #include #endif +FILE *logFile = nullptr; + +void FileLog::init(std::string path) { + logFile = fopen(path.c_str(), "w"); +} + void FileLog::e(const char *message, ...) { va_list argptr; va_start(argptr, message); + time_t t = time(0); + struct tm *now = localtime(&t); #ifdef ANDROID __android_log_vprint(ANDROID_LOG_ERROR, "tgnet", message, argptr); #else - printf("error: "); + printf("%d-%d %02d:%02d:%02d error: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); vprintf(message, argptr); printf("\n"); fflush(stdout); #endif + if (logFile) { + fprintf(logFile, "%d-%d %02d:%02d:%02d error: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); + vfprintf(logFile, message, argptr); + fprintf(logFile, "\n"); + fflush(logFile); + } + va_end(argptr); } void FileLog::w(const char *message, ...) { va_list argptr; va_start(argptr, message); + time_t t = time(0); + struct tm *now = localtime(&t); #ifdef ANDROID __android_log_vprint(ANDROID_LOG_WARN, "tgnet", message, argptr); #else - printf("warning: "); + printf("%d-%d %02d:%02d:%02d warning: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); vprintf(message, argptr); printf("\n"); fflush(stdout); #endif + if (logFile) { + fprintf(logFile, "%d-%d %02d:%02d:%02d warning: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); + vfprintf(logFile, message, argptr); + fprintf(logFile, "\n"); + fflush(logFile); + } + va_end(argptr); } void FileLog::d(const char *message, ...) { va_list argptr; va_start(argptr, message); + time_t t = time(0); + struct tm *now = localtime(&t); #ifdef ANDROID __android_log_vprint(ANDROID_LOG_DEBUG, "tgnet", message, argptr); #else - printf("debug: "); + printf("%d-%d %02d:%02d:%02d debug: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); vprintf(message, argptr); printf("\n"); fflush(stdout); #endif + if (logFile) { + fprintf(logFile, "%d-%d %02d:%02d:%02d debug: ", now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); + vfprintf(logFile, message, argptr); + fprintf(logFile, "\n"); + fflush(logFile); + } + va_end(argptr); } diff --git a/TMessagesProj/jni/tgnet/FileLog.h b/TMessagesProj/jni/tgnet/FileLog.h index 664593459..7cf8ce34c 100644 --- a/TMessagesProj/jni/tgnet/FileLog.h +++ b/TMessagesProj/jni/tgnet/FileLog.h @@ -13,6 +13,7 @@ class FileLog { public: + static void init(std::string path); static void e(const char *message, ...) __attribute__((format (printf, 1, 2))); static void w(const char *message, ...) __attribute__((format (printf, 1, 2))); static void d(const char *message, ...) __attribute__((format (printf, 1, 2))); diff --git a/TMessagesProj/libs/armeabi-v7a/libtmessages.12.so b/TMessagesProj/libs/armeabi-v7a/libtmessages.14.so similarity index 65% rename from TMessagesProj/libs/armeabi-v7a/libtmessages.12.so rename to TMessagesProj/libs/armeabi-v7a/libtmessages.14.so index 5eeeff5ce..1abf40798 100755 Binary files a/TMessagesProj/libs/armeabi-v7a/libtmessages.12.so and b/TMessagesProj/libs/armeabi-v7a/libtmessages.14.so differ diff --git a/TMessagesProj/libs/armeabi/libtmessages.12.so b/TMessagesProj/libs/armeabi/libtmessages.14.so similarity index 57% rename from TMessagesProj/libs/armeabi/libtmessages.12.so rename to TMessagesProj/libs/armeabi/libtmessages.14.so index d08b9a714..25ed33c58 100755 Binary files a/TMessagesProj/libs/armeabi/libtmessages.12.so and b/TMessagesProj/libs/armeabi/libtmessages.14.so differ diff --git a/TMessagesProj/libs/x86/libtmessages.12.so b/TMessagesProj/libs/x86/libtmessages.14.so similarity index 53% rename from TMessagesProj/libs/x86/libtmessages.12.so rename to TMessagesProj/libs/x86/libtmessages.14.so index 55b0bc44a..b4661cbc2 100755 Binary files a/TMessagesProj/libs/x86/libtmessages.12.so and b/TMessagesProj/libs/x86/libtmessages.14.so differ diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index bd5b61a8e..23231df30 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -12,8 +12,6 @@ - - @@ -26,7 +24,6 @@ - @@ -39,6 +36,7 @@ + + + + + + + + diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_0.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_0.jpg deleted file mode 100644 index 251747ff3..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_0.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_1.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_1.jpg deleted file mode 100644 index 21bc015ea..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_1.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_2.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_2.jpg deleted file mode 100644 index c1c6fd3b7..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_2.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_3.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_3.jpg deleted file mode 100644 index bb398488c..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_3.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_4.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_4.jpg deleted file mode 100644 index a74e170f9..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_4.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_0.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_0.jpg deleted file mode 100644 index 2fe760d04..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_0.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_1.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_1.jpg deleted file mode 100644 index 776bf5887..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_1.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_2.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_2.jpg deleted file mode 100644 index 43a7aa378..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_2.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_3.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_3.jpg deleted file mode 100644 index 95d146fea..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_3.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_4.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_4.jpg deleted file mode 100644 index 2be40c476..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji2.0x_a_4.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_0.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_0.jpg deleted file mode 100644 index bc1d03b45..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_0.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_1.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_1.jpg deleted file mode 100644 index 8288773c4..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_1.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_2.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_2.jpg deleted file mode 100644 index feea12096..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_2.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_3.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_3.jpg deleted file mode 100644 index 0e3bcede0..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_3.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_4.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_4.jpg deleted file mode 100644 index 1f74e8359..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_4.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_0.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_0.jpg deleted file mode 100644 index 5218c3ca4..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_0.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_1.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_1.jpg deleted file mode 100644 index e6192101a..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_1.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_2.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_2.jpg deleted file mode 100644 index 58476054b..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_2.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_3.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_3.jpg deleted file mode 100644 index 7e4ea184c..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_3.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_4.jpg b/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_4.jpg deleted file mode 100644 index 9bb3ea6cd..000000000 Binary files a/TMessagesProj/src/main/assets/emoji/v4_emoji3.0x_a_4.jpg and /dev/null differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_0.jpg new file mode 100644 index 000000000..fa0923f6c Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_1.jpg new file mode 100644 index 000000000..ed5a5d679 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_2.jpg new file mode 100644 index 000000000..9c835601e Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_3.jpg new file mode 100644 index 000000000..78637adc1 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_0_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_0.jpg new file mode 100644 index 000000000..da6c51df6 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_1.jpg new file mode 100644 index 000000000..454a6b2cf Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_2.jpg new file mode 100644 index 000000000..5e589bd67 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_3.jpg new file mode 100644 index 000000000..5f266035a Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_1_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_0.jpg new file mode 100644 index 000000000..47ac67242 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_1.jpg new file mode 100644 index 000000000..cd48e2672 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_2.jpg new file mode 100644 index 000000000..01ae27b0d Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_3.jpg new file mode 100644 index 000000000..1189e43bb Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_2_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_0.jpg new file mode 100644 index 000000000..de71960a9 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_1.jpg new file mode 100644 index 000000000..f9d3f664e Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_2.jpg new file mode 100644 index 000000000..142848445 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_3.jpg new file mode 100644 index 000000000..6de0df8e2 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_3_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_0.jpg new file mode 100644 index 000000000..4ed59bede Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_1.jpg new file mode 100644 index 000000000..7cd44246a Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_2.jpg new file mode 100644 index 000000000..0169deb51 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_3.jpg new file mode 100644 index 000000000..2a68beecc Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_4_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_0.jpg new file mode 100644 index 000000000..714e186a6 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_1.jpg new file mode 100644 index 000000000..c659dad05 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_2.jpg new file mode 100644 index 000000000..1e308bdbe Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_3.jpg new file mode 100644 index 000000000..ca39a7d1a Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_0_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_0.jpg new file mode 100644 index 000000000..29556f698 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_1.jpg new file mode 100644 index 000000000..015563d4c Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_2.jpg new file mode 100644 index 000000000..86306574f Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_3.jpg new file mode 100644 index 000000000..30b5a9278 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_1_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_0.jpg new file mode 100644 index 000000000..2ff8348b4 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_1.jpg new file mode 100644 index 000000000..1398cf95b Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_2.jpg new file mode 100644 index 000000000..d5843711b Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_3.jpg new file mode 100644 index 000000000..103f7693c Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_2_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_0.jpg new file mode 100644 index 000000000..0616f2960 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_1.jpg new file mode 100644 index 000000000..7a6d2e3f3 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_2.jpg new file mode 100644 index 000000000..bef04e680 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_3.jpg new file mode 100644 index 000000000..1ce93089f Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_3_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_0.jpg new file mode 100644 index 000000000..684965e70 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_1.jpg new file mode 100644 index 000000000..eef5ec534 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_2.jpg new file mode 100644 index 000000000..6d147857c Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_3.jpg new file mode 100644 index 000000000..d08f80b76 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji2.0x_a_4_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_0.jpg new file mode 100644 index 000000000..2048549a6 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_1.jpg new file mode 100644 index 000000000..f712e4bb7 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_2.jpg new file mode 100644 index 000000000..9225aa233 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_3.jpg new file mode 100644 index 000000000..76657809a Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_0_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_0.jpg new file mode 100644 index 000000000..ba950bff7 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_1.jpg new file mode 100644 index 000000000..d1266580a Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_2.jpg new file mode 100644 index 000000000..c394f8149 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_3.jpg new file mode 100644 index 000000000..fdfd98d78 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_1_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_0.jpg new file mode 100644 index 000000000..e19f186a0 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_1.jpg new file mode 100644 index 000000000..af66cb3c9 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_2.jpg new file mode 100644 index 000000000..597859740 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_3.jpg new file mode 100644 index 000000000..476c9ed3f Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_2_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_0.jpg new file mode 100644 index 000000000..29758492f Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_1.jpg new file mode 100644 index 000000000..c9613022d Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_2.jpg new file mode 100644 index 000000000..16d5bbfdd Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_3.jpg new file mode 100644 index 000000000..f6db0ff32 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_3_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_0.jpg new file mode 100644 index 000000000..59b6c198b Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_1.jpg new file mode 100644 index 000000000..d285314ab Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_2.jpg new file mode 100644 index 000000000..afd775135 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_3.jpg new file mode 100644 index 000000000..81468d010 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_4_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_0.jpg new file mode 100644 index 000000000..3e62257dd Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_1.jpg new file mode 100644 index 000000000..6eff54180 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_2.jpg new file mode 100644 index 000000000..ff866c722 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_3.jpg new file mode 100644 index 000000000..1006fa4c0 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_0_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_0.jpg new file mode 100644 index 000000000..74448ec6e Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_1.jpg new file mode 100644 index 000000000..e9a646019 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_2.jpg new file mode 100644 index 000000000..f9d6c78bf Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_3.jpg new file mode 100644 index 000000000..c27537c2f Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_1_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_0.jpg new file mode 100644 index 000000000..c54537579 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_1.jpg new file mode 100644 index 000000000..deaf755ab Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_2.jpg new file mode 100644 index 000000000..4f06199ed Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_3.jpg new file mode 100644 index 000000000..aa1261b58 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_2_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_0.jpg new file mode 100644 index 000000000..ec2ce25c6 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_1.jpg new file mode 100644 index 000000000..f73bfb8c8 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_2.jpg new file mode 100644 index 000000000..e81151b98 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_3.jpg new file mode 100644 index 000000000..cb60b76cb Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_3_3.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_0.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_0.jpg new file mode 100644 index 000000000..fb85fee49 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_0.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_1.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_1.jpg new file mode 100644 index 000000000..65f0a2bf1 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_1.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_2.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_2.jpg new file mode 100644 index 000000000..b5aa9c173 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_2.jpg differ diff --git a/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_3.jpg b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_3.jpg new file mode 100644 index 000000000..28d5ef5b9 Binary files /dev/null and b/TMessagesProj/src/main/assets/emoji/v7_emoji3.0x_a_4_3.jpg differ diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java index 87deca404..01275c5a0 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteCursor.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.SQLite; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java index 0aecf4b23..eb8bd6ada 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.SQLite; @@ -22,7 +22,7 @@ public class SQLiteDatabase { } public SQLiteDatabase(String fileName) throws SQLiteException { - sqliteHandle = opendb(fileName, ApplicationLoader.applicationContext.getFilesDir().getPath()); + sqliteHandle = opendb(fileName, ApplicationLoader.getFilesDirFixed().getPath()); isOpen = true; } diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteException.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteException.java index d27cfb6a0..2540c0947 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteException.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteException.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.SQLite; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteNoRowException.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteNoRowException.java index 042f0070f..944d21430 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteNoRowException.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteNoRowException.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.SQLite; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java index a2c871404..cd933701c 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.SQLite; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index acc95e7d3..1f467cea5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -16,6 +16,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Color; @@ -265,7 +266,7 @@ public class AndroidUtilities { 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) { @@ -304,38 +305,6 @@ public class AndroidUtilities { } catch (Exception 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) { @@ -799,12 +768,19 @@ public class AndroidUtilities { if (uri == null) { return; } - Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - mediaScanIntent.setData(uri); - ApplicationLoader.applicationContext.sendBroadcast(mediaScanIntent); + try { + Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + mediaScanIntent.setData(uri); + ApplicationLoader.applicationContext.sendBroadcast(mediaScanIntent); + } catch (Exception e) { + FileLog.e("tmessages", e); + } } private static File getAlbumDir() { + if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + return FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE); + } File storageDir = null; if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Telegram"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/AnimatorListenerAdapterProxy.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/AnimatorListenerAdapterProxy.java index eb7f73207..a136fbe58 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/AnimatorListenerAdapterProxy.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/AnimatorListenerAdapterProxy.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.AnimationCompat; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/AnimatorSetProxy.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/AnimatorSetProxy.java index 2dd7f21dd..ac3663877 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/AnimatorSetProxy.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/AnimatorSetProxy.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.AnimationCompat; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/ObjectAnimatorProxy.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/ObjectAnimatorProxy.java index 6ffffe341..392c25506 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/ObjectAnimatorProxy.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/ObjectAnimatorProxy.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.AnimationCompat; @@ -73,12 +73,13 @@ public class ObjectAnimatorProxy { } } - public void start() { + public ObjectAnimatorProxy start() { if (View10.NEED_PROXY) { ((ObjectAnimator10) objectAnimator).start(); } else { ((ObjectAnimator) objectAnimator).start(); } + return this; } public void setAutoCancel(boolean cancel) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/ViewProxy.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/ViewProxy.java index 492c136b1..e313acb8f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/ViewProxy.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimationCompat/ViewProxy.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.AnimationCompat; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AppStartReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AppStartReceiver.java index a601d66c0..153f68966 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AppStartReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AppStartReceiver.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 478c039bf..b5fbcbef9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -17,6 +17,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.graphics.drawable.ColorDrawable; @@ -92,7 +93,7 @@ public class ApplicationLoader extends Application { cachedWallpaper = applicationContext.getResources().getDrawable(R.drawable.background_hd); isCustomTheme = false; } else { - File toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper.jpg"); + File toFile = new File(getFilesDirFixed(), "wallpaper.jpg"); if (toFile.exists()) { cachedWallpaper = Drawable.createFromPath(toFile.getAbsolutePath()); isCustomTheme = true; @@ -151,7 +152,7 @@ public class ApplicationLoader extends Application { } try { - File file = new File(ApplicationLoader.applicationContext.getFilesDir(), "tgnet.dat"); + File file = new File(getFilesDirFixed(), "tgnet.dat"); RandomAccessFile fileOutputStream = new RandomAccessFile(file, "rws"); byte[] bytes = buffer.toByteArray(); fileOutputStream.writeInt(Integer.reverseBytes(bytes.length)); @@ -165,6 +166,24 @@ public class ApplicationLoader extends Application { } } + public static File getFilesDirFixed() { + for (int a = 0; a < 10; a++) { + File path = ApplicationLoader.applicationContext.getFilesDir(); + if (path != null) { + return path; + } + } + try { + ApplicationInfo info = applicationContext.getApplicationInfo(); + File path = new File(info.dataDir, "files"); + path.mkdirs(); + return path; + } catch (Exception e) { + FileLog.e("tmessages", e); + } + return new File("/data/data/org.telegram.messenger/files"); + } + public static void postInitApplication() { if (applicationInited) { return; @@ -201,7 +220,7 @@ public class ApplicationLoader extends Application { String langCode; String appVersion; String systemVersion; - String configPath = ApplicationLoader.applicationContext.getFilesDir().toString(); + String configPath = getFilesDirFixed().toString(); try { langCode = LocaleController.getLocaleString(LocaleController.getInstance().getSystemDefaultLocale()); @@ -229,7 +248,7 @@ public class ApplicationLoader extends Application { } MessagesController.getInstance(); - ConnectionsManager.getInstance().init(BuildVars.BUILD_VERSION, TLRPC.LAYER, BuildVars.APP_ID, deviceModel, systemVersion, appVersion, langCode, configPath, UserConfig.getClientUserId()); + ConnectionsManager.getInstance().init(BuildVars.BUILD_VERSION, TLRPC.LAYER, BuildVars.APP_ID, deviceModel, systemVersion, appVersion, langCode, configPath, FileLog.getNetworkLogPath(), UserConfig.getClientUserId()); if (UserConfig.getCurrentUser() != null) { MessagesController.getInstance().putUser(UserConfig.getCurrentUser(), true); ConnectionsManager.getInstance().applyCountryPortNumber(UserConfig.getCurrentUser().phone); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AuthenticatorService.java b/TMessagesProj/src/main/java/org/telegram/messenger/AuthenticatorService.java index e88d46ed2..60984c1b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AuthenticatorService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AuthenticatorService.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java index 9bf109e92..839eb3fee 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageHeardReceiver.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java index bc3324449..52d8d7051 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoMessageReplyReceiver.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Bitmaps.java b/TMessagesProj/src/main/java/org/telegram/messenger/Bitmaps.java new file mode 100644 index 000000000..c9ee2c4ef --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Bitmaps.java @@ -0,0 +1,257 @@ +/* + * This is the source code of Telegram for Android v. 3.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.messenger; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Build; + +public class Bitmaps { + + private static volatile Matrix sScaleMatrix; + + private static final ThreadLocal jpegData = new ThreadLocal() { + @Override + protected byte[] initialValue() { + return new byte[]{ + (byte) 0xff, (byte) 0xd8, (byte) 0xff, (byte) 0xdb, (byte) 0x00, (byte) 0x43, (byte) 0x00, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xc0, (byte) 0x00, (byte) 0x11, (byte) 0x08, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x22, (byte) 0x00, + (byte) 0x02, (byte) 0x11, (byte) 0x00, (byte) 0x03, (byte) 0x11, (byte) 0x00, (byte) 0xff, + (byte) 0xc4, (byte) 0x00, (byte) 0x1f, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x05, + (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, + (byte) 0x08, (byte) 0x09, (byte) 0x0a, (byte) 0x0b, (byte) 0xff, (byte) 0xc4, (byte) 0x00, + (byte) 0xb5, (byte) 0x10, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x03, (byte) 0x03, + (byte) 0x02, (byte) 0x04, (byte) 0x03, (byte) 0x05, (byte) 0x05, (byte) 0x04, (byte) 0x04, + (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x7d, (byte) 0x01, (byte) 0x02, (byte) 0x03, + (byte) 0x00, (byte) 0x04, (byte) 0x11, (byte) 0x05, (byte) 0x12, (byte) 0x21, (byte) 0x31, + (byte) 0x41, (byte) 0x06, (byte) 0x13, (byte) 0x51, (byte) 0x61, (byte) 0x07, (byte) 0x22, + (byte) 0x71, (byte) 0x14, (byte) 0x32, (byte) 0x81, (byte) 0x91, (byte) 0xa1, (byte) 0x08, + (byte) 0x23, (byte) 0x42, (byte) 0xb1, (byte) 0xc1, (byte) 0x15, (byte) 0x52, (byte) 0xd1, + (byte) 0xf0, (byte) 0x24, (byte) 0x33, (byte) 0x62, (byte) 0x72, (byte) 0x82, (byte) 0x09, + (byte) 0x0a, (byte) 0x16, (byte) 0x17, (byte) 0x18, (byte) 0x19, (byte) 0x1a, (byte) 0x25, + (byte) 0x26, (byte) 0x27, (byte) 0x28, (byte) 0x29, (byte) 0x2a, (byte) 0x34, (byte) 0x35, + (byte) 0x36, (byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3a, (byte) 0x43, (byte) 0x44, + (byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48, (byte) 0x49, (byte) 0x4a, (byte) 0x53, + (byte) 0x54, (byte) 0x55, (byte) 0x56, (byte) 0x57, (byte) 0x58, (byte) 0x59, (byte) 0x5a, + (byte) 0x63, (byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67, (byte) 0x68, (byte) 0x69, + (byte) 0x6a, (byte) 0x73, (byte) 0x74, (byte) 0x75, (byte) 0x76, (byte) 0x77, (byte) 0x78, + (byte) 0x79, (byte) 0x7a, (byte) 0x83, (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87, + (byte) 0x88, (byte) 0x89, (byte) 0x8a, (byte) 0x92, (byte) 0x93, (byte) 0x94, (byte) 0x95, + (byte) 0x96, (byte) 0x97, (byte) 0x98, (byte) 0x99, (byte) 0x9a, (byte) 0xa2, (byte) 0xa3, + (byte) 0xa4, (byte) 0xa5, (byte) 0xa6, (byte) 0xa7, (byte) 0xa8, (byte) 0xa9, (byte) 0xaa, + (byte) 0xb2, (byte) 0xb3, (byte) 0xb4, (byte) 0xb5, (byte) 0xb6, (byte) 0xb7, (byte) 0xb8, + (byte) 0xb9, (byte) 0xba, (byte) 0xc2, (byte) 0xc3, (byte) 0xc4, (byte) 0xc5, (byte) 0xc6, + (byte) 0xc7, (byte) 0xc8, (byte) 0xc9, (byte) 0xca, (byte) 0xd2, (byte) 0xd3, (byte) 0xd4, + (byte) 0xd5, (byte) 0xd6, (byte) 0xd7, (byte) 0xd8, (byte) 0xd9, (byte) 0xda, (byte) 0xe1, + (byte) 0xe2, (byte) 0xe3, (byte) 0xe4, (byte) 0xe5, (byte) 0xe6, (byte) 0xe7, (byte) 0xe8, + (byte) 0xe9, (byte) 0xea, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4, (byte) 0xf5, + (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9, (byte) 0xfa, (byte) 0xff, (byte) 0xc4, + (byte) 0x00, (byte) 0x1f, (byte) 0x01, (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x01, + (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, + (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, + (byte) 0x09, (byte) 0x0a, (byte) 0x0b, (byte) 0xff, (byte) 0xc4, (byte) 0x00, (byte) 0xb5, + (byte) 0x11, (byte) 0x00, (byte) 0x02, (byte) 0x01, (byte) 0x02, (byte) 0x04, (byte) 0x04, + (byte) 0x03, (byte) 0x04, (byte) 0x07, (byte) 0x05, (byte) 0x04, (byte) 0x04, (byte) 0x00, + (byte) 0x01, (byte) 0x02, (byte) 0x77, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, + (byte) 0x11, (byte) 0x04, (byte) 0x05, (byte) 0x21, (byte) 0x31, (byte) 0x06, (byte) 0x12, + (byte) 0x41, (byte) 0x51, (byte) 0x07, (byte) 0x61, (byte) 0x71, (byte) 0x13, (byte) 0x22, + (byte) 0x32, (byte) 0x81, (byte) 0x08, (byte) 0x14, (byte) 0x42, (byte) 0x91, (byte) 0xa1, + (byte) 0xb1, (byte) 0xc1, (byte) 0x09, (byte) 0x23, (byte) 0x33, (byte) 0x52, (byte) 0xf0, + (byte) 0x15, (byte) 0x62, (byte) 0x72, (byte) 0xd1, (byte) 0x0a, (byte) 0x16, (byte) 0x24, + (byte) 0x34, (byte) 0xe1, (byte) 0x25, (byte) 0xf1, (byte) 0x17, (byte) 0x18, (byte) 0x19, + (byte) 0x1a, (byte) 0x26, (byte) 0x27, (byte) 0x28, (byte) 0x29, (byte) 0x2a, (byte) 0x35, + (byte) 0x36, (byte) 0x37, (byte) 0x38, (byte) 0x39, (byte) 0x3a, (byte) 0x43, (byte) 0x44, + (byte) 0x45, (byte) 0x46, (byte) 0x47, (byte) 0x48, (byte) 0x49, (byte) 0x4a, (byte) 0x53, + (byte) 0x54, (byte) 0x55, (byte) 0x56, (byte) 0x57, (byte) 0x58, (byte) 0x59, (byte) 0x5a, + (byte) 0x63, (byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67, (byte) 0x68, (byte) 0x69, + (byte) 0x6a, (byte) 0x73, (byte) 0x74, (byte) 0x75, (byte) 0x76, (byte) 0x77, (byte) 0x78, + (byte) 0x79, (byte) 0x7a, (byte) 0x82, (byte) 0x83, (byte) 0x84, (byte) 0x85, (byte) 0x86, + (byte) 0x87, (byte) 0x88, (byte) 0x89, (byte) 0x8a, (byte) 0x92, (byte) 0x93, (byte) 0x94, + (byte) 0x95, (byte) 0x96, (byte) 0x97, (byte) 0x98, (byte) 0x99, (byte) 0x9a, (byte) 0xa2, + (byte) 0xa3, (byte) 0xa4, (byte) 0xa5, (byte) 0xa6, (byte) 0xa7, (byte) 0xa8, (byte) 0xa9, + (byte) 0xaa, (byte) 0xb2, (byte) 0xb3, (byte) 0xb4, (byte) 0xb5, (byte) 0xb6, (byte) 0xb7, + (byte) 0xb8, (byte) 0xb9, (byte) 0xba, (byte) 0xc2, (byte) 0xc3, (byte) 0xc4, (byte) 0xc5, + (byte) 0xc6, (byte) 0xc7, (byte) 0xc8, (byte) 0xc9, (byte) 0xca, (byte) 0xd2, (byte) 0xd3, + (byte) 0xd4, (byte) 0xd5, (byte) 0xd6, (byte) 0xd7, (byte) 0xd8, (byte) 0xd9, (byte) 0xda, + (byte) 0xe2, (byte) 0xe3, (byte) 0xe4, (byte) 0xe5, (byte) 0xe6, (byte) 0xe7, (byte) 0xe8, + (byte) 0xe9, (byte) 0xea, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4, (byte) 0xf5, (byte) 0xf6, + (byte) 0xf7, (byte) 0xf8, (byte) 0xf9, (byte) 0xfa, (byte) 0xff, (byte) 0xda, (byte) 0x00, + (byte) 0x0c, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x11, (byte) 0x03, + (byte) 0x11, (byte) 0x00, (byte) 0x3f, (byte) 0x00, (byte) 0x8e, (byte) 0x8a, (byte) 0x28, + (byte) 0xa0, (byte) 0x0f, (byte) 0xff, (byte) 0xd9 + }; + } + }; + + public static Bitmap createBitmap(int width, int height, Bitmap.Config config) { + Bitmap bitmap; + if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 21) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inDither = true; + options.inPreferredConfig = config; + options.inPurgeable = true; + options.inSampleSize = 1; + options.inMutable = true; + byte[] array = jpegData.get(); + array[76] = (byte) (height >> 8); + array[77] = (byte) (height & 0x00ff); + array[78] = (byte) (width >> 8); + array[79] = (byte) (width & 0x00ff); + bitmap = BitmapFactory.decodeByteArray(array, 0, array.length, options); + Utilities.pinBitmap(bitmap); + bitmap.setHasAlpha(true); + bitmap.eraseColor(0); + } else { + bitmap = Bitmap.createBitmap(width, height, config); + } + if (config == Bitmap.Config.ARGB_8888 || config == Bitmap.Config.ARGB_4444) { + bitmap.eraseColor(Color.TRANSPARENT); + } + return bitmap; + } + + private static void checkXYSign(int x, int y) { + if (x < 0) { + throw new IllegalArgumentException("x must be >= 0"); + } + if (y < 0) { + throw new IllegalArgumentException("y must be >= 0"); + } + } + + private static void checkWidthHeight(int width, int height) { + if (width <= 0) { + throw new IllegalArgumentException("width must be > 0"); + } + if (height <= 0) { + throw new IllegalArgumentException("height must be > 0"); + } + } + + public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) { + checkXYSign(x, y); + checkWidthHeight(width, height); + if (x + width > source.getWidth()) { + throw new IllegalArgumentException("x + width must be <= bitmap.width()"); + } + if (y + height > source.getHeight()) { + throw new IllegalArgumentException("y + height must be <= bitmap.height()"); + } + if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() && height == source.getHeight() && (m == null || m.isIdentity())) { + return source; + } + + int neww = width; + int newh = height; + Canvas canvas = new Canvas(); + Bitmap bitmap; + Paint paint; + + Rect srcR = new Rect(x, y, x + width, y + height); + RectF dstR = new RectF(0, 0, width, height); + + Bitmap.Config newConfig = Bitmap.Config.ARGB_8888; + final Bitmap.Config config = source.getConfig(); + if (config != null) { + switch (config) { + case RGB_565: + newConfig = Bitmap.Config.RGB_565; + break; + case ALPHA_8: + newConfig = Bitmap.Config.ALPHA_8; + break; + case ARGB_4444: + case ARGB_8888: + default: + newConfig = Bitmap.Config.ARGB_8888; + break; + } + } + + if (m == null || m.isIdentity()) { + bitmap = createBitmap(neww, newh, newConfig); + paint = null; + } else { + final boolean transformed = !m.rectStaysRect(); + RectF deviceR = new RectF(); + m.mapRect(deviceR, dstR); + neww = Math.round(deviceR.width()); + newh = Math.round(deviceR.height()); + bitmap = createBitmap(neww, newh, transformed ? Bitmap.Config.ARGB_8888 : newConfig); + canvas.translate(-deviceR.left, -deviceR.top); + canvas.concat(m); + paint = new Paint(); + paint.setFilterBitmap(filter); + if (transformed) { + paint.setAntiAlias(true); + } + } + bitmap.setDensity(source.getDensity()); + if (Build.VERSION.SDK_INT >= 12) { + bitmap.setHasAlpha(source.hasAlpha()); + } + if (Build.VERSION.SDK_INT >= 19) { + bitmap.setPremultiplied(source.isPremultiplied()); + } + canvas.setBitmap(bitmap); + canvas.drawBitmap(source, srcR, dstR, paint); + try { + canvas.setBitmap(null); + } catch (Exception e) { + //don't promt, this will crash on 2.x + } + return bitmap; + } + + public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) { + return createBitmap(source, x, y, width, height, null, false); + } + + public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) { + Matrix m; + synchronized (Bitmap.class) { + m = sScaleMatrix; + sScaleMatrix = null; + } + if (m == null) { + m = new Matrix(); + } + final int width = src.getWidth(); + final int height = src.getHeight(); + final float sx = dstWidth / (float) width; + final float sy = dstHeight / (float) height; + m.setScale(sx, sy); + Bitmap b = createBitmap(src, 0, 0, width, height, m, filter); + synchronized (Bitmap.class) { + if (sScaleMatrix == null) { + sScaleMatrix = m; + } + } + return b; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index e8da530bb..3aae5aa96 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -10,7 +10,7 @@ package org.telegram.messenger; public class BuildVars { public static boolean DEBUG_VERSION = false; - public static int BUILD_VERSION = 627; + public static int BUILD_VERSION = 654; 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 HOCKEY_APP_HASH = "your-hockeyapp-api-key-here"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java index 702d3ac53..415701473 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatObject.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -50,8 +50,8 @@ public class ChatObject { public static TLRPC.Chat getChatByDialog(long did) { int lower_id = (int) did; int high_id = (int) (did >> 32); - if (high_id == 0 && lower_id < 0) { - MessagesController.getInstance().getChat(-lower_id); + if (lower_id < 0) { + return MessagesController.getInstance().getChat(-lower_id); } return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java index c0ee19250..8ae160f81 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java @@ -3,7 +3,7 @@ * 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. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -16,8 +16,10 @@ import android.content.ContentProviderResult; import android.content.ContentResolver; import android.content.ContentValues; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.provider.BaseColumns; import android.provider.ContactsContract; import android.text.TextUtils; @@ -275,6 +277,9 @@ public class ContactsController { private boolean checkContactsInternal() { boolean reload = false; try { + if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { + return false; + } ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver(); Cursor pCur = null; try { @@ -329,6 +334,9 @@ public class ContactsController { private HashMap readContactsFromPhoneBook() { HashMap contactsMap = new HashMap<>(); try { + if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { + return contactsMap; + } ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver(); HashMap shortContacts = new HashMap<>(); @@ -1274,6 +1282,9 @@ public class ContactsController { private void performWriteContactsToPhoneBookInternal(ArrayList contactsArray) { try { + if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { + return; + } Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, currentAccount.name).appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, currentAccount.type).build(); Cursor c1 = ApplicationLoader.applicationContext.getContentResolver().query(rawContactUri, new String[]{BaseColumns._ID, ContactsContract.RawContacts.SYNC2}, null, null, null); HashMap bookContacts = new HashMap<>(); @@ -1475,6 +1486,9 @@ public class ContactsController { if (currentAccount == null || user == null || user.phone == null || user.phone.length() == 0) { return -1; } + if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { + return -1; + } long res = -1; synchronized (observerLock) { ignoreChanges = true; @@ -1533,11 +1547,14 @@ public class ContactsController { } private void deleteContactFromPhoneBook(int uid) { - ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver(); + if (Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { + return; + } synchronized (observerLock) { ignoreChanges = true; } try { + ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver(); Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, currentAccount.name).appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, currentAccount.type).build(); int value = contentResolver.delete(rawContactUri, ContactsContract.RawContacts.SYNC2 + " = " + uid, null); } catch (Exception e) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsSyncAdapterService.java b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsSyncAdapterService.java index d6d3ecd32..1dac54c94 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsSyncAdapterService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsSyncAdapterService.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java index 529cbdbc5..f1a1918e1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadObject.java index efb90ec94..9bfb579ce 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadObject.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java index b82b7cb46..bd4510593 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -18,6 +18,7 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.Spannable; @@ -29,168 +30,23 @@ import android.view.ViewGroup; import android.widget.TextView; public class Emoji { - private static HashMap rects = new HashMap<>(); + private static HashMap rects = new HashMap<>(); private static int drawImgSize; private static int bigImgSize; private static boolean inited = false; private static Paint placeholderPaint; - private static Bitmap emojiBmp[] = new Bitmap[5]; - private static boolean loadingEmoji[] = new boolean[5]; + private static final int splitCount = 4; + private static Bitmap emojiBmp[][] = new Bitmap[5][splitCount]; + private static boolean loadingEmoji[][] = new boolean[5][splitCount]; - private static final int[] cols = { - 13, 10, 15, 10, 14 + private static final int[][] cols = { + {11, 11, 11, 11}, + {6, 6, 6, 6}, + {9, 9, 9, 9}, + {9, 9, 9, 9}, + {8, 8, 8, 7} }; - private static final char[] emojiChars = { - 0x00A9, 0x00AE, 0x203C, 0x2049, 0x2122, 0x2139, 0x2194, 0x2195, 0x2196, 0x2197, - 0x2198, 0x2199, 0x21A9, 0x21AA, 0x231A, 0x231B, 0x23E9, 0x23EA, 0x23EB, 0x23EC, - 0x23F0, 0x23F3, 0x24C2, 0x25AA, 0x25AB, 0x25B6, 0x25C0, 0x25FB, 0x25FC, 0x25FD, - 0x25FE, 0x2600, 0x2601, 0x260E, 0x2611, 0x2614, 0x2615, 0x261D, 0x263A, 0x2648, - 0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, - 0x2653, 0x2660, 0x2663, 0x2665, 0x2666, 0x2668, 0x267B, 0x267F, 0x2693, 0x26A0, - 0x26A1, 0x26AA, 0x26AB, 0x26BD, 0x26BE, 0x26C4, 0x26C5, 0x26CE, 0x26D4, 0x26EA, - 0x26F2, 0x26F3, 0x26F5, 0x26FA, 0x26FD, 0x2702, 0x2705, 0x2708, 0x2709, 0x270A, - 0x270B, 0x270C, 0x270F, 0x2712, 0x2714, 0x2716, 0x2728, 0x2733, 0x2734, 0x2744, - 0x2747, 0x274C, 0x274E, 0x2753, 0x2754, 0x2755, 0x2757, 0x2764, 0x2795, 0x2796, - 0x2797, 0x27A1, 0x27B0, 0x27BF, 0x2934, 0x2935, 0x2B05, 0x2B06, 0x2B07, 0x2B1B, - 0x2B1C, 0x2B50, 0x2B55, 0x3030, 0x303D, 0x3297, 0x3299 - }; - - public static long[][] data = { - new long[]//189 - { - 0x00000000D83DDE04L, 0x00000000D83DDE03L, 0x00000000D83DDE00L, 0x00000000D83DDE0AL, 0x000000000000263AL, 0x00000000D83DDE09L, 0x00000000D83DDE0DL, - 0x00000000D83DDE18L, 0x00000000D83DDE1AL, 0x00000000D83DDE17L, 0x00000000D83DDE19L, 0x00000000D83DDE1CL, 0x00000000D83DDE1DL, 0x00000000D83DDE1BL, - 0x00000000D83DDE33L, 0x00000000D83DDE01L, 0x00000000D83DDE14L, 0x00000000D83DDE0CL, 0x00000000D83DDE12L, 0x00000000D83DDE1EL, 0x00000000D83DDE23L, - 0x00000000D83DDE22L, 0x00000000D83DDE02L, 0x00000000D83DDE2DL, 0x00000000D83DDE2AL, 0x00000000D83DDE25L, 0x00000000D83DDE30L, 0x00000000D83DDE05L, - 0x00000000D83DDE13L, 0x00000000D83DDE29L, 0x00000000D83DDE2BL, 0x00000000D83DDE28L, 0x00000000D83DDE31L, 0x00000000D83DDE20L, 0x00000000D83DDE21L, - 0x00000000D83DDE24L, 0x00000000D83DDE16L, 0x00000000D83DDE06L, 0x00000000D83DDE0BL, 0x00000000D83DDE37L, 0x00000000D83DDE0EL, 0x00000000D83DDE34L, - 0x00000000D83DDE35L, 0x00000000D83DDE32L, 0x00000000D83DDE1FL, 0x00000000D83DDE26L, 0x00000000D83DDE27L, 0x00000000D83DDE08L, 0x00000000D83DDC7FL, - 0x00000000D83DDE2EL, 0x00000000D83DDE2CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L, 0x00000000D83DDE2FL, 0x00000000D83DDE36L, 0x00000000D83DDE07L, - 0x00000000D83DDE0FL, 0x00000000D83DDE11L, 0x00000000D83DDC72L, 0x00000000D83DDC73L, 0x00000000D83DDC6EL, 0x00000000D83DDC77L, 0x00000000D83DDC82L, - 0x00000000D83DDC76L, 0x00000000D83DDC66L, 0x00000000D83DDC67L, 0x00000000D83DDC68L, 0x00000000D83DDC69L, 0x00000000D83DDC74L, 0x00000000D83DDC75L, - 0x00000000D83DDC71L, 0x00000000D83DDC7CL, 0x00000000D83DDC78L, 0x00000000D83DDE3AL, 0x00000000D83DDE38L, 0x00000000D83DDE3BL, 0x00000000D83DDE3DL, - 0x00000000D83DDE3CL, 0x00000000D83DDE40L, 0x00000000D83DDE3FL, 0x00000000D83DDE39L, 0x00000000D83DDE3EL, 0x00000000D83DDC79L, 0x00000000D83DDC7AL, - 0x00000000D83DDE48L, 0x00000000D83DDE49L, 0x00000000D83DDE4AL, 0x00000000D83DDC80L, 0x00000000D83DDC7DL, 0x00000000D83DDCA9L, 0x00000000D83DDD25L, - 0x0000000000002728L, 0x00000000D83CDF1FL, 0x00000000D83DDCABL, 0x00000000D83DDCA5L, 0x00000000D83DDCA2L, 0x00000000D83DDCA6L, 0x00000000D83DDCA7L, - 0x00000000D83DDCA4L, 0x00000000D83DDCA8L, 0x00000000D83DDC42L, 0x00000000D83DDC40L, 0x00000000D83DDC43L, 0x00000000D83DDC45L, 0x00000000D83DDC44L, - 0x00000000D83DDC4DL, 0x00000000D83DDC4EL, 0x00000000D83DDC4CL, 0x00000000D83DDC4AL, 0x000000000000270AL, 0x000000000000270CL, 0x00000000D83DDC4BL, - 0x000000000000270BL, 0x00000000D83DDC50L, 0x00000000D83DDC46L, 0x00000000D83DDC47L, 0x00000000D83DDC49L, 0x00000000D83DDC48L, 0x00000000D83DDE4CL, - 0x00000000D83DDE4FL, 0x000000000000261DL, 0x00000000D83DDC4FL, 0x00000000D83DDCAAL, 0x00000000D83DDEB6L, 0x00000000D83CDFC3L, 0x00000000D83DDC83L, - 0x00000000D83DDC6BL, 0x00000000D83DDC6AL, 0x00000000D83DDC6CL, 0x00000000D83DDC6DL, 0x00000000D83DDC8FL, 0x00000000D83DDC91L, 0x00000000D83DDC6FL, - 0x00000000D83DDE46L, 0x00000000D83DDE45L, 0x00000000D83DDC81L, 0x00000000D83DDE4BL, 0x00000000D83DDC86L, 0x00000000D83DDC87L, 0x00000000D83DDC85L, - 0x00000000D83DDC70L, 0x00000000D83DDE4EL, 0x00000000D83DDE4DL, 0x00000000D83DDE47L, 0x00000000D83CDFA9L, 0x00000000D83DDC51L, 0x00000000D83DDC52L, - 0x00000000D83DDC5FL, 0x00000000D83DDC5EL, 0x00000000D83DDC61L, 0x00000000D83DDC60L, 0x00000000D83DDC62L, 0x00000000D83DDC55L, 0x00000000D83DDC54L, - 0x00000000D83DDC5AL, 0x00000000D83DDC57L, 0x00000000D83CDFBDL, 0x00000000D83DDC56L, 0x00000000D83DDC58L, 0x00000000D83DDC59L, 0x00000000D83DDCBCL, - 0x00000000D83DDC5CL, 0x00000000D83DDC5DL, 0x00000000D83DDC5BL, 0x00000000D83DDC53L, 0x00000000D83CDF80L, 0x00000000D83CDF02L, 0x00000000D83DDC84L, - 0x00000000D83DDC9BL, 0x00000000D83DDC99L, 0x00000000D83DDC9CL, 0x00000000D83DDC9AL, 0x0000000000002764L, 0x00000000D83DDC94L, 0x00000000D83DDC97L, - 0x00000000D83DDC93L, 0x00000000D83DDC95L, 0x00000000D83DDC96L, 0x00000000D83DDC9EL, 0x00000000D83DDC98L, 0x00000000D83DDC8CL, 0x00000000D83DDC8BL, - 0x00000000D83DDC8DL, 0x00000000D83DDC8EL, 0x00000000D83DDC64L, 0x00000000D83DDC65L, 0x00000000D83DDCACL, 0x00000000D83DDC63L, 0x00000000D83DDCADL}, - new long[]//116 - { - 0x00000000D83DDC36L, 0x00000000D83DDC3AL, 0x00000000D83DDC31L, 0x00000000D83DDC2DL, 0x00000000D83DDC39L, 0x00000000D83DDC30L, 0x00000000D83DDC38L, 0x00000000D83DDC2FL, - 0x00000000D83DDC28L, 0x00000000D83DDC3BL, 0x00000000D83DDC37L, 0x00000000D83DDC3DL, 0x00000000D83DDC2EL, 0x00000000D83DDC17L, 0x00000000D83DDC35L, - 0x00000000D83DDC12L, 0x00000000D83DDC34L, 0x00000000D83DDC11L, 0x00000000D83DDC18L, 0x00000000D83DDC3CL, 0x00000000D83DDC27L, 0x00000000D83DDC26L, - 0x00000000D83DDC24L, 0x00000000D83DDC25L, 0x00000000D83DDC23L, 0x00000000D83DDC14L, 0x00000000D83DDC0DL, 0x00000000D83DDC22L, 0x00000000D83DDC1BL, - 0x00000000D83DDC1DL, 0x00000000D83DDC1CL, 0x00000000D83DDC1EL, 0x00000000D83DDC0CL, 0x00000000D83DDC19L, 0x00000000D83DDC1AL, 0x00000000D83DDC20L, - 0x00000000D83DDC1FL, 0x00000000D83DDC2CL, 0x00000000D83DDC33L, 0x00000000D83DDC0BL, 0x00000000D83DDC04L, 0x00000000D83DDC0FL, 0x00000000D83DDC00L, - 0x00000000D83DDC03L, 0x00000000D83DDC05L, 0x00000000D83DDC07L, 0x00000000D83DDC09L, 0x00000000D83DDC0EL, 0x00000000D83DDC10L, 0x00000000D83DDC13L, - 0x00000000D83DDC15L, 0x00000000D83DDC16L, 0x00000000D83DDC01L, 0x00000000D83DDC02L, 0x00000000D83DDC32L, 0x00000000D83DDC21L, 0x00000000D83DDC0AL, - 0x00000000D83DDC2BL, 0x00000000D83DDC2AL, 0x00000000D83DDC06L, 0x00000000D83DDC08L, 0x00000000D83DDC29L, 0x00000000D83DDC3EL, 0x00000000D83DDC90L, - 0x00000000D83CDF38L, 0x00000000D83CDF37L, 0x00000000D83CDF40L, 0x00000000D83CDF39L, 0x00000000D83CDF3BL, 0x00000000D83CDF3AL, 0x00000000D83CDF41L, - 0x00000000D83CDF43L, 0x00000000D83CDF42L, 0x00000000D83CDF3FL, 0x00000000D83CDF3EL, 0x00000000D83CDF44L, 0x00000000D83CDF35L, 0x00000000D83CDF34L, - 0x00000000D83CDF32L, 0x00000000D83CDF33L, 0x00000000D83CDF30L, 0x00000000D83CDF31L, 0x00000000D83CDF3CL, 0x00000000D83CDF10L, 0x00000000D83CDF1EL, - 0x00000000D83CDF1DL, 0x00000000D83CDF1AL, 0x00000000D83CDF11L, 0x00000000D83CDF12L, 0x00000000D83CDF13L, 0x00000000D83CDF14L, 0x00000000D83CDF15L, - 0x00000000D83CDF16L, 0x00000000D83CDF17L, 0x00000000D83CDF18L, 0x00000000D83CDF1CL, 0x00000000D83CDF1BL, 0x00000000D83CDF19L, 0x00000000D83CDF0DL, - 0x00000000D83CDF0EL, 0x00000000D83CDF0FL, 0x00000000D83CDF0BL, 0x00000000D83CDF0CL, 0x00000000D83CDF20L, 0x0000000000002B50L, 0x0000000000002600L, - 0x00000000000026C5L, 0x0000000000002601L, 0x00000000000026A1L, 0x0000000000002614L, 0x0000000000002744L, 0x00000000000026C4L, 0x00000000D83CDF00L, - 0x00000000D83CDF01L, 0x00000000D83CDF08L, 0x00000000D83CDF0AL}, - new long[]//230 - { - 0x00000000D83CDF8DL, 0x00000000D83DDC9DL, 0x00000000D83CDF8EL, 0x00000000D83CDF92L, 0x00000000D83CDF93L, 0x00000000D83CDF8FL, 0x00000000D83CDF86L, 0x00000000D83CDF87L, - 0x00000000D83CDF90L, 0x00000000D83CDF91L, 0x00000000D83CDF83L, 0x00000000D83DDC7BL, 0x00000000D83CDF85L, 0x00000000D83CDF84L, 0x00000000D83CDF81L, - 0x00000000D83CDF8BL, 0x00000000D83CDF89L, 0x00000000D83CDF8AL, 0x00000000D83CDF88L, 0x00000000D83CDF8CL, 0x00000000D83DDD2EL, 0x00000000D83CDFA5L, - 0x00000000D83DDCF7L, 0x00000000D83DDCF9L, 0x00000000D83DDCFCL, 0x00000000D83DDCBFL, 0x00000000D83DDCC0L, 0x00000000D83DDCBDL, 0x00000000D83DDCBEL, - 0x00000000D83DDCBBL, 0x00000000D83DDCF1L, 0x000000000000260EL, 0x00000000D83DDCDEL, 0x00000000D83DDCDFL, 0x00000000D83DDCE0L, 0x00000000D83DDCE1L, - 0x00000000D83DDCFAL, 0x00000000D83DDCFBL, 0x00000000D83DDD0AL, 0x00000000D83DDD09L, 0x00000000D83DDD08L, 0x00000000D83DDD07L, 0x00000000D83DDD14L, - 0x00000000D83DDD15L, 0x00000000D83DDCE2L, 0x00000000D83DDCE3L, 0x00000000000023F3L, 0x000000000000231BL, 0x00000000000023F0L, 0x000000000000231AL, - 0x00000000D83DDD13L, 0x00000000D83DDD12L, 0x00000000D83DDD0FL, 0x00000000D83DDD10L, 0x00000000D83DDD11L, 0x00000000D83DDD0EL, 0x00000000D83DDCA1L, - 0x00000000D83DDD26L, 0x00000000D83DDD06L, 0x00000000D83DDD05L, 0x00000000D83DDD0CL, 0x00000000D83DDD0BL, 0x00000000D83DDD0DL, 0x00000000D83DDEC1L, 0x00000000D83DDEC0L, - 0x00000000D83DDEBFL, 0x00000000D83DDEBDL, 0x00000000D83DDD27L, 0x00000000D83DDD29L, 0x00000000D83DDD28L, 0x00000000D83DDEAAL, 0x00000000D83DDEACL, - 0x00000000D83DDCA3L, 0x00000000D83DDD2BL, 0x00000000D83DDD2AL, 0x00000000D83DDC8AL, 0x00000000D83DDC89L, 0x00000000D83DDCB0L, 0x00000000D83DDCB4L, - 0x00000000D83DDCB5L, 0x00000000D83DDCB7L, 0x00000000D83DDCB6L, 0x00000000D83DDCB3L, 0x00000000D83DDCB8L, 0x00000000D83DDCF2L, 0x00000000D83DDCE7L, - 0x00000000D83DDCE5L, 0x00000000D83DDCE4L, 0x0000000000002709L, 0x00000000D83DDCE9L, 0x00000000D83DDCE8L, 0x00000000D83DDCEFL, 0x00000000D83DDCEBL, - 0x00000000D83DDCEAL, 0x00000000D83DDCECL, 0x00000000D83DDCEDL, 0x00000000D83DDCEEL, 0x00000000D83DDCE6L, 0x00000000D83DDCDDL, 0x00000000D83DDCC4L, - 0x00000000D83DDCC3L, 0x00000000D83DDCD1L, 0x00000000D83DDCCAL, 0x00000000D83DDCC8L, 0x00000000D83DDCC9L, 0x00000000D83DDCDCL, 0x00000000D83DDCCBL, - 0x00000000D83DDCC5L, 0x00000000D83DDCC6L, 0x00000000D83DDCC7L, 0x00000000D83DDCC1L, 0x00000000D83DDCC2L, 0x0000000000002702L, 0x00000000D83DDCCCL, - 0x00000000D83DDCCEL, 0x0000000000002712L, 0x000000000000270FL, 0x00000000D83DDCCFL, 0x00000000D83DDCD0L, 0x00000000D83DDCD5L, 0x00000000D83DDCD7L, - 0x00000000D83DDCD8L, 0x00000000D83DDCD9L, 0x00000000D83DDCD3L, 0x00000000D83DDCD4L, 0x00000000D83DDCD2L, 0x00000000D83DDCDAL, 0x00000000D83DDCD6L, - 0x00000000D83DDD16L, 0x00000000D83DDCDBL, 0x00000000D83DDD2CL, 0x00000000D83DDD2DL, 0x00000000D83DDCF0L, 0x00000000D83CDFA8L, 0x00000000D83CDFACL, - 0x00000000D83CDFA4L, 0x00000000D83CDFA7L, 0x00000000D83CDFBCL, 0x00000000D83CDFB5L, 0x00000000D83CDFB6L, 0x00000000D83CDFB9L, 0x00000000D83CDFBBL, - 0x00000000D83CDFBAL, 0x00000000D83CDFB7L, 0x00000000D83CDFB8L, 0x00000000D83DDC7EL, 0x00000000D83CDFAEL, 0x00000000D83CDCCFL, 0x00000000D83CDFB4L, - 0x00000000D83CDC04L, 0x00000000D83CDFB2L, 0x00000000D83CDFAFL, 0x00000000D83CDFC8L, 0x00000000D83CDFC0L, 0x00000000000026BDL, 0x00000000000026BEL, - 0x00000000D83CDFBEL, 0x00000000D83CDFB1L, 0x00000000D83CDFC9L, 0x00000000D83CDFB3L, 0x00000000000026F3L, 0x00000000D83DDEB5L, 0x00000000D83DDEB4L, - 0x00000000D83CDFC1L, 0x00000000D83CDFC7L, 0x00000000D83CDFC6L, 0x00000000D83CDFBFL, 0x00000000D83CDFC2L, 0x00000000D83CDFCAL, 0x00000000D83CDFC4L, - 0x00000000D83CDFA3L, 0x0000000000002615L, 0x00000000D83CDF75L, 0x00000000D83CDF76L, 0x00000000D83CDF7CL, 0x00000000D83CDF7AL, 0x00000000D83CDF7BL, - 0x00000000D83CDF78L, 0x00000000D83CDF79L, 0x00000000D83CDF77L, 0x00000000D83CDF74L, 0x00000000D83CDF55L, 0x00000000D83CDF54L, 0x00000000D83CDF5FL, - 0x00000000D83CDF57L, 0x00000000D83CDF56L, 0x00000000D83CDF5DL, 0x00000000D83CDF5BL, 0x00000000D83CDF64L, 0x00000000D83CDF71L, 0x00000000D83CDF63L, - 0x00000000D83CDF65L, 0x00000000D83CDF59L, 0x00000000D83CDF58L, 0x00000000D83CDF5AL, 0x00000000D83CDF5CL, 0x00000000D83CDF72L, 0x00000000D83CDF62L, - 0x00000000D83CDF61L, 0x00000000D83CDF73L, 0x00000000D83CDF5EL, 0x00000000D83CDF69L, 0x00000000D83CDF6EL, 0x00000000D83CDF66L, 0x00000000D83CDF68L, - 0x00000000D83CDF67L, 0x00000000D83CDF82L, 0x00000000D83CDF70L, 0x00000000D83CDF6AL, 0x00000000D83CDF6BL, 0x00000000D83CDF6CL, 0x00000000D83CDF6DL, - 0x00000000D83CDF6FL, 0x00000000D83CDF4EL, 0x00000000D83CDF4FL, 0x00000000D83CDF4AL, 0x00000000D83CDF4BL, 0x00000000D83CDF52L, 0x00000000D83CDF47L, - 0x00000000D83CDF49L, 0x00000000D83CDF53L, 0x00000000D83CDF51L, 0x00000000D83CDF48L, 0x00000000D83CDF4CL, 0x00000000D83CDF50L, 0x00000000D83CDF4DL, - 0x00000000D83CDF60L, 0x00000000D83CDF46L, 0x00000000D83CDF45L, 0x00000000D83CDF3DL}, - new long[]//101 - { - 0x00000000D83CDFE0L, 0x00000000D83CDFE1L, 0x00000000D83CDFEBL, 0x00000000D83CDFE2L, 0x00000000D83CDFE3L, 0x00000000D83CDFE5L, 0x00000000D83CDFE6L, 0x00000000D83CDFEAL, - 0x00000000D83CDFE9L, 0x00000000D83CDFE8L, 0x00000000D83DDC92L, 0x00000000000026EAL, 0x00000000D83CDFECL, 0x00000000D83CDFE4L, 0x00000000D83CDF07L, - 0x00000000D83CDF06L, 0x00000000D83CDFEFL, 0x00000000D83CDFF0L, 0x00000000000026FAL, 0x00000000D83CDFEDL, 0x00000000D83DDDFCL, 0x00000000D83DDDFEL, - 0x00000000D83DDDFBL, 0x00000000D83CDF04L, 0x00000000D83CDF05L, 0x00000000D83CDF03L, 0x00000000D83DDDFDL, 0x00000000D83CDF09L, 0x00000000D83CDFA0L, - 0x00000000D83CDFA1L, 0x00000000000026F2L, 0x00000000D83CDFA2L, 0x00000000D83DDEA2L, 0x00000000000026F5L, 0x00000000D83DDEA4L, 0x00000000D83DDEA3L, - 0x0000000000002693L, 0x00000000D83DDE80L, 0x0000000000002708L, 0x00000000D83DDCBAL, 0x00000000D83DDE81L, 0x00000000D83DDE82L, 0x00000000D83DDE8AL, - 0x00000000D83DDE89L, 0x00000000D83DDE9EL, 0x00000000D83DDE86L, 0x00000000D83DDE84L, 0x00000000D83DDE85L, 0x00000000D83DDE88L, 0x00000000D83DDE87L, - 0x00000000D83DDE9DL, 0x00000000D83DDE8BL, 0x00000000D83DDE83L, 0x00000000D83DDE8EL, 0x00000000D83DDE8CL, 0x00000000D83DDE8DL, 0x00000000D83DDE99L, - 0x00000000D83DDE98L, 0x00000000D83DDE97L, 0x00000000D83DDE95L, 0x00000000D83DDE96L, 0x00000000D83DDE9BL, 0x00000000D83DDE9AL, 0x00000000D83DDEA8L, - 0x00000000D83DDE93L, 0x00000000D83DDE94L, 0x00000000D83DDE92L, 0x00000000D83DDE91L, 0x00000000D83DDE90L, 0x00000000D83DDEB2L, 0x00000000D83DDEA1L, - 0x00000000D83DDE9FL, 0x00000000D83DDEA0L, 0x00000000D83DDE9CL, 0x00000000D83DDC88L, 0x00000000D83DDE8FL, 0x00000000D83CDFABL, 0x00000000D83DDEA6L, - 0x00000000D83DDEA5L, 0x00000000000026A0L, 0x00000000D83DDEA7L, 0x00000000D83DDD30L, 0x00000000000026FDL, 0x00000000D83CDFEEL, 0x00000000D83CDFB0L, - 0x0000000000002668L, 0x00000000D83DDDFFL, 0x00000000D83CDFAAL, 0x00000000D83CDFADL, 0x00000000D83DDCCDL, 0x00000000D83DDEA9L, 0xD83CDDEFD83CDDF5L, - 0xD83CDDF0D83CDDF7L, 0xD83CDDE9D83CDDEAL, 0xD83CDDE8D83CDDF3L, 0xD83CDDFAD83CDDF8L, 0xD83CDDEBD83CDDF7L, 0xD83CDDEAD83CDDF8L, 0xD83CDDEED83CDDF9L, - 0xD83CDDF7D83CDDFAL, 0xD83CDDECD83CDDE7L}, - new long[]//209 - { - 0x00000000003120E3L, 0x00000000003220E3L, 0x00000000003320E3L, 0x00000000003420E3L, 0x00000000003520E3L, 0x00000000003620E3L, 0x00000000003720E3L, - 0x00000000003820E3L, 0x00000000003920E3L, 0x00000000003020E3L, 0x00000000D83DDD1FL, 0x00000000D83DDD22L, 0x00000000002320E3L, 0x00000000D83DDD23L, - 0x0000000000002B06L, 0x0000000000002B07L, 0x0000000000002B05L, 0x00000000000027A1L, 0x00000000D83DDD20L, 0x00000000D83DDD21L, 0x00000000D83DDD24L, - 0x0000000000002197L, 0x0000000000002196L, 0x0000000000002198L, 0x0000000000002199L, 0x0000000000002194L, 0x0000000000002195L, 0x00000000D83DDD04L, - 0x00000000000025C0L, 0x00000000000025B6L, 0x00000000D83DDD3CL, 0x00000000D83DDD3DL, 0x00000000000021A9L, 0x00000000000021AAL, 0x0000000000002139L, - 0x00000000000023EAL, 0x00000000000023E9L, 0x00000000000023EBL, 0x00000000000023ECL, 0x0000000000002935L, 0x0000000000002934L, 0x00000000D83CDD97L, - 0x00000000D83DDD00L, 0x00000000D83DDD01L, 0x00000000D83DDD02L, 0x00000000D83CDD95L, 0x00000000D83CDD99L, 0x00000000D83CDD92L, 0x00000000D83CDD93L, - 0x00000000D83CDD96L, 0x00000000D83DDCF6L, 0x00000000D83CDFA6L, 0x00000000D83CDE01L, 0x00000000D83CDE2FL, 0x00000000D83CDE33L, 0x00000000D83CDE35L, - 0x00000000D83CDE32L, 0x00000000D83CDE34L, 0x00000000D83CDE50L, 0x00000000D83CDE39L, 0x00000000D83CDE3AL, 0x00000000D83CDE36L, 0x00000000D83CDE1AL, - 0x00000000D83DDEBBL, 0x00000000D83DDEB9L, 0x00000000D83DDEBAL, 0x00000000D83DDEBCL, 0x00000000D83DDEBEL, 0x00000000D83DDEB0L, 0x00000000D83DDEAEL, - 0x00000000D83CDD7FL, 0x000000000000267FL, 0x00000000D83DDEADL, 0x00000000D83CDE37L, 0x00000000D83CDE38L, 0x00000000D83CDE02L, 0x00000000000024C2L, - 0x00000000D83DDEC2L, 0x00000000D83DDEC4L, 0x00000000D83DDEC5L, 0x00000000D83DDEC3L, 0x00000000D83CDE51L, 0x0000000000003299L, 0x0000000000003297L, - 0x00000000D83CDD91L, 0x00000000D83CDD98L, 0x00000000D83CDD94L, 0x00000000D83DDEABL, - 0x00000000D83DDD1EL, 0x00000000D83DDCF5L, 0x00000000D83DDEAFL, 0x00000000D83DDEB1L, 0x00000000D83DDEB3L, 0x00000000D83DDEB7L, 0x00000000D83DDEB8L, - 0x00000000000026D4L, 0x0000000000002733L, 0x0000000000002747L, 0x000000000000274EL, 0x0000000000002705L, 0x0000000000002734L, 0x00000000D83DDC9FL, - 0x00000000D83CDD9AL, 0x00000000D83DDCF3L, 0x00000000D83DDCF4L, 0x00000000D83CDD70L, 0x00000000D83CDD71L, 0x00000000D83CDD8EL, 0x00000000D83CDD7EL, - 0x00000000D83DDCA0L, 0x00000000000027BFL, 0x000000000000267BL, 0x0000000000002648L, 0x0000000000002649L, 0x000000000000264AL, 0x000000000000264BL, - 0x000000000000264CL, 0x000000000000264DL, 0x000000000000264EL, 0x000000000000264FL, 0x0000000000002650L, 0x0000000000002651L, 0x0000000000002652L, - 0x0000000000002653L, 0x00000000000026CEL, 0x00000000D83DDD2FL, 0x00000000D83CDFE7L, 0x00000000D83DDCB9L, 0x00000000D83DDCB2L, 0x00000000D83DDCB1L, - 0x00000000000000A9L, 0x00000000000000AEL, 0x0000000000002122L, 0x000000000000303DL, 0x0000000000003030L, 0x00000000D83DDD1DL, 0x00000000D83DDD1AL, - 0x00000000D83DDD19L, 0x00000000D83DDD1BL, 0x00000000D83DDD1CL, 0x000000000000274CL, 0x0000000000002B55L, 0x0000000000002757L, 0x000000000000203CL, - 0x0000000000002049L, 0x0000000000002753L, - 0x0000000000002755L, 0x0000000000002754L, 0x00000000D83DDD03L, 0x00000000D83DDD5BL, 0x00000000D83DDD67L, 0x00000000D83DDD50L, 0x00000000D83DDD5CL, - 0x00000000D83DDD51L, 0x00000000D83DDD5DL, 0x00000000D83DDD52L, 0x00000000D83DDD5EL, 0x00000000D83DDD53L, 0x00000000D83DDD5FL, 0x00000000D83DDD54L, - 0x00000000D83DDD60L, 0x00000000D83DDD55L, 0x00000000D83DDD56L, 0x00000000D83DDD57L, 0x00000000D83DDD58L, 0x00000000D83DDD59L, 0x00000000D83DDD5AL, - 0x00000000D83DDD61L, 0x00000000D83DDD62L, 0x00000000D83DDD63L, 0x00000000D83DDD64L, 0x00000000D83DDD65L, 0x00000000D83DDD66L, 0x0000000000002716L, - 0x0000000000002795L, 0x0000000000002796L, 0x0000000000002797L, 0x0000000000002660L, 0x0000000000002665L, 0x0000000000002663L, 0x0000000000002666L, - 0x00000000D83DDCAEL, 0x00000000D83DDCAFL, 0x0000000000002714L, 0x0000000000002611L, 0x00000000D83DDD18L, 0x00000000D83DDD17L, 0x00000000000027B0L, - 0x00000000D83DDD31L, 0x00000000D83DDD32L, 0x00000000D83DDD33L, 0x00000000000025FCL, 0x00000000000025FBL, 0x00000000000025FEL, 0x00000000000025FDL, - 0x00000000000025AAL, 0x00000000000025ABL, 0x00000000D83DDD3AL, 0x0000000000002B1CL, 0x0000000000002B1BL, 0x00000000000026ABL, 0x00000000000026AAL, - 0x00000000D83DDD34L, 0x00000000D83DDD35L, 0x00000000D83DDD3BL, 0x00000000D83DDD36L, 0x00000000D83DDD37L, 0x00000000D83DDD38L, 0x00000000D83DDD39L}}; - static { int emojiFullSize; if (AndroidUtilities.density <= 1.0f) { @@ -200,26 +56,26 @@ public class Emoji { } else if (AndroidUtilities.density <= 2.0f) { emojiFullSize = 64; } else { - emojiFullSize = 96; + emojiFullSize = 64; } drawImgSize = AndroidUtilities.dp(20); - if (AndroidUtilities.isTablet()) { - bigImgSize = AndroidUtilities.dp(40); - } else { - bigImgSize = AndroidUtilities.dp(32); - } + bigImgSize = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 40 : 32); - for (int j = 0; j < data.length; j++) { - for (int i = 0; i < data[j].length; i++) { - Rect rect = new Rect((i % cols[j]) * emojiFullSize, (i / cols[j]) * emojiFullSize, (i % cols[j] + 1) * emojiFullSize, (i / cols[j] + 1) * emojiFullSize); - rects.put(data[j][i], new DrawableInfo(rect, (byte) j)); + for (int j = 0; j < EmojiData.data.length; j++) { + int count2 = (int) Math.ceil(EmojiData.data[j].length / (float) splitCount); + int position; + for (int i = 0; i < EmojiData.data[j].length; i++) { + int page = i / count2; + position = i - page * count2; + Rect rect = new Rect((position % cols[j][page]) * emojiFullSize, (position / cols[j][page]) * emojiFullSize, (position % cols[j][page] + 1) * emojiFullSize, (position / cols[j][page] + 1) * emojiFullSize); + rects.put(EmojiData.data[j][i], new DrawableInfo(rect, (byte) j, (byte) page)); } } placeholderPaint = new Paint(); placeholderPaint.setColor(0x00000000); } - private static void loadEmoji(final int page) { + private static void loadEmoji(final int page, final int page2) { try { float scale; int imageResize = 1; @@ -232,28 +88,31 @@ public class Emoji { } else if (AndroidUtilities.density <= 2.0f) { scale = 2.0f; } else { - scale = 3.0f; + scale = 2.0f; } String 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(); + for (int a = 4; a < 6; a++) { + imageName = String.format(Locale.US, "v%d_emoji%.01fx_%d.jpg", a, scale, page); + imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); + if (imageFile.exists()) { + imageFile.delete(); + } + imageName = String.format(Locale.US, "v%d_emoji%.01fx_a_%d.jpg", a, 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); + + imageName = String.format(Locale.US, "v7_emoji%.01fx_%d_%d.jpg", scale, page, page2); imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); if (!imageFile.exists()) { InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + imageName); @@ -272,7 +131,7 @@ public class Emoji { final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Utilities.loadBitmap(imageFile.getAbsolutePath(), bitmap, imageResize, width, height, stride); - imageName = String.format(Locale.US, "v4_emoji%.01fx_a_%d.jpg", scale, page); + imageName = String.format(Locale.US, "v7_emoji%.01fx_a_%d_%d.jpg", scale, page, page2); imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); if (!imageFile.exists()) { InputStream is = ApplicationLoader.applicationContext.getAssets().open("emoji/" + imageName); @@ -285,7 +144,7 @@ public class Emoji { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - emojiBmp[page] = bitmap; + emojiBmp[page][page2] = bitmap; NotificationCenter.getInstance().postNotificationName(NotificationCenter.emojiDidLoaded); } }); @@ -294,19 +153,6 @@ public class Emoji { } } - private static void loadEmojiAsync(final int page) { - if (loadingEmoji[page]) { - return; - } - loadingEmoji[page] = true; - new Thread(new Runnable() { - public void run() { - loadEmoji(page); - loadingEmoji[page] = false; - } - }).start(); - } - public static void invalidateAll(View view) { if (view instanceof ViewGroup) { ViewGroup g = (ViewGroup) view; @@ -318,10 +164,41 @@ public class Emoji { } } - public static EmojiDrawable getEmojiDrawable(long code) { + public static String fixEmoji(String emoji) { + char ch; + int lenght = emoji.length(); + for (int a = 0; a < lenght; a++) { + ch = emoji.charAt(a); + if (ch >= 0xD83C && ch <= 0xD83E) { + if (ch == 0xD83C && a < lenght - 1) { + ch = emoji.charAt(a + 1); + if (ch == 0xDE2F || ch == 0xDC04 || ch == 0xDE1A || ch == 0xDD7F) { + emoji = emoji.substring(0, a + 2) + "\uFE0F" + emoji.substring(a + 2); + lenght++; + a += 2; + } else { + a++; + } + } else { + a++; + } + } else if (ch == 0x20E3) { + return emoji; + } else if (ch >= 0x203C && ch <= 0x3299) { + if (EmojiData.emojiToFE0FMap.containsKey(ch)) { + emoji = emoji.substring(0, a + 1) + "\uFE0F" + emoji.substring(a + 1); + lenght++; + a++; + } + } + } + return emoji; + } + + public static EmojiDrawable getEmojiDrawable(CharSequence code) { DrawableInfo info = rects.get(code); if (info == null) { - FileLog.e("tmessages", "No emoji drawable for code " + String.format("%016X", code)); + FileLog.e("tmessages", "No drawable for emoji " + code); return null; } EmojiDrawable ed = new EmojiDrawable(info); @@ -329,7 +206,7 @@ public class Emoji { return ed; } - public static Drawable getEmojiBigDrawable(long code) { + public static Drawable getEmojiBigDrawable(String code) { EmojiDrawable ed = getEmojiDrawable(code); if (ed == null) { return null; @@ -342,7 +219,8 @@ public class Emoji { public static class EmojiDrawable extends Drawable { private DrawableInfo info; private boolean fullSize = false; - private static Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); + private static Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); + private static Rect rect = new Rect(); public EmojiDrawable(DrawableInfo i) { info = i; @@ -353,22 +231,33 @@ public class Emoji { } public Rect getDrawRect() { - Rect b = copyBounds(); - int cX = b.centerX(), cY = b.centerY(); - b.left = cX - (fullSize ? bigImgSize : drawImgSize) / 2; - b.right = cX + (fullSize ? bigImgSize : drawImgSize) / 2; - b.top = cY - (fullSize ? bigImgSize : drawImgSize) / 2; - b.bottom = cY + (fullSize ? bigImgSize : drawImgSize) / 2; - return b; + Rect original = getBounds(); + int cX = original.centerX(), cY = original.centerY(); + rect.left = cX - (fullSize ? bigImgSize : drawImgSize) / 2; + rect.right = cX + (fullSize ? bigImgSize : drawImgSize) / 2; + rect.top = cY - (fullSize ? bigImgSize : drawImgSize) / 2; + rect.bottom = cY + (fullSize ? bigImgSize : drawImgSize) / 2; + return rect; } @Override public void draw(Canvas canvas) { - if (emojiBmp[info.page] == null) { - loadEmojiAsync(info.page); + if (emojiBmp[info.page][info.page2] == null) { + if (loadingEmoji[info.page][info.page2]) { + return; + } + loadingEmoji[info.page][info.page2] = true; + Utilities.globalQueue.postRunnable(new Runnable() { + @Override + public void run() { + loadEmoji(info.page, info.page2); + loadingEmoji[info.page][info.page2] = false; + } + }); canvas.drawRect(getBounds(), placeholderPaint); return; } + Rect b; if (fullSize) { b = getDrawRect(); @@ -377,13 +266,16 @@ public class Emoji { } if (!canvas.quickReject(b.left, b.top, b.right, b.bottom, Canvas.EdgeType.AA)) { - canvas.drawBitmap(emojiBmp[info.page], info.rect, b, paint); + canvas.save(); + canvas.clipRect(b); + canvas.drawBitmap(emojiBmp[info.page][info.page2], info.rect, b, fullSize ? null : paint); + canvas.restore(); } } @Override public int getOpacity() { - return 0; + return PixelFormat.TRANSPARENT; } @Override @@ -400,10 +292,12 @@ public class Emoji { private static class DrawableInfo { public Rect rect; public byte page; + public byte page2; - public DrawableInfo(Rect r, byte p) { + public DrawableInfo(Rect r, byte p, byte p2) { rect = r; page = p; + page2 = p2; } } @@ -416,14 +310,6 @@ public class Emoji { return false; } - private static boolean isNextCharIsColor(CharSequence cs, int i) { - if (i + 2 >= cs.length()) { - return false; - } - int value = cs.charAt(i + 1) << 16 | cs.charAt(i + 2); - return value == 0xd83cdffb || value == 0xd83cdffc || value == 0xd83cdffd || value == 0xd83cdffe || value == 0xd83cdfff; - } - public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew) { if (cs == null || cs.length() == 0) { return cs; @@ -438,65 +324,97 @@ public class Emoji { } long buf = 0; int emojiCount = 0; + char c; + int startIndex = -1; + int startLength = 0; + int previousGoodIndex = 0; + StringBuilder emojiCode = new StringBuilder(16); + boolean nextIsSkinTone; + EmojiDrawable drawable; + EmojiSpan span; + int length = cs.length(); + boolean doneEmoji = false; //s.setSpansCount(emojiCount); try { - for (int i = 0; i < cs.length(); i++) { - char c = cs.charAt(i); - if (c == 0xD83C || c == 0xD83D || (buf != 0 && (buf & 0xFFFFFFFF00000000L) == 0 && (c >= 0xDDE6 && c <= 0xDDFA))) { + for (int i = 0; i < length; i++) { + c = cs.charAt(i); + if (c >= 0xD83C && c <= 0xD83E || (buf != 0 && (buf & 0xFFFFFFFF00000000L) == 0 && (buf & 0xFFFF) == 0xD83C && (c >= 0xDDE6 && c <= 0xDDFF))) { + if (startIndex == -1) { + startIndex = i; + } + emojiCode.append(c); + startLength++; buf <<= 16; buf |= c; } else if (buf > 0 && (c & 0xF000) == 0xD000) { - buf <<= 16; - buf |= c; - EmojiDrawable d = Emoji.getEmojiDrawable(buf); - if (d != null) { - boolean nextIsSkinTone = isNextCharIsColor(cs, i); - EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); - if (c >= 0xDDE6 && c <= 0xDDFA) { - s.setSpan(span, i - 3, i + (nextIsSkinTone ? 3 : 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } else { - s.setSpan(span, i - 1, i + (nextIsSkinTone ? 3 : 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - emojiCount++; - if (nextIsSkinTone) { - i += 2; - } - } + emojiCode.append(c); + startLength++; buf = 0; + doneEmoji = true; } else if (c == 0x20E3) { if (i > 0) { - char c2 = cs.charAt(i - 1); - if ((c2 >= '0' && c2 <= '9') || c2 == '#') { - buf = c2; - buf <<= 16; - buf |= c; - EmojiDrawable d = Emoji.getEmojiDrawable(buf); - if (d != null) { - boolean nextIsSkinTone = isNextCharIsColor(cs, i); - EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); - s.setSpan(span, i - 1, i + (nextIsSkinTone ? 3 : 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - emojiCount++; - if (nextIsSkinTone) { - i += 2; - } - } - buf = 0; + char c2 = cs.charAt(previousGoodIndex); + if ((c2 >= '0' && c2 <= '9') || c2 == '#' || c2 == '*') { + startIndex = previousGoodIndex; + startLength = i - previousGoodIndex + 1; + emojiCode.append(c2); + emojiCode.append(c); + doneEmoji = true; } } - } else if (inArray(c, emojiChars)) { - EmojiDrawable d = Emoji.getEmojiDrawable(c); - if (d != null) { - boolean nextIsSkinTone = isNextCharIsColor(cs, i); - EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); - s.setSpan(span, i, i + (nextIsSkinTone ? 3 : 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - emojiCount++; - if (nextIsSkinTone) { - i += 2; + } else if ((c == 0x00A9 || c == 0x00AE || c >= 0x203C && c <= 0x3299) && EmojiData.dataCharsMap.containsKey(c)) { + if (startIndex == -1) { + startIndex = i; + } + startLength++; + emojiCode.append(c); + doneEmoji = true; + } else if (startIndex != -1) { + emojiCode.setLength(0); + startIndex = -1; + startLength = 0; + doneEmoji = false; + } + previousGoodIndex = i; + for (int a = 0; a < 3; a++) { + if (i + 1 < length) { + c = cs.charAt(i + 1); + if (a == 1) { + if (c == 0x200D) { + emojiCode.append(c); + i++; + startLength++; + doneEmoji = false; + } + } else { + if (c >= 0xFE00 && c <= 0xFE0F) { + i++; + startLength++; + } } } } - if (emojiCount >= 50) { + if (doneEmoji) { + if (i + 2 < length) { + if (cs.charAt(i + 1) == 0xD83C && cs.charAt(i + 2) >= 0xDFFB && cs.charAt(i + 2) <= 0xDFFF) { + emojiCode.append(cs.subSequence(i + 1, i + 3)); + startLength += 2; + i += 2; + } + } + drawable = Emoji.getEmojiDrawable(emojiCode.subSequence(0, emojiCode.length())); + if (drawable != null) { + span = new EmojiSpan(drawable, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); + s.setSpan(span, startIndex, startIndex + startLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + emojiCount++; + } + startLength = 0; + startIndex = -1; + emojiCode.setLength(0); + doneEmoji = false; + } + if (emojiCount >= 50) { //654 new break; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java b/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java new file mode 100644 index 000000000..4fdbde10e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/EmojiData.java @@ -0,0 +1,348 @@ +/* + * This is the source code of Telegram for Android v. 3.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.messenger; + +import java.util.HashMap; + +public class EmojiData { + + public static final char[] emojiToFE0F = { + 0x2B50, 0x2600, 0x26C5, 0x2601, 0x26A1, 0x2744, 0x26C4, 0x2614, 0x2708, 0x26F5, + 0x2693, 0x26FD, 0x26F2, 0x26FA, 0x26EA, 0x2615, 0x26BD, 0x26BE, 0x26F3, 0x231A, + 0x260E, 0x231B, 0x2709, 0x2702, 0x2712, 0x270F, 0x2648, 0x2649, 0x264A, 0x264B, + 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, 0x2734, 0x3299, + 0x3297, 0x26D4, 0x2B55, 0x2668, 0x2757, 0x203C, 0x2049, 0x303D, 0x26A0, 0x267B, + 0x2747, 0x2733, 0x24C2, 0x267F, 0x25B6, 0x25C0, 0x27A1, 0x2B05, 0x2B06, 0x2B07, + 0x2197, 0x2198, 0x2199, 0x2196, 0x2195, 0x2194, 0x21AA, 0x21A9, 0x2934, 0x2935, + 0x2139, 0x2714, 0x2716, 0x2611, 0x26AA, 0x26AB, 0x25AA, 0x25AB, 0x2B1B, 0x2B1C, + 0x25FC, 0x25FB, 0x25FE, 0x25FD, 0x2660, 0x2663, 0x2665, 0x2666, 0x263A, 0x2639, + 0x270C, 0x261D, 0x2764 + }; + //0xD83CDE2F, 0xD83CDC04, 0xD83CDE1A, 0xD83CDD7F + + public static final char[] dataChars = { + 0x262E, 0x271D, 0x262A, 0x2638, 0x2721, 0x262F, 0x2626, 0x26CE, 0x2648, 0x2649, + 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, 0x2650, 0x2651, 0x2652, 0x2653, + 0x269B, 0x2622, 0x2623, 0x2734, 0x3299, 0x3297, 0x26D4, 0x274C, 0x2B55, 0x2668, + 0x2757, 0x2755, 0x2753, 0x2754, 0x203C, 0x2049, 0x269C, 0x303D, 0x26A0, 0x267B, + 0x2747, 0x2733, 0x274E, 0x2705, 0x27BF, 0x24C2, 0x267F, 0x25B6, 0x23F8, 0x23EF, + 0x23F9, 0x23FA, 0x23ED, 0x23EE, 0x23E9, 0x23EA, 0x25C0, 0x23EB, 0x23EC, 0x27A1, + 0x2B05, 0x2B06, 0x2B07, 0x2197, 0x2198, 0x2199, 0x2196, 0x2195, 0x2194, 0x21AA, + 0x21A9, 0x2934, 0x2935, 0x2139, 0x3030, 0x27B0, 0x2714, 0x2795, 0x2796, 0x2797, + 0x2716, 0x00A9, 0x00AE, 0x2122, 0x2611, 0x26AA, 0x26AB, 0x25AA, 0x25AB, 0x2B1B, + 0x2B1C, 0x25FC, 0x25FB, 0x25FE, 0x25FD, 0x2660, 0x2663, 0x2665, 0x2666, 0x263A, + 0x2639, 0x270A, 0x270C, 0x270B, 0x261D, 0x270D, 0x26D1, 0x2764, 0x2763, 0x2615, + 0x26BD, 0x26BE, 0x26F3, 0x26F7, 0x26F8, 0x26F9, 0x231A, 0x2328, 0x260E, 0x23F1, + 0x23F2, 0x23F0, 0x23F3, 0x231B, 0x2696, 0x2692, 0x26CF, 0x2699, 0x26D3, 0x2694, + 0x2620, 0x26B0, 0x26B1, 0x2697, 0x26F1, 0x2709, 0x2702, 0x2712, 0x270F, 0x2708, + 0x26F5, 0x26F4, 0x2693, 0x26FD, 0x26F2, 0x26F0, 0x26FA, 0x26EA, 0x26E9, 0x2618, + 0x2B50, 0x2728, 0x2604, 0x2600, 0x26C5, 0x2601, 0x26C8, 0x26A1, 0x2744, 0x2603, + 0x26C4, 0x2602, 0x2614 + }; + + public static final String[] emojiColored = { + "🙌", "👏", "👋", "👍", "👎", "👊", "✊", "✌", "👌", "✋", + "👐", "💪", "🙏", "☝", "👆", "👇", "👈", "👉", "🖕", "🖐", + "🤘", "🖖", "✍", "💅", "👂", "👃", "👶", "👦", "👧", "👨", + "👩", "👱", "👴", "👵", "👲", "👳", "👮", "👷", "💂", "🎅", + "👼", "👸", "👰", "🚶", "🏃", "💃", "🙇", "💁", "🙅", "🙆", + "🙋", "🙎", "🙍", "💇", "💆", "🚣", "🏊", "🏄", "🛀", "⛹", + "🏋", "🚴", "🚵", "🏇", + }; + + public static final String[][] dataColored = { + new String[]{ + "😀", "😬", "😁", "😂", "😃", "😄", "😅", "😆", "😇", "😉", "😊", + "🙂", "🙃", "☺", "😋", "😌", "😍", "😘", "😗", "😙", "😚", + "😜", "😝", "😛", "🤑", "🤓", "😎", "🤗", "😏", "😶", "😐", + "😑", "😒", "🙄", "🤔", "😳", "😞", "😟", "😠", "😡", "😔", + "😕", "🙁", "☹", "😣", "😖", "😫", "😩", "😤", "😮", "😱", + "😨", "😰", "😯", "😦", "😧", "😢", "😥", "😪", "😓", "😭", + "😵", "😲", "🤐", "😷", "🤒", "🤕", "😴", "💤", "💩", "😈", + "👿", "👹", "👺", "💀", "👻", "👽", "🤖", "😺", "😸", "😹", + "😻", "😼", "😽", "🙀", "😿", "😾", "🙌", + "👏", "👋", + "👍", + "👎", "👊", + "✊", "✌", + "👌", + "✋", "👐", + "💪", "🙏", + "☝", + "👆", "👇", + "👈", "👉", + "🖕", + "🖐", "🤘", + "🖖", "✍", + "💅", + "👄", "👅", "👂", "👃", + "👁", "👀", "👤", "👥", "🗣", "👶", + "👦", + "👧", "👨", + "👩", "👱", + "👴", + "👵", "👲", + "👳", "👮", + "👷", + "💂", "🕵", "🎅", + "👼", + "👸", "👰", + "🚶", "🏃", + "💃", + "👯", "👫", "👬", "👭", "🙇", + "💁", "🙅", + "🙆", "🙋", + "🙎", + "🙍", "💇", + "💆", "💑", "👩‍❤‍👩", + "👨‍❤‍👨", "💏", "👩‍❤‍💋‍👩", "👨‍❤‍💋‍👨", "👪", "👨‍👩‍👧", "👨‍👩‍👧‍👦", "👨‍👩‍👦‍👦", "👨‍👩‍👧‍👧", "👩‍👩‍👦", + "👩‍👩‍👧", "👩‍👩‍👧‍👦", "👩‍👩‍👦‍👦", "👩‍👩‍👧‍👧", "👨‍👨‍👦", "👨‍👨‍👧", "👨‍👨‍👧‍👦", "👨‍👨‍👦‍👦", "👨‍👨‍👧‍👧", "👚", + "👕", "👖", "👔", "👗", "👙", "👘", "💄", "💋", "👣", "👠", + "👡", "👢", "👞", "👟", "👒", "🎩", "🎓", "👑", "⛑", "🎒", + "👝", "👛", "👜", "💼", "👓", "🕶", "💍", "🌂", "❤", "💛", + "💚", "💙", "💜", "💔", "❣", "💕", "💞", "💓", "💗", "💖", + "💘", "💝", + }, + null, + new String[]{ + "🍏", "🍎", "🍐", "🍊", "🍋", "🍌", "🍉", "🍇", "🍓", "🍈", "🍒", + "🍑", "🍍", "🍅", "🍆", "🌶", "🌽", "🍠", "🍯", "🍞", "🧀", + "🍗", "🍖", "🍤", "🍳", "🍔", "🍟", "🌭", "🍕", "🍝", "🌮", + "🌯", "🍜", "🍲", "🍥", "🍣", "🍱", "🍛", "🍙", "🍚", "🍘", + "🍢", "🍡", "🍧", "🍨", "🍦", "🍰", "🎂", "🍮", "🍬", "🍭", + "🍫", "🍿", "🍩", "🍪", "🍺", "🍻", "🍷", "🍸", "🍹", "🍾", + "🍶", "🍵", "☕", "🍼", "🍴", "🍽", "⚽", "🏀", "🏈", "⚾", + "🎾", "🏐", "🏉", "🎱", "⛳", "🏌", "🏓", "🏸", "🏒", "🏑", + "🏏", "🎿", "⛷", "🏂", "⛸", "🏹", "🎣", "🚣", + "🏊", "🏄", + "🛀", + "⛹", "🏋", + "🚴", "🚵", + "🏇", + "🕴", "🏆", "🎽", "🏅", "🎖", "🎗", "🏵", "🎫", "🎟", + "🎭", "🎨", "🎪", "🎤", "🎧", "🎼", "🎹", "🎷", "🎺", "🎸", + "🎻", "🎬", "🎮", "👾", "🎯", "🎲", "🎰", "🎳", "⌚", "📱", + "📲", "💻", "⌨", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", + "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", + "📞", "☎", "📟", "🎛", "⏱", "⏲", "⏰", "🕰", "⏳", "⌛", + "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🗑", "🛢", "💸", "💵", + "💴", "💶", "💷", "💰", "💳", "💎", "⚖", "🔧", "🔨", "⚒", + "🛠", "⛏", "🔩", "⚙", "⛓", "🔫", "💣", "🔪", "🗡", "⚔", + "🛡", "🚬", "☠", "⚰", "⚱", "🏺", "🔮", "📿", "💈", "⚗", + "🔭", "🔬", "🕳", "💊", "💉", "🌡", "🏷", "🔖", "🚽", "🚿", + "🛁", "🔑", "🗝", "🛋", "🛌", "🛏", "🚪", "🛎", "🖼", "🗺", + "⛱", "🗿", "🛍", "🎈", "🎏", "🎀", "🎁", "🎊", "🎉", "🎎", + "🎐", "🎌", "🏮", "✉", "📩", "📨", "📧", "💌", "📮", "📪", + "📫", "📬", "📭", "📦", "📯", "📥", "📤", "📜", "📃", "📑", + "📊", "📈", "📉", "📄", "📅", "📆", "🗓", "📇", "🗃", "🗳", + "🗄", "📋", "🗒", "📁", "📂", "🗂", "🗞", "📰", "📓", "📕", + "📗", "📘", "📙", "📔", "📒", "📚", "📖", "🔗", "📎", "🖇", + "✂", "📐", "📏", "📌", "📍", "🚩", "🏳", "🏴", "🔐", "🔒", + "🔓", "🔏", "🖊", "🖋", "✒", "📝", "✏", "🖍", "🖌", "🔍", + "🔎", + }, + null, + null + }; + + public static final String[][] data = { + new String[]{ + "😀", "😬", "😁", "😂", "😃", "😄", "😅", "😆", "😇", "😉", "😊", + "🙂", "🙃", "☺", "😋", "😌", "😍", "😘", "😗", "😙", "😚", + "😜", "😝", "😛", "🤑", "🤓", "😎", "🤗", "😏", "😶", "😐", + "😑", "😒", "🙄", "🤔", "😳", "😞", "😟", "😠", "😡", "😔", + "😕", "🙁", "☹", "😣", "😖", "😫", "😩", "😤", "😮", "😱", + "😨", "😰", "😯", "😦", "😧", "😢", "😥", "😪", "😓", "😭", + "😵", "😲", "🤐", "😷", "🤒", "🤕", "😴", "💤", "💩", "😈", + "👿", "👹", "👺", "💀", "👻", "👽", "🤖", "😺", "😸", "😹", + "😻", "😼", "😽", "🙀", "😿", "😾", "🙌", "🙌🏻", "🙌🏼", "🙌🏽", + "🙌🏾", "🙌🏿", "👏", "👏🏻", "👏🏼", "👏🏽", "👏🏾", "👏🏿", "👋", "👋🏻", + "👋🏼", "👋🏽", "👋🏾", "👋🏿", "👍", "👍🏻", "👍🏼", "👍🏽", "👍🏾", "👍🏿", + "👎", "👎🏻", "👎🏼", "👎🏽", "👎🏾", "👎🏿", "👊", "👊🏻", "👊🏼", "👊🏽", + "👊🏾", "👊🏿", "✊", "✊🏻", "✊🏼", "✊🏽", "✊🏾", "✊🏿", "✌", "✌🏻", + "✌🏼", "✌🏽", "✌🏾", "✌🏿", "👌", "👌🏻", "👌🏼", "👌🏽", "👌🏾", "👌🏿", + "✋", "✋🏻", "✋🏼", "✋🏽", "✋🏾", "✋🏿", "👐", "👐🏻", "👐🏼", "👐🏽", + "👐🏾", "👐🏿", "💪", "💪🏻", "💪🏼", "💪🏽", "💪🏾", "💪🏿", "🙏", "🙏🏻", + "🙏🏼", "🙏🏽", "🙏🏾", "🙏🏿", "☝", "☝🏻", "☝🏼", "☝🏽", "☝🏾", "☝🏿", + "👆", "👆🏻", "👆🏼", "👆🏽", "👆🏾", "👆🏿", "👇", "👇🏻", "👇🏼", "👇🏽", + "👇🏾", "👇🏿", "👈", "👈🏻", "👈🏼", "👈🏽", "👈🏾", "👈🏿", "👉", "👉🏻", + "👉🏼", "👉🏽", "👉🏾", "👉🏿", "🖕", "🖕🏻", "🖕🏼", "🖕🏽", "🖕🏾", "🖕🏿", + "🖐", "🖐🏻", "🖐🏼", "🖐🏽", "🖐🏾", "🖐🏿", "🤘", "🤘🏻", "🤘🏼", "🤘🏽", + "🤘🏾", "🤘🏿", "🖖", "🖖🏻", "🖖🏼", "🖖🏽", "🖖🏾", "🖖🏿", "✍", "✍🏻", + "✍🏼", "✍🏽", "✍🏾", "✍🏿", "💅", "💅🏻", "💅🏼", "💅🏽", "💅🏾", "💅🏿", + "👄", "👅", "👂", "👂🏻", "👂🏼", "👂🏽", "👂🏾", "👂🏿", "👃", "👃🏻", + "👃🏼", "👃🏽", "👃🏾", "👃🏿", "👁", "👀", "👤", "👥", "🗣", "👶", + "👶🏻", "👶🏼", "👶🏽", "👶🏾", "👶🏿", "👦", "👦🏻", "👦🏼", "👦🏽", "👦🏾", + "👦🏿", "👧", "👧🏻", "👧🏼", "👧🏽", "👧🏾", "👧🏿", "👨", "👨🏻", "👨🏼", + "👨🏽", "👨🏾", "👨🏿", "👩", "👩🏻", "👩🏼", "👩🏽", "👩🏾", "👩🏿", "👱", + "👱🏻", "👱🏼", "👱🏽", "👱🏾", "👱🏿", "👴", "👴🏻", "👴🏼", "👴🏽", "👴🏾", + "👴🏿", "👵", "👵🏻", "👵🏼", "👵🏽", "👵🏾", "👵🏿", "👲", "👲🏻", "👲🏼", + "👲🏽", "👲🏾", "👲🏿", "👳", "👳🏻", "👳🏼", "👳🏽", "👳🏾", "👳🏿", "👮", + "👮🏻", "👮🏼", "👮🏽", "👮🏾", "👮🏿", "👷", "👷🏻", "👷🏼", "👷🏽", "👷🏾", + "👷🏿", "💂", "💂🏻", "💂🏼", "💂🏽", "💂🏾", "💂🏿", "🕵", "🎅", "🎅🏻", + "🎅🏼", "🎅🏽", "🎅🏾", "🎅🏿", "👼", "👼🏻", "👼🏼", "👼🏽", "👼🏾", "👼🏿", + "👸", "👸🏻", "👸🏼", "👸🏽", "👸🏾", "👸🏿", "👰", "👰🏻", "👰🏼", "👰🏽", + "👰🏾", "👰🏿", "🚶", "🚶🏻", "🚶🏼", "🚶🏽", "🚶🏾", "🚶🏿", "🏃", "🏃🏻", + "🏃🏼", "🏃🏽", "🏃🏾", "🏃🏿", "💃", "💃🏻", "💃🏼", "💃🏽", "💃🏾", "💃🏿", + "👯", "👫", "👬", "👭", "🙇", "🙇🏻", "🙇🏼", "🙇🏽", "🙇🏾", "🙇🏿", + "💁", "💁🏻", "💁🏼", "💁🏽", "💁🏾", "💁🏿", "🙅", "🙅🏻", "🙅🏼", "🙅🏽", + "🙅🏾", "🙅🏿", "🙆", "🙆🏻", "🙆🏼", "🙆🏽", "🙆🏾", "🙆🏿", "🙋", "🙋🏻", + "🙋🏼", "🙋🏽", "🙋🏾", "🙋🏿", "🙎", "🙎🏻", "🙎🏼", "🙎🏽", "🙎🏾", "🙎🏿", + "🙍", "🙍🏻", "🙍🏼", "🙍🏽", "🙍🏾", "🙍🏿", "💇", "💇🏻", "💇🏼", "💇🏽", + "💇🏾", "💇🏿", "💆", "💆🏻", "💆🏼", "💆🏽", "💆🏾", "💆🏿", "💑", "👩‍❤‍👩", + "👨‍❤‍👨", "💏", "👩‍❤‍💋‍👩", "👨‍❤‍💋‍👨", "👪", "👨‍👩‍👧", "👨‍👩‍👧‍👦", "👨‍👩‍👦‍👦", "👨‍👩‍👧‍👧", "👩‍👩‍👦", + "👩‍👩‍👧", "👩‍👩‍👧‍👦", "👩‍👩‍👦‍👦", "👩‍👩‍👧‍👧", "👨‍👨‍👦", "👨‍👨‍👧", "👨‍👨‍👧‍👦", "👨‍👨‍👦‍👦", "👨‍👨‍👧‍👧", "👚", + "👕", "👖", "👔", "👗", "👙", "👘", "💄", "💋", "👣", "👠", + "👡", "👢", "👞", "👟", "👒", "🎩", "🎓", "👑", "⛑", "🎒", + "👝", "👛", "👜", "💼", "👓", "🕶", "💍", "🌂", "❤", "💛", + "💚", "💙", "💜", "💔", "❣", "💕", "💞", "💓", "💗", "💖", + "💘", "💝" + }, + new String[]{ + "🐶", "🐱", "🐭", "🐹", "🐰", "🐻", "🐼", "🐨", "🐯", "🦁", "🐮", + "🐷", "🐽", "🐸", "🐙", "🐵", "🙈", "🙉", "🙊", "🐒", "🐔", + "🐧", "🐦", "🐤", "🐣", "🐥", "🐺", "🐗", "🐴", "🦄", "🐝", + "🐛", "🐌", "🐞", "🐜", "🕷", "🦂", "🦀", "🐍", "🐢", "🐠", + "🐟", "🐡", "🐬", "🐳", "🐋", "🐊", "🐆", "🐅", "🐃", "🐂", + "🐄", "🐪", "🐫", "🐘", "🐐", "🐏", "🐑", "🐎", "🐖", "🐀", + "🐁", "🐓", "🦃", "🕊", "🐕", "🐩", "🐈", "🐇", "🐿", "🐾", + "🐉", "🐲", "🌵", "🎄", "🌲", "🌳", "🌴", "🌱", "🌿", "☘", + "🍀", "🎍", "🎋", "🍃", "🍂", "🍁", "🌾", "🌺", "🌻", "🌹", + "🌷", "🌼", "🌸", "💐", "🍄", "🌰", "🎃", "🐚", "🕸", "🌎", + "🌍", "🌏", "🌕", "🌖", "🌗", "🌘", "🌑", "🌒", "🌓", "🌔", + "🌚", "🌝", "🌛", "🌜", "🌞", "🌙", "⭐", "🌟", "💫", "✨", + "☄", "☀", "🌤", "⛅", "🌥", "🌦", "☁", "🌧", "⛈", "🌩", + "⚡", "🔥", "💥", "❄", "🌨", "☃", "⛄", "🌬", "💨", "🌪", + "🌫", "☂", "☔", "💧", "💦", "🌊" + }, + new String[]{ + "🍏", "🍎", "🍐", "🍊", "🍋", "🍌", "🍉", "🍇", "🍓", "🍈", "🍒", + "🍑", "🍍", "🍅", "🍆", "🌶", "🌽", "🍠", "🍯", "🍞", "🧀", + "🍗", "🍖", "🍤", "🍳", "🍔", "🍟", "🌭", "🍕", "🍝", "🌮", + "🌯", "🍜", "🍲", "🍥", "🍣", "🍱", "🍛", "🍙", "🍚", "🍘", + "🍢", "🍡", "🍧", "🍨", "🍦", "🍰", "🎂", "🍮", "🍬", "🍭", + "🍫", "🍿", "🍩", "🍪", "🍺", "🍻", "🍷", "🍸", "🍹", "🍾", + "🍶", "🍵", "☕", "🍼", "🍴", "🍽", "⚽", "🏀", "🏈", "⚾", + "🎾", "🏐", "🏉", "🎱", "⛳", "🏌", "🏓", "🏸", "🏒", "🏑", + "🏏", "🎿", "⛷", "🏂", "⛸", "🏹", "🎣", "🚣", "🚣🏻", "🚣🏼", + "🚣🏽", "🚣🏾", "🚣🏿", "🏊", "🏊🏻", "🏊🏼", "🏊🏽", "🏊🏾", "🏊🏿", "🏄", + "🏄🏻", "🏄🏼", "🏄🏽", "🏄🏾", "🏄🏿", "🛀", "🛀🏻", "🛀🏼", "🛀🏽", "🛀🏾", + "🛀🏿", "⛹", "⛹🏻", "⛹🏼", "⛹🏽", "⛹🏾", "⛹🏿", "🏋", "🏋🏻", "🏋🏼", + "🏋🏽", "🏋🏾", "🏋🏿", "🚴", "🚴🏻", "🚴🏼", "🚴🏽", "🚴🏾", "🚴🏿", "🚵", + "🚵🏻", "🚵🏼", "🚵🏽", "🚵🏾", "🚵🏿", "🏇", "🏇🏻", "🏇🏼", "🏇🏽", "🏇🏾", + "🏇🏿", "🕴", "🏆", "🎽", "🏅", "🎖", "🎗", "🏵", "🎫", "🎟", + "🎭", "🎨", "🎪", "🎤", "🎧", "🎼", "🎹", "🎷", "🎺", "🎸", + "🎻", "🎬", "🎮", "👾", "🎯", "🎲", "🎰", "🎳", "⌚", "📱", + "📲", "💻", "⌨", "🖥", "🖨", "🖱", "🖲", "🕹", "🗜", "💽", + "💾", "💿", "📀", "📼", "📷", "📸", "📹", "🎥", "📽", "🎞", + "📞", "☎", "📟", "🎛", "⏱", "⏲", "⏰", "🕰", "⏳", "⌛", + "📡", "🔋", "🔌", "💡", "🔦", "🕯", "🗑", "🛢", "💸", "💵", + "💴", "💶", "💷", "💰", "💳", "💎", "⚖", "🔧", "🔨", "⚒", + "🛠", "⛏", "🔩", "⚙", "⛓", "🔫", "💣", "🔪", "🗡", "⚔", + "🛡", "🚬", "☠", "⚰", "⚱", "🏺", "🔮", "📿", "💈", "⚗", + "🔭", "🔬", "🕳", "💊", "💉", "🌡", "🏷", "🔖", "🚽", "🚿", + "🛁", "🔑", "🗝", "🛋", "🛌", "🛏", "🚪", "🛎", "🖼", "🗺", + "⛱", "🗿", "🛍", "🎈", "🎏", "🎀", "🎁", "🎊", "🎉", "🎎", + "🎐", "🎌", "🏮", "✉", "📩", "📨", "📧", "💌", "📮", "📪", + "📫", "📬", "📭", "📦", "📯", "📥", "📤", "📜", "📃", "📑", + "📊", "📈", "📉", "📄", "📅", "📆", "🗓", "📇", "🗃", "🗳", + "🗄", "📋", "🗒", "📁", "📂", "🗂", "🗞", "📰", "📓", "📕", + "📗", "📘", "📙", "📔", "📒", "📚", "📖", "🔗", "📎", "🖇", + "✂", "📐", "📏", "📌", "📍", "🚩", "🏳", "🏴", "🔐", "🔒", + "🔓", "🔏", "🖊", "🖋", "✒", "📝", "✏", "🖍", "🖌", "🔍", + "🔎" + }, + new String[]{ + "🚗", "🚕", "🚙", "🚌", "🚎", "🏎", "🚓", "🚑", "🚒", "🚐", "🚚", + "🚛", "🚜", "🏍", "🚲", "🚨", "🚔", "🚍", "🚘", "🚖", "🚡", + "🚠", "🚟", "🚃", "🚋", "🚝", "🚄", "🚅", "🚈", "🚞", "🚂", + "🚆", "🚇", "🚊", "🚉", "🚁", "🛩", "✈", "🛫", "🛬", "⛵", + "🛥", "🚤", "⛴", "🛳", "🚀", "🛰", "💺", "⚓", "🚧", "⛽", + "🚏", "🚦", "🚥", "🏁", "🚢", "🎡", "🎢", "🎠", "🏗", "🌁", + "🗼", "🏭", "⛲", "🎑", "⛰", "🏔", "🗻", "🌋", "🗾", "🏕", + "⛺", "🏞", "🛣", "🛤", "🌅", "🌄", "🏜", "🏖", "🏝", "🌇", + "🌆", "🏙", "🌃", "🌉", "🌌", "🌠", "🎇", "🎆", "🌈", "🏘", + "🏰", "🏯", "🏟", "🗽", "🏠", "🏡", "🏚", "🏢", "🏬", "🏣", + "🏤", "🏥", "🏦", "🏨", "🏪", "🏫", "🏩", "💒", "🏛", "⛪", + "🕌", "🕍", "🕋", "⛩", "🇦🇺", "🇦🇹", "🇦🇿", "🇦🇽", "🇦🇱", "🇩🇿", + "🇦🇸", "🇦🇮", "🇦🇴", "🇦🇩", "🇦🇶", "🇦🇬", "🇦🇷", "🇦🇲", "🇦🇼", "🇦🇫", + "🇧🇸", "🇧🇩", "🇧🇧", "🇧🇭", "🇧🇾", "🇧🇿", "🇧🇪", "🇧🇯", "🇧🇲", "🇧🇬", + "🇧🇴", "🇧🇶", "🇧🇦", "🇧🇼", "🇧🇷", "🇮🇴", "🇧🇳", "🇧🇫", "🇧🇮", "🇧🇹", + "🇻🇺", "🇻🇦", "🇬🇧", "🇭🇺", "🇻🇪", "🇻🇬", "🇻🇮", "🇹🇱", "🇻🇳", "🇬🇦", + "🇭🇹", "🇬🇾", "🇬🇲", "🇬🇭", "🇬🇵", "🇬🇹", "🇬🇳", "🇬🇼", "🇩🇪", "🇬🇬", + "🇬🇮", "🇭🇳", "🇭🇰", "🇬🇩", "🇬🇱", "🇬🇷", "🇬🇪", "🇬🇺", "🇩🇰", "🇯🇪", + "🇩🇯", "🇩🇲", "🇩🇴", "🇪🇺", "🇪🇬", "🇿🇲", "🇪🇭", "🇿🇼", "🇮🇱", "🇮🇳", + "🇮🇩", "🇯🇴", "🇮🇶", "🇮🇷", "🇮🇪", "🇮🇸", "🇪🇸", "🇮🇹", "🇾🇪", "🇨🇻", + "🇰🇿", "🇰🇾", "🇰🇭", "🇨🇲", "🇨🇦", "🇮🇨", "🇶🇦", "🇰🇪", "🇨🇾", "🇰🇬", + "🇰🇮", "🇨🇳", "🇰🇵", "🇨🇨", "🇨🇴", "🇰🇲", "🇨🇬", "🇨🇩", "🇽🇰", "🇨🇷", + "🇨🇮", "🇨🇺", "🇰🇼", "🇨🇼", "🇱🇦", "🇱🇻", "🇱🇸", "🇱🇷", "🇱🇧", "🇱🇾", + "🇱🇹", "🇱🇮", "🇱🇺", "🇲🇺", "🇲🇷", "🇲🇬", "🇾🇹", "🇲🇴", "🇲🇰", "🇲🇼", + "🇲🇾", "🇲🇱", "🇲🇻", "🇲🇹", "🇲🇦", "🇲🇶", "🇲🇭", "🇲🇽", "🇫🇲", "🇲🇿", + "🇲🇩", "🇲🇨", "🇲🇳", "🇲🇸", "🇲🇲", "🇳🇦", "🇳🇷", "🇳🇵", "🇳🇪", "🇳🇬", + "🇳🇱", "🇳🇮", "🇳🇺", "🇳🇿", "🇳🇨", "🇳🇴", "🇮🇲", "🇳🇫", "🇨🇽", "🇸🇭", + "🇨🇰", "🇹🇨", "🇦🇪", "🇴🇲", "🇵🇰", "🇵🇼", "🇵🇸", "🇵🇦", "🇵🇬", "🇵🇾", + "🇵🇪", "🇵🇳", "🇵🇱", "🇵🇹", "🇵🇷", "🇰🇷", "🇷🇪", "🇷🇺", "🇷🇼", "🇷🇴", + "🇸🇻", "🇼🇸", "🇸🇲", "🇸🇹", "🇸🇦", "🇸🇿", "🇲🇵", "🇸🇨", "🇧🇱", "🇵🇲", + "🇸🇳", "🇻🇨", "🇰🇳", "🇱🇨", "🇷🇸", "🇸🇬", "🇸🇽", "🇸🇾", "🇸🇰", "🇸🇮", + "🇺🇸", "🇸🇧", "🇸🇴", "🇸🇩", "🇸🇷", "🇸🇱", "🇹🇯", "🇹🇭", "🇹🇼", "🇹🇿", + "🇹🇬", "🇹🇰", "🇹🇴", "🇹🇹", "🇹🇻", "🇹🇳", "🇹🇲", "🇹🇷", "🇺🇬", "🇺🇿", + "🇺🇦", "🇼🇫", "🇺🇾", "🇫🇴", "🇫🇯", "🇵🇭", "🇫🇮", "🇫🇰", "🇫🇷", "🇬🇫", + "🇵🇫", "🇹🇫", "🇭🇷", "🇨🇫", "🇹🇩", "🇲🇪", "🇨🇿", "🇨🇱", "🇨🇭", "🇸🇪", + "🇱🇰", "🇪🇨", "🇬🇶", "🇪🇷", "🇪🇪", "🇪🇹", "🇿🇦", "🇬🇸", "🇸🇸", "🇯🇲", + "🇯🇵" + }, + new String[]{ + "💟", "☮", "✝", "☪", "🕉", "☸", "✡", "🔯", "🕎", "☯", "☦", + "🛐", "⛎", "♈", "♉", "♊", "♋", "♌", "♍", "♎", "♏", + "♐", "♑", "♒", "♓", "🆔", "⚛", "🈳", "🈹", "☢", "☣", + "📴", "📳", "🈶", "🈚", "🈸", "🈺", "🈷", "✴", "🆚", "🉑", + "💮", "🉐", "㊙", "㊗", "🈴", "🈵", "🈲", "🅰", "🅱", "🆎", + "🆑", "🅾", "🆘", "⛔", "📛", "🚫", "❌", "⭕", "💢", "♨", + "🚷", "🚯", "🚳", "🚱", "🔞", "📵", "❗", "❕", "❓", "❔", + "‼", "⁉", "💯", "🔅", "🔆", "🔱", "⚜", "〽", "⚠", "🚸", + "🔰", "♻", "🈯", "💹", "❇", "✳", "❎", "✅", "💠", "🌀", + "➿", "🌐", "Ⓜ", "🏧", "🈂", "🛂", "🛃", "🛄", "🛅", "♿", + "🚭", "🚾", "🅿", "🚰", "🚹", "🚺", "🚼", "🚻", "🚮", "🎦", + "📶", "🈁", "🆖", "🆗", "🆙", "🆒", "🆕", "🆓", "0⃣", "1⃣", + "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟", "🔢", + "▶", "⏸", "⏯", "⏹", "⏺", "⏭", "⏮", "⏩", "⏪", "🔀", + "🔁", "🔂", "◀", "🔼", "🔽", "⏫", "⏬", "➡", "⬅", "⬆", + "⬇", "↗", "↘", "↙", "↖", "↕", "↔", "🔄", "↪", "↩", + "⤴", "⤵", "#⃣", "*⃣", "ℹ", "🔤", "🔡", "🔠", "🔣", "🎵", + "🎶", "〰", "➰", "✔", "🔃", "➕", "➖", "➗", "✖", "💲", + "💱", "©", "®", "™", "🔚", "🔙", "🔛", "🔝", "🔜", "☑", + "🔘", "⚪", "⚫", "🔴", "🔵", "🔸", "🔹", "🔶", "🔷", "🔺", + "▪", "▫", "⬛", "⬜", "🔻", "◼", "◻", "◾", "◽", "🔲", + "🔳", "🔈", "🔉", "🔊", "🔇", "📣", "📢", "🔔", "🔕", "🃏", + "🀄", "♠", "♣", "♥", "♦", "🎴", "👁‍🗨", "💭", "🗯", "💬", + "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", + "🕚", "🕛", "🕜", "🕝", "🕞", "🕟", "🕠", "🕡", "🕢", "🕣", + "🕤", "🕥", "🕦", "🕧" + } + }; + + public static final HashMap emojiToFE0FMap = new HashMap<>(emojiToFE0F.length); + public static final HashMap dataCharsMap = new HashMap<>(dataChars.length); + public static final HashMap emojiColoredMap = new HashMap<>(emojiColored.length); + + static { + for (int a = 0; a < emojiToFE0F.length; a++) { + emojiToFE0FMap.put(emojiToFE0F[a], true); + } + for (int a = 0; a < dataChars.length; a++) { + dataCharsMap.put(dataChars[a], true); + } + for (int a = 0; a < emojiColored.length; a++) { + emojiColoredMap.put(emojiColored[a], true); + } + dataColored[1] = data[1]; + dataColored[3] = data[3]; + dataColored[4] = data[4]; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 6da24d042..b99063d20 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 9eb1dd319..dc5600a20 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -23,7 +23,7 @@ public class FileLoader { public interface FileLoaderDelegate { void fileUploadProgressChanged(String location, float progress, boolean isEncrypted); - void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv); + void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv, long totalFileSize); void fileDidFailedUpload(String location, boolean isEncrypted); @@ -107,6 +107,7 @@ public class FileLoader { } uploadSizes.remove(location); if (operation != null) { + uploadOperationPathsEnc.remove(location); uploadOperationQueue.remove(operation); uploadSmallOperationQueue.remove(operation); operation.cancel(); @@ -170,7 +171,7 @@ public class FileLoader { } operation.delegate = new FileUploadOperation.FileUploadOperationDelegate() { @Override - public void didFinishUploadingFile(FileUploadOperation operation, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv) { + public void didFinishUploadingFile(final FileUploadOperation operation, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv) { fileLoaderQueue.postRunnable(new Runnable() { @Override public void run() { @@ -199,7 +200,7 @@ public class FileLoader { } } if (delegate != null) { - delegate.fileDidUploaded(location, inputFile, inputEncryptedFile, key, iv); + delegate.fileDidUploaded(location, inputFile, inputEncryptedFile, key, iv, operation.getTotalFileSize()); } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index 3ce40e4a7..1455cc9c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -22,6 +22,7 @@ public class FileLog { private FastDateFormat dateFormat = null; private DispatchQueue logQueue = null; private File currentFile = null; + private File networkFile = null; private static volatile FileLog Instance = null; public static FileLog getInstance() { @@ -65,6 +66,22 @@ public class FileLog { } } + public static String getNetworkLogPath() { + try { + File sdCard = ApplicationLoader.applicationContext.getExternalFilesDir(null); + if (sdCard == null) { + return ""; + } + File dir = new File(sdCard.getAbsolutePath() + "/logs"); + dir.mkdirs(); + getInstance().networkFile = new File(dir, getInstance().dateFormat.format(System.currentTimeMillis()) + "_net.txt"); + return getInstance().networkFile.getAbsolutePath(); + } catch (Throwable e) { + e.printStackTrace(); + } + return ""; + } + public static void e(final String tag, final String message, final Throwable exception) { if (!BuildVars.DEBUG_VERSION) { return; @@ -180,6 +197,9 @@ public class FileLog { if (getInstance().currentFile != null && file.getAbsolutePath().equals(getInstance().currentFile.getAbsolutePath())) { continue; } + if (getInstance().networkFile != null && file.getAbsolutePath().equals(getInstance().networkFile.getAbsolutePath())) { + continue; + } file.delete(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index da776516c..e60cc2892 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -63,6 +63,10 @@ public class FileUploadOperation { estimatedSize = estimated; } + public long getTotalFileSize() { + return totalFileSize; + } + public void start() { if (state != 0) { return; @@ -77,7 +81,7 @@ public class FileUploadOperation { } public void cancel() { - if (state != 1) { + if (state == 3) { return; } state = 2; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/GcmBroadcastReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/GcmBroadcastReceiver.java index 8ad9d9a37..7a18c9e1b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/GcmBroadcastReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/GcmBroadcastReceiver.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index a86af8f97..4b6797053 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -466,7 +466,7 @@ public class ImageLoader { return; } float scaleFactor = Math.min((float) w / size, (float) h / size); - Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, (int) (w / scaleFactor), (int) (h / scaleFactor), true); + Bitmap scaledBitmap = Bitmaps.createScaledBitmap(originalBitmap, (int) (w / scaleFactor), (int) (h / scaleFactor), true); if (scaledBitmap != originalBitmap) { originalBitmap.recycle(); } @@ -590,14 +590,20 @@ public class ImageLoader { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 1; - if (!useNativeWebpLoaded && Build.VERSION.SDK_INT > 10 && Build.VERSION.SDK_INT < 21) { + if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 21) { opts.inPurgeable = true; } if (useNativeWebpLoaded) { RandomAccessFile file = new RandomAccessFile(cacheFileFinal, "r"); ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, cacheFileFinal.length()); - image = Utilities.loadWebpImage(buffer, buffer.limit(), null); + + BitmapFactory.Options bmOptions = new BitmapFactory.Options(); + bmOptions.inJustDecodeBounds = true; + Utilities.loadWebpImage(null, buffer, buffer.limit(), bmOptions, true); + image = Bitmaps.createBitmap(bmOptions.outWidth, bmOptions.outHeight, Bitmap.Config.ARGB_8888); + + Utilities.loadWebpImage(image, buffer, buffer.limit(), null, !opts.inPurgeable); file.close(); } else { if (opts.inPurgeable) { @@ -629,8 +635,7 @@ public class ImageLoader { Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); Utilities.blurBitmap(image, 7, opts.inPurgeable ? 0 : 1); - } - if (blurType == 0 && opts.inPurgeable) { + } else if (blurType == 0 && opts.inPurgeable) { Utilities.pinBitmap(image); } if (runtimeHack != null) { @@ -730,7 +735,7 @@ public class ImageLoader { } else { opts.inPreferredConfig = Bitmap.Config.RGB_565; } - if (!useNativeWebpLoaded && Build.VERSION.SDK_INT > 10 && Build.VERSION.SDK_INT < 21) { + if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 21) { opts.inPurgeable = true; } @@ -746,7 +751,13 @@ public class ImageLoader { if (useNativeWebpLoaded) { RandomAccessFile file = new RandomAccessFile(cacheFileFinal, "r"); ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, cacheFileFinal.length()); - image = Utilities.loadWebpImage(buffer, buffer.limit(), null); + + BitmapFactory.Options bmOptions = new BitmapFactory.Options(); + bmOptions.inJustDecodeBounds = true; + Utilities.loadWebpImage(null, buffer, buffer.limit(), bmOptions, true); + image = Bitmaps.createBitmap(bmOptions.outWidth, bmOptions.outHeight, Bitmap.Config.ARGB_8888); + + Utilities.loadWebpImage(image, buffer, buffer.limit(), null, !opts.inPurgeable); file.close(); } else { if (opts.inPurgeable) { @@ -776,7 +787,7 @@ public class ImageLoader { float bitmapH = image.getHeight(); if (!opts.inPurgeable && w_filter != 0 && bitmapW != w_filter && bitmapW > w_filter + 20) { float scaleFactor = bitmapW / w_filter; - Bitmap scaledBitmap = Bitmap.createScaledBitmap(image, (int) w_filter, (int) (bitmapH / scaleFactor), true); + Bitmap scaledBitmap = Bitmaps.createScaledBitmap(image, (int) w_filter, (int) (bitmapH / scaleFactor), true); if (image != scaledBitmap) { image.recycle(); image = scaledBitmap; @@ -1010,6 +1021,12 @@ public class ImageLoader { } public ImageLoader() { + + cacheOutQueue.setPriority(Thread.MIN_PRIORITY); + cacheThumbOutQueue.setPriority(Thread.MIN_PRIORITY); + thumbGeneratingQueue.setPriority(Thread.MIN_PRIORITY); + imageLoadQueue.setPriority(Thread.MIN_PRIORITY); + int cacheSize = Math.min(15, ((ActivityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass() / 7) * 1024 * 1024; if (Build.VERSION.SDK_INT < 11) { @@ -1018,8 +1035,8 @@ public class ImageLoader { } memCache = new LruCache(cacheSize) { @Override - protected int sizeOf(String key, BitmapDrawable bitmap) { - Bitmap b = bitmap.getBitmap(); + protected int sizeOf(String key, BitmapDrawable value) { + Bitmap b = value.getBitmap(); if (Build.VERSION.SDK_INT < 12) { return b.getRowBytes() * b.getHeight(); } else { @@ -1028,13 +1045,13 @@ public class ImageLoader { } @Override - protected void entryRemoved(boolean evicted, String key, final BitmapDrawable oldBitmap, BitmapDrawable newBitmap) { + protected void entryRemoved(boolean evicted, String key, final BitmapDrawable oldValue, BitmapDrawable newValue) { if (ignoreRemoval != null && key != null && ignoreRemoval.equals(key)) { return; } final Integer count = bitmapUseCounts.get(key); if (count == null || count == 0) { - Bitmap b = oldBitmap.getBitmap(); + Bitmap b = oldValue.getBitmap(); if (runtimeHack != null) { runtimeHack.trackAlloc(b.getRowBytes() * b.getHeight()); } @@ -1063,14 +1080,14 @@ public class ImageLoader { } @Override - public void fileDidUploaded(final String location, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv) { + public void fileDidUploaded(final String location, final TLRPC.InputFile inputFile, final TLRPC.InputEncryptedFile inputEncryptedFile, final byte[] key, final byte[] iv, final long totalFileSize) { Utilities.stageQueue.postRunnable(new Runnable() { @Override public void run() { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidUpload, location, inputFile, inputEncryptedFile, key, iv); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.FileDidUpload, location, inputFile, inputEncryptedFile, key, iv, totalFileSize); } }); fileProgresses.remove(location); @@ -1172,7 +1189,7 @@ public class ImageLoader { FileLoader.getInstance().setMediaDirs(createMediaPaths()); } - private HashMap createMediaPaths() { + public HashMap createMediaPaths() { HashMap mediaDirs = new HashMap<>(); File cachePath = AndroidUtilities.getCacheDir(); if (!cachePath.isDirectory()) { @@ -1257,7 +1274,7 @@ public class ImageLoader { private boolean canMoveFiles(File from, File to) { RandomAccessFile file = null; try { - for (int a = 0; a < 5; a++) { + for (int a = 0; a < 2; a++) { File srcFile = new File(from, "temp.file"); srcFile.createNewFile(); file = new RandomAccessFile(srcFile, "rws"); @@ -1914,6 +1931,7 @@ public class ImageLoader { } bmOptions.inJustDecodeBounds = false; bmOptions.inSampleSize = (int) scaleFactor; + bmOptions.inPurgeable = Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 21; String exifPath = null; if (path != null) { @@ -1951,7 +1969,14 @@ public class ImageLoader { try { b = BitmapFactory.decodeFile(path, bmOptions); if (b != null) { - b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true); + if (bmOptions.inPurgeable) { + Utilities.pinBitmap(b); + } + Bitmap newBitmap = Bitmaps.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true); + if (newBitmap != b) { + b.recycle(); + b = newBitmap; + } } } catch (Throwable e) { FileLog.e("tmessages", e); @@ -1959,9 +1984,16 @@ public class ImageLoader { try { if (b == null) { b = BitmapFactory.decodeFile(path, bmOptions); + if (b != null && bmOptions.inPurgeable) { + Utilities.pinBitmap(b); + } } if (b != null) { - b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true); + Bitmap newBitmap = Bitmaps.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true); + if (newBitmap != b) { + b.recycle(); + b = newBitmap; + } } } catch (Throwable e2) { FileLog.e("tmessages", e2); @@ -1971,7 +2003,14 @@ public class ImageLoader { try { b = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, bmOptions); if (b != null) { - b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true); + if (bmOptions.inPurgeable) { + Utilities.pinBitmap(b); + } + Bitmap newBitmap = Bitmaps.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true); + if (newBitmap != b) { + b.recycle(); + b = newBitmap; + } } } catch (Throwable e) { FileLog.e("tmessages", e); @@ -2007,7 +2046,7 @@ public class ImageLoader { private static TLRPC.PhotoSize scaleAndSaveImageInternal(Bitmap bitmap, int w, int h, float photoW, float photoH, float scaleFactor, int quality, boolean cache, boolean scaleAnyway) throws Exception { Bitmap scaledBitmap; if (scaleFactor > 1 || scaleAnyway) { - scaledBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true); + scaledBitmap = Bitmaps.createScaledBitmap(bitmap, w, h, true); } else { scaledBitmap = bitmap; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 0e9c66388..12ce3f535 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -3,7 +3,7 @@ * 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. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 9a9b4d3f5..c9bfa8987 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -354,7 +354,7 @@ public class LocaleController { return false; } - File finalFile = new File(ApplicationLoader.applicationContext.getFilesDir(), languageCode + ".xml"); + File finalFile = new File(ApplicationLoader.getFilesDirFixed(), languageCode + ".xml"); if (!AndroidUtilities.copyFile(file, finalFile)) { return false; } @@ -711,6 +711,14 @@ public class LocaleController { if (dateDay == day && year == dateYear) { return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("TodayAt", R.string.TodayAt), formatterDay.format(new Date(date * 1000))); + /*int diff = (int) (ConnectionsManager.getInstance().getCurrentTime() - date) / 60; + if (diff < 1) { + return LocaleController.getString("LastSeenNow", R.string.LastSeenNow); + } else if (diff < 60) { + return LocaleController.formatPluralString("LastSeenMinutes", diff); + } else { + return LocaleController.formatPluralString("LastSeenHours", (int) Math.ceil(diff / 60.0f)); + }*/ } else if (dateDay + 1 == day && year == dateYear) { return String.format("%s %s %s", LocaleController.getString("LastSeen", R.string.LastSeen), LocaleController.getString("YesterdayAt", R.string.YesterdayAt), formatterDay.format(new Date(date * 1000))); } else if (year == dateYear) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LruCache.java b/TMessagesProj/src/main/java/org/telegram/messenger/LruCache.java index 7e5280832..d1bed2cda 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LruCache.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LruCache.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 1860a397b..f7e09ac62 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -3,11 +3,12 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; +import android.Manifest; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; @@ -17,6 +18,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.database.ContentObserver; import android.database.Cursor; import android.graphics.BitmapFactory; @@ -62,6 +64,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.HashMap; @@ -273,6 +276,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel private ArrayList shuffledPlaylist = new ArrayList<>(); private int currentPlaylistNum; private boolean downloadingCurrentMessage; + private boolean playMusicAgain; private AudioInfo audioInfo; private AudioRecord audioRecorder = null; @@ -310,10 +314,22 @@ public class MediaController implements NotificationCenter.NotificationCenterDel recordBuffers.remove(0); } else { buffer = ByteBuffer.allocateDirect(recordBufferSize); + buffer.order(ByteOrder.nativeOrder()); } buffer.rewind(); int len = audioRecorder.read(buffer, buffer.capacity()); if (len > 0) { + double sum = 0; + try { + for (int i = 0; i < len / 2; i++) { + short peak = buffer.getShort(); + sum += peak * peak; + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + buffer.position(0); + final double amplitude = Math.sqrt(sum / len / 2); buffer.limit(len); final ByteBuffer finalBuffer = buffer; final boolean flush = len != buffer.capacity(); @@ -351,7 +367,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.recordProgressChanged, System.currentTimeMillis() - recordStartTime); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.recordProgressChanged, System.currentTimeMillis() - recordStartTime, amplitude); } }); } else { @@ -493,6 +509,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } for (int a = 0; a < 5; a++) { ByteBuffer buffer = ByteBuffer.allocateDirect(4096); + buffer.order(ByteOrder.nativeOrder()); recordBuffers.add(buffer); } for (int a = 0; a < 3; a++) { @@ -647,13 +664,14 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } public void cleanup() { - clenupPlayer(false, true); + cleanupPlayer(false, true); if (currentGifDrawable != null) { currentGifDrawable.recycle(); currentGifDrawable = null; } currentMediaCell = null; audioInfo = null; + playMusicAgain = false; currentGifMessageObject = null; photoDownloadQueue.clear(); audioDownloadQueue.clear(); @@ -1050,6 +1068,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (downloadingCurrentMessage && playingMessageObject != null) { String file = FileLoader.getAttachFileName(playingMessageObject.messageOwner.media.document); if (file.equals(fileName)) { + playMusicAgain = true; playAudio(playingMessageObject); } } @@ -1126,13 +1145,13 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } ArrayList markAsDeletedMessages = (ArrayList) args[0]; if (markAsDeletedMessages.contains(playingMessageObject.getId())) { - clenupPlayer(false, true); + cleanupPlayer(false, true); } } } else if (id == NotificationCenter.removeAllMessagesFromDialog) { long did = (Long) args[0]; if (playingMessageObject != null && playingMessageObject.getDialogId() == did) { - clenupPlayer(false, true); + cleanupPlayer(false, true); } } else if (id == NotificationCenter.musicDidLoaded) { long did = (Long) args[0]; @@ -1240,7 +1259,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel audioTrackPlayer.setNotificationMarkerPosition(1); } if (finalBuffersWrited == 1) { - clenupPlayer(true, true); + cleanupPlayer(true, true); } } } @@ -1287,7 +1306,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioRouteChanged, useFrontSpeaker); MessageObject currentMessageObject = playingMessageObject; float progress = playingMessageObject.audioProgress; - clenupPlayer(false, true); + cleanupPlayer(false, true); currentMessageObject.audioProgress = progress; playAudio(currentMessageObject); ignoreProximity = false; @@ -1332,41 +1351,46 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } - public void clenupPlayer(boolean notify, boolean stopService) { + public void cleanupPlayer(boolean notify, boolean stopService) { stopProximitySensor(); - if (playingMessageObject != null) { - if (audioPlayer != null) { + if (audioPlayer != null) { + try { + audioPlayer.reset(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + try { + audioPlayer.stop(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + try { + audioPlayer.release(); + audioPlayer = null; + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } else if (audioTrackPlayer != null) { + synchronized (playerObjectSync) { try { - audioPlayer.stop(); + audioTrackPlayer.pause(); + audioTrackPlayer.flush(); } catch (Exception e) { FileLog.e("tmessages", e); } try { - audioPlayer.release(); - audioPlayer = null; + audioTrackPlayer.release(); + audioTrackPlayer = null; } catch (Exception e) { FileLog.e("tmessages", e); } - } else if (audioTrackPlayer != null) { - synchronized (playerObjectSync) { - try { - audioTrackPlayer.pause(); - audioTrackPlayer.flush(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - try { - audioTrackPlayer.release(); - audioTrackPlayer = null; - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } } - stopProgressTimer(); - lastProgress = 0; - buffersWrited = 0; - isPaused = false; + } + stopProgressTimer(); + lastProgress = 0; + buffersWrited = 0; + isPaused = false; + if (playingMessageObject != null) { if (downloadingCurrentMessage) { FileLoader.getInstance().cancelLoadFile(playingMessageObject.messageOwner.media.document); } @@ -1465,6 +1489,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (playingMessageObject == current) { return playAudio(current); } + playMusicAgain = !playlist.isEmpty(); playlist.clear(); for (int a = messageObjects.size() - 1; a >= 0; a--) { MessageObject messageObject = messageObjects.get(a); @@ -1494,7 +1519,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel ArrayList currentPlayList = shuffleMusic ? shuffledPlaylist : playlist; if (byStop && repeatMode == 2) { - clenupPlayer(false, false); + cleanupPlayer(false, false); playAudio(currentPlayList.get(currentPlaylistNum)); return; } @@ -1546,6 +1571,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (currentPlaylistNum < 0 || currentPlaylistNum >= currentPlayList.size()) { return; } + playMusicAgain = true; playAudio(currentPlayList.get(currentPlaylistNum)); } @@ -1559,6 +1585,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (currentPlaylistNum < 0 || currentPlaylistNum >= currentPlayList.size()) { return; } + playMusicAgain = true; playAudio(currentPlayList.get(currentPlaylistNum)); } @@ -1599,7 +1626,8 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (audioTrackPlayer != null) { MusicPlayerService.setIgnoreAudioFocus(); } - clenupPlayer(true, false); + cleanupPlayer(!playMusicAgain, false); + playMusicAgain = false; File file = null; if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() > 0) { file = new File(messageObject.messageOwner.attachPath); @@ -1659,7 +1687,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel audioTrackPlayer.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() { @Override public void onMarkerReached(AudioTrack audioTrack) { - clenupPlayer(true, true); + cleanupPlayer(true, true); } @Override @@ -1695,7 +1723,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (!playlist.isEmpty() && playlist.size() > 1) { playNextMessage(true); } else { - clenupPlayer(true, true); + cleanupPlayer(true, true); } } }); @@ -1844,7 +1872,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (currentPlaylistNum == -1) { playlist.clear(); shuffledPlaylist.clear(); - clenupPlayer(true, true); + cleanupPlayer(true, true); } } } @@ -2448,50 +2476,52 @@ public class MediaController implements NotificationCenter.NotificationCenterDel Cursor cursor = null; try { - cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projectionPhotos, "", null, MediaStore.Images.Media.DATE_TAKEN + " DESC"); - if (cursor != null) { - int imageIdColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID); - int bucketIdColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID); - int bucketNameColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME); - int dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA); - int dateColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN); - int orientationColumn = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION); + if (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projectionPhotos, "", null, MediaStore.Images.Media.DATE_TAKEN + " DESC"); + if (cursor != null) { + int imageIdColumn = cursor.getColumnIndex(MediaStore.Images.Media._ID); + int bucketIdColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID); + int bucketNameColumn = cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME); + int dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA); + int dateColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN); + int orientationColumn = cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION); - while (cursor.moveToNext()) { - int imageId = cursor.getInt(imageIdColumn); - int bucketId = cursor.getInt(bucketIdColumn); - String bucketName = cursor.getString(bucketNameColumn); - String path = cursor.getString(dataColumn); - long dateTaken = cursor.getLong(dateColumn); - int orientation = cursor.getInt(orientationColumn); + while (cursor.moveToNext()) { + int imageId = cursor.getInt(imageIdColumn); + int bucketId = cursor.getInt(bucketIdColumn); + String bucketName = cursor.getString(bucketNameColumn); + String path = cursor.getString(dataColumn); + long dateTaken = cursor.getLong(dateColumn); + int orientation = cursor.getInt(orientationColumn); - if (path == null || path.length() == 0) { - continue; - } - - PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, orientation, false); - - if (allPhotosAlbum == null) { - allPhotosAlbum = new AlbumEntry(0, LocaleController.getString("AllPhotos", R.string.AllPhotos), photoEntry, false); - albumsSorted.add(0, allPhotosAlbum); - } - if (allPhotosAlbum != null) { - allPhotosAlbum.addPhoto(photoEntry); - } - - AlbumEntry albumEntry = albums.get(bucketId); - if (albumEntry == null) { - albumEntry = new AlbumEntry(bucketId, bucketName, photoEntry, false); - albums.put(bucketId, albumEntry); - if (cameraAlbumId == null && cameraFolder != null && path != null && path.startsWith(cameraFolder)) { - albumsSorted.add(0, albumEntry); - cameraAlbumId = bucketId; - } else { - albumsSorted.add(albumEntry); + if (path == null || path.length() == 0) { + continue; } - } - albumEntry.addPhoto(photoEntry); + PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, orientation, false); + + if (allPhotosAlbum == null) { + allPhotosAlbum = new AlbumEntry(0, LocaleController.getString("AllPhotos", R.string.AllPhotos), photoEntry, false); + albumsSorted.add(0, allPhotosAlbum); + } + if (allPhotosAlbum != null) { + allPhotosAlbum.addPhoto(photoEntry); + } + + AlbumEntry albumEntry = albums.get(bucketId); + if (albumEntry == null) { + albumEntry = new AlbumEntry(bucketId, bucketName, photoEntry, false); + albums.put(bucketId, albumEntry); + if (cameraAlbumId == null && cameraFolder != null && path != null && path.startsWith(cameraFolder)) { + albumsSorted.add(0, albumEntry); + cameraAlbumId = bucketId; + } else { + albumsSorted.add(albumEntry); + } + } + + albumEntry.addPhoto(photoEntry); + } } } } catch (Throwable e) { @@ -2507,50 +2537,52 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } try { - albums.clear(); - AlbumEntry allVideosAlbum = null; - cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projectionVideo, "", null, MediaStore.Video.Media.DATE_TAKEN + " DESC"); - if (cursor != null) { - int imageIdColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID); - int bucketIdColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID); - int bucketNameColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME); - int dataColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATA); - int dateColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATE_TAKEN); + if (Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 23 && ApplicationLoader.applicationContext.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + albums.clear(); + AlbumEntry allVideosAlbum = null; + cursor = MediaStore.Images.Media.query(ApplicationLoader.applicationContext.getContentResolver(), MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projectionVideo, "", null, MediaStore.Video.Media.DATE_TAKEN + " DESC"); + if (cursor != null) { + int imageIdColumn = cursor.getColumnIndex(MediaStore.Video.Media._ID); + int bucketIdColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID); + int bucketNameColumn = cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME); + int dataColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATA); + int dateColumn = cursor.getColumnIndex(MediaStore.Video.Media.DATE_TAKEN); - while (cursor.moveToNext()) { - int imageId = cursor.getInt(imageIdColumn); - int bucketId = cursor.getInt(bucketIdColumn); - String bucketName = cursor.getString(bucketNameColumn); - String path = cursor.getString(dataColumn); - long dateTaken = cursor.getLong(dateColumn); + while (cursor.moveToNext()) { + int imageId = cursor.getInt(imageIdColumn); + int bucketId = cursor.getInt(bucketIdColumn); + String bucketName = cursor.getString(bucketNameColumn); + String path = cursor.getString(dataColumn); + long dateTaken = cursor.getLong(dateColumn); - if (path == null || path.length() == 0) { - continue; - } - - PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, 0, true); - - if (allVideosAlbum == null) { - allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideo", R.string.AllVideo), photoEntry, true); - videoAlbumsSorted.add(0, allVideosAlbum); - } - if (allVideosAlbum != null) { - allVideosAlbum.addPhoto(photoEntry); - } - - AlbumEntry albumEntry = albums.get(bucketId); - if (albumEntry == null) { - albumEntry = new AlbumEntry(bucketId, bucketName, photoEntry, true); - albums.put(bucketId, albumEntry); - if (cameraAlbumVideoId == null && cameraFolder != null && path != null && path.startsWith(cameraFolder)) { - videoAlbumsSorted.add(0, albumEntry); - cameraAlbumVideoId = bucketId; - } else { - videoAlbumsSorted.add(albumEntry); + if (path == null || path.length() == 0) { + continue; } - } - albumEntry.addPhoto(photoEntry); + PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, 0, true); + + if (allVideosAlbum == null) { + allVideosAlbum = new AlbumEntry(0, LocaleController.getString("AllVideo", R.string.AllVideo), photoEntry, true); + videoAlbumsSorted.add(0, allVideosAlbum); + } + if (allVideosAlbum != null) { + allVideosAlbum.addPhoto(photoEntry); + } + + AlbumEntry albumEntry = albums.get(bucketId); + if (albumEntry == null) { + albumEntry = new AlbumEntry(bucketId, bucketName, photoEntry, true); + albums.put(bucketId, albumEntry); + if (cameraAlbumVideoId == null && cameraFolder != null && path != null && path.startsWith(cameraFolder)) { + videoAlbumsSorted.add(0, albumEntry); + cameraAlbumVideoId = bucketId; + } else { + videoAlbumsSorted.add(albumEntry); + } + } + + albumEntry.addPhoto(photoEntry); + } } } } catch (Throwable e) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java index 3789758c8..ac218a10b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageKeyData.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 90a1ad977..b969b209f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -23,6 +23,7 @@ import android.text.util.Linkify; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.TypefaceSpan; +import org.telegram.ui.Components.URLSpanBotCommand; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.URLSpanNoUnderlineBold; import org.telegram.ui.Components.URLSpanReplacement; @@ -420,7 +421,7 @@ public class MessageObject { int dateYear = rightNow.get(Calendar.YEAR); int dateMonth = rightNow.get(Calendar.MONTH); dateKey = String.format("%d_%02d_%02d", dateYear, dateMonth, dateDay); - if (contentType == 1 || contentType == 2 || contentType == 0) { + if (contentType == 1 || contentType == 2 || contentType == 0 || contentType == 8) { monthKey = String.format("%d_%02d", dateYear, dateMonth); } @@ -524,6 +525,23 @@ public class MessageObject { return source; } + public String getExtension() { + String fileName = getFileName(); + int idx = fileName.lastIndexOf("."); + String ext = null; + if (idx != -1) { + ext = fileName.substring(idx + 1); + } + if (ext == null || ext.length() == 0) { + ext = messageOwner.media.document.mime_type; + } + if (ext == null) { + ext = ""; + } + ext = ext.toUpperCase(); + return ext; + } + public String getFileName() { if (messageOwner.media instanceof TLRPC.TL_messageMediaVideo) { return FileLoader.getAttachFileName(messageOwner.media.video); @@ -623,7 +641,11 @@ public class MessageObject { if (messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageOwner.media.webpage instanceof TLRPC.TL_webPage && messageOwner.media.webpage.description != null) { linkDescription = Spannable.Factory.getInstance().newSpannable(messageOwner.media.webpage.description); if (containsUrls(linkDescription)) { - Linkify.addLinks((Spannable) linkDescription, Linkify.WEB_URLS); + try { + Linkify.addLinks((Spannable) linkDescription, Linkify.WEB_URLS); + } catch (Exception e) { + FileLog.e("tmessages", e); + } } } } @@ -657,7 +679,12 @@ public class MessageObject { if (charSequence.charAt(start) != '@' && charSequence.charAt(start) != '#' && charSequence.charAt(start) != '/') { start++; } - URLSpanNoUnderline url = new URLSpanNoUnderline(charSequence.subSequence(start, end).toString()); + URLSpanNoUnderline url; + if (charSequence.charAt(start) == '/') { + url = new URLSpanBotCommand(charSequence.subSequence(start, end).toString()); + } else { + url = new URLSpanNoUnderline(charSequence.subSequence(start, end).toString()); + } ((Spannable) charSequence).setSpan(url, start, end, 0); } } catch (Exception e) { @@ -732,7 +759,9 @@ public class MessageObject { spannable.setSpan(new TypefaceSpan(Typeface.MONOSPACE), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if (!useManualParse) { String url = messageOwner.message.substring(entity.offset, entity.offset + entity.length); - if (entity instanceof TLRPC.TL_messageEntityBotCommand || entity instanceof TLRPC.TL_messageEntityHashtag || entity instanceof TLRPC.TL_messageEntityMention) { + if (entity instanceof TLRPC.TL_messageEntityBotCommand) { + spannable.setSpan(new URLSpanBotCommand(url), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (entity instanceof TLRPC.TL_messageEntityHashtag || entity instanceof TLRPC.TL_messageEntityMention) { spannable.setSpan(new URLSpanNoUnderline(url), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else if (entity instanceof TLRPC.TL_messageEntityEmail) { spannable.setSpan(new URLSpanReplacement("mailto:" + url), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -815,6 +844,14 @@ public class MessageObject { FileLog.e("tmessages", e); continue; } + if (a == blocksCount - 1) { + currentBlockLinesCount = Math.max(currentBlockLinesCount, block.textLayout.getLineCount()); + try { + textHeight = Math.max(textHeight, (int) (block.textYOffset + block.textLayout.getHeight())); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } } textLayoutBlocks.add(block); @@ -849,7 +886,7 @@ public class MessageObject { if (currentBlockLinesCount > 1) { float textRealMaxWidth = 0, textRealMaxWidthWithLeft = 0, lineWidth, lineLeft; - for (int n = 0; n < currentBlockLinesCount; ++n) { + for (int n = 0; n < currentBlockLinesCount; n++) { try { lineWidth = block.textLayout.getLineWidth(n); } catch (Exception e) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 0e66ce9b6..1b6907c1b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -47,6 +47,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter private ConcurrentHashMap users = new ConcurrentHashMap<>(100, 1.0f, 2); private ConcurrentHashMap usersByUsernames = new ConcurrentHashMap<>(100, 1.0f, 2); + private ArrayList joiningToChannels = new ArrayList<>(); + private HashMap exportedChats = new HashMap<>(); public ArrayList dialogs = new ArrayList<>(); @@ -104,7 +106,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter public boolean loadingDialogs = false; public boolean dialogsEndReached = false; public boolean gettingDifference = false; - public boolean gettingDifferenceAgain = false; public boolean updatingState = false; public boolean firstGettingTask = false; public boolean registeringForPush = false; @@ -415,10 +416,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } else if (id == NotificationCenter.messageReceivedByServer) { Integer msgId = (Integer) args[0]; + Integer newMsgId = (Integer) args[1]; Long did = (Long) args[3]; MessageObject obj = dialogMessage.get(did); if (obj != null && obj.getId() == msgId) { - Integer newMsgId = (Integer) args[1]; obj.messageOwner.id = newMsgId; obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; TLRPC.Dialog dialog = dialogs_dict.get(did); @@ -429,6 +430,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter } NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); } + obj = dialogMessagesByIds.remove(msgId); + if (obj != null) { + dialogMessagesByIds.put(newMsgId, obj); + } } } @@ -443,6 +448,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogs_dict.clear(); exportedChats.clear(); dialogs.clear(); + joiningToChannels.clear(); channelViewsToSend.clear(); channelViewsToReload.clear(); dialogsServerOnly.clear(); @@ -479,7 +485,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter loadingDialogs = false; dialogsEndReached = false; gettingDifference = false; - gettingDifferenceAgain = false; loadingBlockedUsers = false; firstGettingTask = false; updatingState = false; @@ -493,6 +498,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter Utilities.stageQueue.postRunnable(new Runnable() { @Override public void run() { + ConnectionsManager.getInstance().setIsUpdating(false); updatesQueueChannels.clear(); updatesStartWaitTimeChannels.clear(); gettingDifferenceChannels.clear(); @@ -784,6 +790,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter } private void reloadMessages(final ArrayList mids, final long dialog_id) { + if (mids.isEmpty()) { + return; + } TLObject request; final ArrayList result = new ArrayList<>(); TLRPC.Chat chat = ChatObject.getChatByDialog(dialog_id); @@ -1659,10 +1668,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } if (label.length() != 0) { - if (arr.size() > 2) { - newPrintingStrings.put(key, String.format("%s %s", label, LocaleController.formatPluralString("AndMoreTyping", arr.size() - 2))); + if (count == 1) { + newPrintingStrings.put(key, String.format("%s %s", label, LocaleController.getString("IsTyping", R.string.IsTyping))); } else { - newPrintingStrings.put(key, String.format("%s %s", label, LocaleController.getString("AreTyping", R.string.AreTyping))); + if (arr.size() > 2) { + newPrintingStrings.put(key, String.format("%s %s", label, LocaleController.formatPluralString("AndMoreTyping", arr.size() - 2))); + } else { + newPrintingStrings.put(key, String.format("%s %s", label, LocaleController.getString("AreTyping", R.string.AreTyping))); + } } newPrintingStringsTypes.put(key, 0); } @@ -1913,15 +1926,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } - public void loadDialogs(final int offset, final int serverOffset, final int count, boolean fromCache) { + public void loadDialogs(final int offset, final int serverOffset, final int cacheOffset, final int count, boolean fromCache) { if (loadingDialogs) { return; } loadingDialogs = true; NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - + FileLog.e("tmessages", "load offset = " + offset + " serverOffset = " + serverOffset + " count = " + count + "cache = " + fromCache); if (fromCache) { - MessagesStorage.getInstance().getDialogs(nextDialogsCacheOffset, offset, serverOffset, count); + MessagesStorage.getInstance().getDialogs(cacheOffset == 0 ? 0 : nextDialogsCacheOffset, offset, serverOffset, count); } else { TLRPC.TL_messages_getDialogs req = new TLRPC.TL_messages_getDialogs(); req.offset = serverOffset; @@ -1931,17 +1944,18 @@ public class MessagesController implements NotificationCenter.NotificationCenter public void run(TLObject response, TLRPC.TL_error error) { if (error == null) { final TLRPC.messages_Dialogs dialogsRes = (TLRPC.messages_Dialogs) response; - processLoadedDialogs(dialogsRes, null, 0, offset, serverOffset, count, false, false); + processLoadedDialogs(dialogsRes, null, 0, offset, serverOffset, count, false, false, false); } } }); } } - public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, final ArrayList encChats, final int cacheOffset, final int offset, final int serverOffset, final int count, final boolean isCache, final boolean resetEnd) { + public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, final ArrayList encChats, final int cacheOffset, final int offset, final int serverOffset, final int count, final boolean isCache, final boolean resetEnd, final boolean isChannels) { Utilities.stageQueue.postRunnable(new Runnable() { @Override public void run() { + FileLog.e("tmessages", "loaded from " + isCache + " count " + dialogsRes.dialogs.size()); if (isCache && dialogsRes.dialogs.size() == 0) { AndroidUtilities.runOnUIThread(new Runnable() { @Override @@ -1952,7 +1966,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogsEndReached = false; } NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - loadDialogs(offset, serverOffset, count, false); + loadDialogs(offset, serverOffset, 0, count, false); } }); return; @@ -1970,7 +1984,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter UserConfig.channelsLoaded = true; UserConfig.saveConfig(false); final TLRPC.messages_Dialogs dialogsRes = (TLRPC.messages_Dialogs) response; - processLoadedDialogs(dialogsRes, null, 0, 0, 0, 100, false, false); + processLoadedDialogs(dialogsRes, null, 0, 0, 0, 100, false, false, true); } } }); @@ -2072,12 +2086,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } loadingDialogs = false; + boolean added = false; for (HashMap.Entry pair : new_dialogs_dict.entrySet()) { Long key = pair.getKey(); TLRPC.Dialog value = pair.getValue(); TLRPC.Dialog currentDialog = dialogs_dict.get(key); if (currentDialog == null) { + added = true; dialogs_dict.put(key, value); MessageObject messageObject = new_dialogMessage.get(value.id); dialogMessage.put(key, messageObject); @@ -2143,9 +2159,15 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - dialogsEndReached = (dialogsRes.dialogs.size() == 0 || dialogsRes.dialogs.size() != count) && !isCache; + if (!isChannels) { + dialogsEndReached = (dialogsRes.dialogs.size() == 0 || dialogsRes.dialogs.size() != count) && !isCache; + } NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); generateUpdateMessage(); + + if (!added && isCache) { + loadDialogs(offset, serverOffset, 0, count, false); + } } }); } @@ -2803,9 +2825,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (botHash == null) { if (isChannel) { if (inputUser instanceof TLRPC.TL_inputUserSelf) { + if (joiningToChannels.contains(chat_id)) { + return; + } TLRPC.TL_channels_joinChannel req = new TLRPC.TL_channels_joinChannel(); req.channel = getInputChannel(chat_id); request = req; + joiningToChannels.add(chat_id); } else { TLRPC.TL_channels_inviteToChannel req = new TLRPC.TL_channels_inviteToChannel(); req.channel = getInputChannel(chat_id); @@ -2831,6 +2857,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter ConnectionsManager.getInstance().sendRequest(request, new RequestDelegate() { @Override public void run(TLObject response, final TLRPC.TL_error error) { + if (isChannel && inputUser instanceof TLRPC.TL_inputUserSelf) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + joiningToChannels.remove((Integer) chat_id); + } + }); + } if (error != null) { AndroidUtilities.runOnUIThread(new Runnable() { @Override @@ -3272,6 +3306,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter Integer channelPts = channelsPts.get(channelId); if (updatesQueue.isEmpty() || channelPts == null) { updatesQueueChannels.remove(channelId); + return; } Collections.sort(updatesQueue, new Comparator() { @Override @@ -3453,6 +3488,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter for (TLRPC.User user : res.users) { usersDict.put(user.id, user); } + final TLRPC.Chat channel = !res.chats.isEmpty() ? res.chats.get(0) : null; final ArrayList msgUpdates = new ArrayList<>(); if (!res.other_updates.isEmpty()) { @@ -3526,9 +3562,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } + TLRPC.Dialog dialog = dialogs_dict.get((long) -channelId); MessageObject obj = new MessageObject(message, usersDict, true); + if (channel != null && (channel.flags & TLRPC.CHAT_FLAG_USER_LEFT) != 0 || dialog != null && dialog.read_inbox_max_id >= obj.getId()) { + obj.setIsRead(); + obj.setContentIsRead(); + } - if (!obj.isOut() && obj.isUnread()) { + if (!obj.isOut() && obj.isContentUnread()) { pushMessages.add(obj); } @@ -3580,6 +3621,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter for (int a = 0; a < res.messages.size(); a++) { res.messages.get(a).dialog_id = -channelId; } + MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, true, true); MessagesStorage.getInstance().overwriteChannel(channelId, (TLRPC.TL_updates_channelDifferenceTooLong) res); } gettingDifferenceChannels.remove(channelId); @@ -3642,12 +3684,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { @Override public void run(TLObject response, TLRPC.TL_error error) { - gettingDifferenceAgain = false; if (error == null) { final TLRPC.updates_Difference res = (TLRPC.updates_Difference) response; if (res instanceof TLRPC.TL_updates_differenceSlice) { - gettingDifferenceAgain = true; getDifference(res.intermediate_state.pts, res.intermediate_state.date, res.intermediate_state.qts, true); } @@ -4442,12 +4482,20 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } } + boolean allowNotify = true; if (checkForUsers) { if (message.to_id.chat_id != 0 && chatsDict.get(message.to_id.chat_id) == null && getChat(message.to_id.chat_id) == null) { return false; } - if (message.to_id.channel_id != 0 && chatsDict.get(message.to_id.channel_id) == null && getChat(message.to_id.channel_id) == null) { - return false; + if (message.to_id.channel_id != 0) { + TLRPC.Chat channel = chatsDict.get(message.to_id.channel_id); + if (channel == null) { + channel = getChat(message.to_id.channel_id); + } + if (channel == null) { + return false; + } + allowNotify = (channel.flags & TLRPC.CHAT_FLAG_USER_LEFT) == 0; } if (message.from_id > 0) { TLRPC.User user = getUser(message.from_id); @@ -4463,6 +4511,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter messagesArr.add(message); ImageLoader.saveMessageThumbs(message); MessageObject obj = new MessageObject(message, usersDict, true); + if (!allowNotify) { + obj.setIsRead(); + obj.setContentIsRead(); + } if (obj.type == 11) { interfaceUpdateMask |= UPDATE_MASK_CHAT_AVATAR; } else if (obj.type == 10) { @@ -4484,7 +4536,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter messages.put(message.dialog_id, arr); } arr.add(obj); - if (!obj.isOut() && (obj.isUnread() && message.to_id.channel_id == 0 || obj.isContentUnread())) { + if (allowNotify && (!obj.isOut() && (obj.isUnread() && message.to_id.channel_id == 0 || obj.isContentUnread()))) { pushMessages.add(obj); } } else if (update instanceof TLRPC.TL_updateReadMessagesContents) { @@ -4579,7 +4631,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter interfaceUpdateMask |= UPDATE_MASK_PHONE; updatesOnMainThread.add(update); } else if (update instanceof TLRPC.TL_updateContactRegistered) { - if (enableJoined && usersDict.containsKey(update.user_id)) { + if (enableJoined && usersDict.containsKey(update.user_id) && !MessagesStorage.getInstance().isDialogHasMessages(update.user_id)) { TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService(); newMessage.action = new TLRPC.TL_messageActionUserJoined(); newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); @@ -5243,23 +5295,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter changed = true; } } else { - boolean change = false; - if (dialog.top_message > 0 && lastMessage.getId() > 0 && lastMessage.getId() > dialog.top_message || - dialog.top_message < 0 && lastMessage.getId() < 0 && lastMessage.getId() < dialog.top_message) { - change = true; - } else { - MessageObject currentDialogMessage = dialogMessage.get(uid); - if (currentDialogMessage != null) { - if (currentDialogMessage.isSending() && lastMessage.isSending()) { - change = true; - } else if (dialog.last_message_date < lastMessage.messageOwner.date || dialog.last_message_date == lastMessage.messageOwner.date && lastMessage.isSending()) { - change = true; - } - } else { - change = true; - } - } - if (change) { + if ((dialog.top_message > 0 && lastMessage.getId() > 0 && lastMessage.getId() > dialog.top_message) || + (dialog.top_message < 0 && lastMessage.getId() < 0 && lastMessage.getId() < dialog.top_message) || + !dialogMessage.containsKey(uid) || dialog.top_message < 0 || dialog.last_message_date <= lastMessage.messageOwner.date) { dialog.top_message = lastMessage.getId(); if (!isBroadcast) { dialog.last_message_date = lastMessage.messageOwner.date; @@ -5289,7 +5327,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } }); - for (TLRPC.Dialog d : dialogs) { + for (int a = 0; a < dialogs.size(); a++) { + TLRPC.Dialog d = dialogs.get(a); int high_id = (int) (d.id >> 32); if ((int) d.id != 0 && high_id != 1) { dialogsServerOnly.add(d); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index cf6b51926..b30c3aba8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -80,7 +80,7 @@ public class MessagesStorage { } public void openDatabase() { - cacheFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "cache4.db"); + cacheFile = new File(ApplicationLoader.getFilesDirFixed(), "cache4.db"); boolean createTable = false; //cacheFile.delete(); @@ -164,7 +164,7 @@ public class MessagesStorage { database.executeFast("CREATE TABLE bot_info(uid INTEGER PRIMARY KEY, info BLOB)").stepThis().dispose(); //version - database.executeFast("PRAGMA user_version = 23").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 25").stepThis().dispose(); //database.executeFast("CREATE TABLE secret_holes(uid INTEGER, seq_in INTEGER, seq_out INTEGER, data BLOB, PRIMARY KEY (uid, seq_in, seq_out));").stepThis().dispose(); //database.executeFast("CREATE TABLE attach_data(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose(); @@ -198,7 +198,7 @@ public class MessagesStorage { } } int version = database.executeInt("PRAGMA user_version"); - if (version < 23) { + if (version < 25) { updateDbToLastVersion(version); } } @@ -460,7 +460,17 @@ public class MessagesStorage { database.executeFast("CREATE TABLE IF NOT EXISTS media_holes_v2(uid INTEGER, type INTEGER, start INTEGER, end INTEGER, PRIMARY KEY(uid, type, start));").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_end_media_holes_v2 ON media_holes_v2(uid, type, end);").stepThis().dispose(); database.executeFast("PRAGMA user_version = 23").stepThis().dispose(); - //version = 23; + version = 23; + } + if (version == 23) { + database.executeFast("DELETE FROM sent_files_v2 WHERE 1").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 24").stepThis().dispose(); + version = 24; + } + if (version == 24) { + database.executeFast("DELETE FROM media_holes_v2 WHERE uid != 0 AND type >= 0 AND start IN (0, 1)").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 25").stepThis().dispose(); + //version = 25; } } catch (Exception e) { FileLog.e("tmessages", e); @@ -690,6 +700,21 @@ public class MessagesStorage { if (!chatIds.isEmpty()) { getChatsInternal(TextUtils.join(",", chatIds), chats); + for (int a = 0; a < chats.size(); a++) { + TLRPC.Chat chat = chats.get(a); + if (chat != null && (chat.flags & TLRPC.CHAT_FLAG_USER_LEFT) != 0) { + chats.remove(a); + a--; + pushDialogs.remove((long) -chat.id); + for (int b = 0; b < messages.size(); b++) { + TLRPC.Message message = messages.get(b); + if (message.dialog_id == -chat.id) { + messages.remove(b); + b--; + } + } + } + } } } Collections.reverse(messages); @@ -1557,7 +1582,7 @@ public class MessagesStorage { int lower_id = (int) dialog_id; if (lower_id != 0) { - state = database.executeFast("UPDATE messages SET read_state = read_state | 1 WHERE uid = ? AND mid > 0 AND mid <= ? AND read_state IN(0,2) AND out = 0"); + state = database.executeFast("UPDATE messages SET read_state = read_state | 1 WHERE uid = ? AND mid <= ? AND read_state IN(0,2) AND out = 0"); state.requery(); state.bindLong(1, dialog_id); state.bindLong(2, max_id); @@ -1572,9 +1597,10 @@ public class MessagesStorage { state.dispose(); } - state = database.executeFast("UPDATE dialogs SET unread_count = 0 WHERE did = ?"); + state = database.executeFast("UPDATE dialogs SET unread_count = 0, inbox_max = ? WHERE did = ?"); state.requery(); - state.bindLong(1, dialog_id); + state.bindLong(1, max_id); + state.bindLong(2, dialog_id); state.step(); state.dispose(); @@ -2213,7 +2239,7 @@ public class MessagesStorage { } } message.send_state = cursor.intValue(2); - if (message.to_id.channel_id == 0 && !MessageObject.isUnread(message) && lower_id != 0 || message.id > 0) { + if (message.id > 0 && message.send_state != 0) { message.send_state = 0; } if (lower_id == 0 && !cursor.isNull(5)) { @@ -2605,6 +2631,31 @@ public class MessagesStorage { }); } + public boolean isDialogHasMessages(final long did) { + final Semaphore semaphore = new Semaphore(0); + final boolean result[] = new boolean[1]; + storageQueue.postRunnable(new Runnable() { + @Override + public void run() { + try { + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid FROM messages WHERE uid = %d LIMIT 1", did)); + result[0] = cursor.next(); + cursor.dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } finally { + semaphore.release(); + } + } + }); + try { + semaphore.acquire(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + return result[0]; + } + public void getEncryptedChat(final int chat_id, final Semaphore semaphore, final ArrayList result) { if (semaphore == null || result == null) { return; @@ -3310,12 +3361,12 @@ public class MessagesStorage { TLRPC.Message lastMessage; if (message.to_id.channel_id == 0 || MessageObject.isImportant(message)) { lastMessage = messagesMap.get(message.dialog_id); - if (lastMessage == null || message.date > lastMessage.date) { + if (lastMessage == null || message.date > lastMessage.date || message.id > 0 && lastMessage.id > 0 && message.id > lastMessage.id || message.id < 0 && lastMessage.id < 0 && message.id < lastMessage.id) { messagesMap.put(message.dialog_id, message); } } else if (message.to_id.channel_id != 0) { - lastMessage = messagesMap.get(message.dialog_id); - if (lastMessage == null || message.date > lastMessage.date) { + lastMessage = messagesMapNotImportant.get(message.dialog_id); + if (lastMessage == null || message.date > lastMessage.date || message.id > 0 && lastMessage.id > 0 && message.id > lastMessage.id || message.id < 0 && lastMessage.id < 0 && message.id < lastMessage.id) { messagesMapNotImportant.put(message.dialog_id, message); } } @@ -4112,7 +4163,7 @@ public class MessagesStorage { ArrayList usersToLoad = new ArrayList<>(); ArrayList chatsToLoad = new ArrayList<>(); ArrayList encryptedToLoad = new ArrayList<>(); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, m.date, d.last_mid_i, d.unread_count_i, d.pts FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid WHERE d.did IN(%s)", ids)); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, m.date, d.last_mid_i, d.unread_count_i, d.pts, d.inbox_max FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid WHERE d.did IN(%s)", ids)); while (cursor.next()) { TLRPC.Dialog dialog; if (channelId == 0) { @@ -4122,6 +4173,7 @@ public class MessagesStorage { } dialog.id = cursor.longValue(0); dialog.top_message = cursor.intValue(1); + dialog.read_inbox_max_id = cursor.intValue(13); dialog.unread_count = cursor.intValue(2); dialog.last_message_date = cursor.intValue(3); dialog.pts = cursor.intValue(11); @@ -4517,9 +4569,9 @@ public class MessagesStorage { if (important != 0) { closeHolesInTable("messages_imp_holes", dialog_id, minId, max_id); } - } else if (load_type == 1 || messages.collapsed.isEmpty()) { + } else if (load_type == 1) { int maxId = messages.messages.get(0).id; - if (important != 2) { + if (important != 2 || messages.collapsed.isEmpty()) { closeHolesInTable("messages_holes", dialog_id, max_id, maxId); closeHolesInMedia(dialog_id, max_id, maxId, -1); } @@ -4634,7 +4686,7 @@ public class MessagesStorage { } data.reuse(); - if (message.reply_markup != null && ((message.reply_markup.flags & 4) == 0 || (message.flags & 16) != 0)) { + if (load_type == 0 && message.reply_markup != null && ((message.reply_markup.flags & 4) == 0 || (message.flags & 16) != 0)) { if (botKeyboard == null || botKeyboard.id < message.id) { botKeyboard = message; } @@ -4724,7 +4776,7 @@ public class MessagesStorage { usersToLoad.add(UserConfig.getClientUserId()); ArrayList chatsToLoad = new ArrayList<>(); ArrayList encryptedToLoad = new ArrayList<>(); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, s.flags, m.date, d.last_mid_i, d.unread_count_i, d.pts FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid LEFT JOIN dialog_settings as s ON d.did = s.did ORDER BY d.date DESC LIMIT %d,%d", cacheOffset, count)); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, s.flags, m.date, d.last_mid_i, d.unread_count_i, d.pts, d.inbox_max FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid LEFT JOIN dialog_settings as s ON d.did = s.did ORDER BY d.date DESC LIMIT %d,%d", cacheOffset, count)); while (cursor.next()) { TLRPC.Dialog dialog; int pts = cursor.intValue(12); @@ -4739,6 +4791,7 @@ public class MessagesStorage { dialog.unread_count = cursor.intValue(2); dialog.last_message_date = cursor.intValue(3); dialog.pts = pts; + dialog.read_inbox_max_id = cursor.intValue(13); dialog.top_not_important_message = cursor.intValue(10); dialog.unread_not_important_count = cursor.intValue(11); long flags = cursor.longValue(8); @@ -4829,14 +4882,14 @@ public class MessagesStorage { if (!usersToLoad.isEmpty()) { getUsersInternal(TextUtils.join(",", usersToLoad), dialogs.users); } - MessagesController.getInstance().processLoadedDialogs(dialogs, encryptedChats, cacheOffset, offset, serverOffset, count, true, false); + MessagesController.getInstance().processLoadedDialogs(dialogs, encryptedChats, cacheOffset, offset, serverOffset, count, true, false, false); } catch (Exception e) { dialogs.dialogs.clear(); dialogs.users.clear(); dialogs.chats.clear(); encryptedChats.clear(); FileLog.e("tmessages", e); - MessagesController.getInstance().processLoadedDialogs(dialogs, encryptedChats, 0, 0, 0, 100, true, true); + MessagesController.getInstance().processLoadedDialogs(dialogs, encryptedChats, 0, 0, 0, 100, true, true, false); } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerReceiver.java index 3f6314f68..cb910e5a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerReceiver.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -60,7 +60,7 @@ public class MusicPlayerReceiver extends BroadcastReceiver { } else if (intent.getAction().equals(MusicPlayerService.NOTIFY_NEXT)) { MediaController.getInstance().playNextMessage(); } else if (intent.getAction().equals(MusicPlayerService.NOTIFY_CLOSE)) { - MediaController.getInstance().clenupPlayer(true, true); + MediaController.getInstance().cleanupPlayer(true, true); } else if (intent.getAction().equals(MusicPlayerService.NOTIFY_PREVIOUS)) { MediaController.getInstance().playPreviousMessage(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java index 2aca07dd3..a6717ee0a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -246,6 +246,7 @@ public class MusicPlayerService extends Service implements AudioManager.OnAudioF metadataEditor.clear(); metadataEditor.apply(); audioManager.unregisterRemoteControlClient(remoteControlClient); + audioManager.abandonAudioFocus(this); } try { TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java index b24812c58..c14b9e3a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -23,7 +23,7 @@ import java.util.zip.ZipFile; public class NativeLoader { - private final static int LIB_VERSION = 12; + private final static int LIB_VERSION = 14; private final static String LIB_NAME = "tmessages." + LIB_VERSION; private final static String LIB_SO_NAME = "lib" + LIB_NAME + ".so"; private final static String LOCALE_LIB_SO_NAME = "lib" + LIB_NAME + "loc.so"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 79176988b..c78f8fa5a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationRepeat.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationRepeat.java index 0b2668d94..78dd91d05 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationRepeat.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationRepeat.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index daee1a18c..d0e3747f9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -51,7 +51,7 @@ public class NotificationsController { private DispatchQueue notificationsQueue = new DispatchQueue("notificationsQueue"); private ArrayList pushMessages = new ArrayList<>(); private ArrayList delayedPushMessages = new ArrayList<>(); - private HashMap pushMessagesDict = new HashMap<>(); + private HashMap pushMessagesDict = new HashMap<>(); private HashMap smartNotificationsDialogs = new HashMap<>(); private NotificationManagerCompat notificationManager = null; private HashMap pushDialogs = new HashMap<>(); @@ -141,38 +141,458 @@ public class NotificationsController { } public void cleanup() { - openned_dialog_id = 0; - total_unread_count = 0; - personal_count = 0; - pushMessages.clear(); - pushMessagesDict.clear(); - pushDialogs.clear(); popupMessages.clear(); - wearNotificationsIds.clear(); - autoNotificationsIds.clear(); - delayedPushMessages.clear(); - notifyCheck = false; - lastBadgeCount = 0; - try { - if (notificationDelayWakelock.isHeld()) { - notificationDelayWakelock.release(); + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + openned_dialog_id = 0; + total_unread_count = 0; + personal_count = 0; + pushMessages.clear(); + pushMessagesDict.clear(); + pushDialogs.clear(); + wearNotificationsIds.clear(); + autoNotificationsIds.clear(); + delayedPushMessages.clear(); + notifyCheck = false; + lastBadgeCount = 0; + try { + if (notificationDelayWakelock.isHeld()) { + notificationDelayWakelock.release(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + setBadge(0); + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + editor.clear(); + editor.commit(); } - } catch (Exception e) { - FileLog.e("tmessages", e); - } - setBadge(0); - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.clear(); - editor.commit(); + }); } public void setInChatSoundEnabled(boolean value) { inChatSoundEnabled = value; } - public void setOpennedDialogId(long dialog_id) { - openned_dialog_id = dialog_id; + public void setOpennedDialogId(final long dialog_id) { + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + openned_dialog_id = dialog_id; + } + }); + } + + public void setLastOnlineFromOtherDevice(final int time) { + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + FileLog.e("tmessages", "set last online from other device = " + time); + lastOnlineFromOtherDevice = time; + } + }); + } + + public void processReadMessages(final SparseArray inbox, final long dialog_id, final int max_date, final int max_id, final boolean isPopup) { + final ArrayList popupArray = popupMessages.isEmpty() ? null : new ArrayList<>(popupMessages); + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + int oldCount = popupArray != null ? popupArray.size() : 0; + if (inbox != null) { + for (int b = 0; b < inbox.size(); b++) { + int key = inbox.keyAt(b); + long messageId = inbox.get(key); + for (int a = 0; a < pushMessages.size(); a++) { + MessageObject messageObject = pushMessages.get(a); + if (messageObject.getDialogId() == key && messageObject.getId() <= (int) messageId) { + if (isPersonalMessage(messageObject)) { + personal_count--; + } + if (popupArray != null) { + popupArray.remove(messageObject); + } + long mid = messageObject.messageOwner.id; + if (messageObject.messageOwner.to_id.channel_id != 0) { + mid |= ((long) messageObject.messageOwner.to_id.channel_id) << 32; + } + pushMessagesDict.remove(mid); + delayedPushMessages.remove(messageObject); + pushMessages.remove(a); + a--; + } + } + } + if (popupArray != null && pushMessages.isEmpty() && !popupArray.isEmpty()) { + popupArray.clear(); + } + } + if (dialog_id != 0 && (max_id != 0 || max_date != 0)) { + for (int a = 0; a < pushMessages.size(); a++) { + MessageObject messageObject = pushMessages.get(a); + if (messageObject.getDialogId() == dialog_id) { + boolean remove = false; + if (max_date != 0) { + if (messageObject.messageOwner.date <= max_date) { + remove = true; + } + } else { + if (!isPopup) { + if (messageObject.getId() <= max_id || max_id < 0) { + remove = true; + } + } else { + if (messageObject.getId() == max_id || max_id < 0) { + remove = true; + } + } + } + if (remove) { + if (isPersonalMessage(messageObject)) { + personal_count--; + } + pushMessages.remove(a); + delayedPushMessages.remove(messageObject); + if (popupArray != null) { + popupArray.remove(messageObject); + } + long mid = messageObject.messageOwner.id; + if (messageObject.messageOwner.to_id.channel_id != 0) { + mid |= ((long) messageObject.messageOwner.to_id.channel_id) << 32; + } + pushMessagesDict.remove(mid); + a--; + } + } + } + if (popupArray != null && pushMessages.isEmpty() && !popupArray.isEmpty()) { + popupArray.clear(); + } + } + if (popupArray != null && oldCount != popupArray.size()) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + popupMessages = popupArray; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.pushMessagesUpdated); + } + }); + } + } + }); + } + + public void processNewMessages(final ArrayList messageObjects, final boolean isLast) { + if (messageObjects.isEmpty()) { + return; + } + final ArrayList popupArray = new ArrayList<>(popupMessages); + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + boolean added = false; + + int oldCount = popupArray.size(); + HashMap settingsCache = new HashMap<>(); + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); + int popup = 0; + + for (int a = 0; a < messageObjects.size(); a++) { + MessageObject messageObject = messageObjects.get(a); + long mid = messageObject.messageOwner.id; + if (messageObject.messageOwner.to_id.channel_id != 0) { + mid |= ((long) messageObject.messageOwner.to_id.channel_id) << 32; + } + if (pushMessagesDict.containsKey(mid)) { + continue; + } + long dialog_id = messageObject.getDialogId(); + long original_dialog_id = dialog_id; + if (dialog_id == openned_dialog_id && ApplicationLoader.isScreenOn) { + playInChatSound(); + continue; + } + if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) { + dialog_id = messageObject.messageOwner.from_id; + } + if (isPersonalMessage(messageObject)) { + personal_count++; + } + added = true; + + Boolean value = settingsCache.get(dialog_id); + boolean isChat = (int)dialog_id < 0; + popup = (int)dialog_id == 0 ? 0 : preferences.getInt(isChat ? "popupGroup" : "popupAll", 0); + if (value == null) { + int notifyOverride = getNotifyOverride(preferences, dialog_id); + value = !(notifyOverride == 2 || (!preferences.getBoolean("EnableAll", true) || isChat && !preferences.getBoolean("EnableGroup", true)) && notifyOverride == 0); + settingsCache.put(dialog_id, value); + } + if (value) { + if (popup != 0) { + popupArray.add(0, messageObject); + } + delayedPushMessages.add(messageObject); + pushMessages.add(0, messageObject); + pushMessagesDict.put(mid, messageObject); + if (original_dialog_id != dialog_id) { + pushDialogsOverrideMention.put(original_dialog_id, 1); + } + } + } + + if (added) { + notifyCheck = isLast; + } + + if (!popupArray.isEmpty() && oldCount != popupArray.size() && !AndroidUtilities.needShowPasscode(false)) { + final int popupFinal = popup; + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + popupMessages = popupArray; + if (ApplicationLoader.mainInterfacePaused || !ApplicationLoader.isScreenOn && !UserConfig.isWaitingForPasscodeEnter) { + MessageObject messageObject = messageObjects.get(0); + if (popupFinal == 3 || popupFinal == 1 && ApplicationLoader.isScreenOn || popupFinal == 2 && !ApplicationLoader.isScreenOn) { + Intent popupIntent = new Intent(ApplicationLoader.applicationContext, PopupNotificationActivity.class); + popupIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_FROM_BACKGROUND); + ApplicationLoader.applicationContext.startActivity(popupIntent); + } + } + } + }); + } + } + }); + } + + public void processDialogsUpdateRead(final HashMap dialogsToUpdate) { + final ArrayList popupArray = popupMessages.isEmpty() ? null : new ArrayList<>(popupMessages); + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + int old_unread_count = total_unread_count; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); + for (HashMap.Entry entry : dialogsToUpdate.entrySet()) { + long dialog_id = entry.getKey(); + + int notifyOverride = getNotifyOverride(preferences, dialog_id); + if (notifyCheck) { + Integer override = pushDialogsOverrideMention.get(dialog_id); + if (override != null && override == 1) { + pushDialogsOverrideMention.put(dialog_id, 0); + notifyOverride = 1; + } + } + boolean canAddValue = !(notifyOverride == 2 || (!preferences.getBoolean("EnableAll", true) || ((int)dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notifyOverride == 0); + + Integer currentCount = pushDialogs.get(dialog_id); + Integer newCount = entry.getValue(); + if (newCount == 0) { + smartNotificationsDialogs.remove(dialog_id); + } + + if (newCount < 0) { + if (currentCount == null) { + continue; + } + newCount = currentCount + newCount; + } + if (canAddValue || newCount == 0) { + if (currentCount != null) { + total_unread_count -= currentCount; + } + } + if (newCount == 0) { + pushDialogs.remove(dialog_id); + pushDialogsOverrideMention.remove(dialog_id); + for (int a = 0; a < pushMessages.size(); a++) { + MessageObject messageObject = pushMessages.get(a); + if (messageObject.getDialogId() == dialog_id) { + if (isPersonalMessage(messageObject)) { + personal_count--; + } + pushMessages.remove(a); + a--; + delayedPushMessages.remove(messageObject); + long mid = messageObject.messageOwner.id; + if (messageObject.messageOwner.to_id.channel_id != 0) { + mid |= ((long) messageObject.messageOwner.to_id.channel_id) << 32; + } + pushMessagesDict.remove(mid); + if (popupArray != null) { + popupArray.remove(messageObject); + } + } + } + if (popupArray != null && pushMessages.isEmpty() && !popupArray.isEmpty()) { + popupArray.clear(); + } + } else if (canAddValue) { + total_unread_count += newCount; + pushDialogs.put(dialog_id, newCount); + } + } + if (popupArray != null) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + popupMessages = popupArray; + } + }); + } + if (old_unread_count != total_unread_count) { + if (!notifyCheck) { + delayedPushMessages.clear(); + showOrUpdateNotification(notifyCheck); + } else { + scheduleNotificationDelay(lastOnlineFromOtherDevice > ConnectionsManager.getInstance().getCurrentTime()); + } + } + notifyCheck = false; + if (preferences.getBoolean("badgeNumber", true)) { + setBadge(total_unread_count); + } + } + }); + } + + public void processLoadedUnreadMessages(final HashMap dialogs, final ArrayList messages, final ArrayList users, final ArrayList chats, final ArrayList encryptedChats) { + MessagesController.getInstance().putUsers(users, true); + MessagesController.getInstance().putChats(chats, true); + MessagesController.getInstance().putEncryptedChats(encryptedChats, true); + + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + pushDialogs.clear(); + pushMessages.clear(); + pushMessagesDict.clear(); + total_unread_count = 0; + personal_count = 0; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); + HashMap settingsCache = new HashMap<>(); + + if (messages != null) { + for (TLRPC.Message message : messages) { + long mid = message.id; + if (message.to_id.channel_id != 0) { + mid |= ((long) message.to_id.channel_id) << 32; + } + if (pushMessagesDict.containsKey(mid)) { + continue; + } + MessageObject messageObject = new MessageObject(message, null, false); + if (isPersonalMessage(messageObject)) { + personal_count++; + } + long dialog_id = messageObject.getDialogId(); + long original_dialog_id = dialog_id; + if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) { + dialog_id = messageObject.messageOwner.from_id; + } + Boolean value = settingsCache.get(dialog_id); + if (value == null) { + int notifyOverride = getNotifyOverride(preferences, dialog_id); + value = !(notifyOverride == 2 || (!preferences.getBoolean("EnableAll", true) || ((int) dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notifyOverride == 0); + settingsCache.put(dialog_id, value); + } + if (!value || dialog_id == openned_dialog_id && ApplicationLoader.isScreenOn) { + continue; + } + pushMessagesDict.put(mid, messageObject); + pushMessages.add(0, messageObject); + if (original_dialog_id != dialog_id) { + pushDialogsOverrideMention.put(original_dialog_id, 1); + } + } + } + for (HashMap.Entry entry : dialogs.entrySet()) { + long dialog_id = entry.getKey(); + Boolean value = settingsCache.get(dialog_id); + if (value == null) { + int notifyOverride = getNotifyOverride(preferences, dialog_id); + Integer override = pushDialogsOverrideMention.get(dialog_id); + if (override != null && override == 1) { + pushDialogsOverrideMention.put(dialog_id, 0); + notifyOverride = 1; + } + value = !(notifyOverride == 2 || (!preferences.getBoolean("EnableAll", true) || ((int) dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notifyOverride == 0); + settingsCache.put(dialog_id, value); + } + if (!value) { + continue; + } + int count = entry.getValue(); + pushDialogs.put(dialog_id, count); + total_unread_count += count; + } + if (total_unread_count == 0) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + popupMessages.clear(); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.pushMessagesUpdated); + } + }); + } + showOrUpdateNotification(SystemClock.uptimeMillis() / 1000 < 60); + + if (preferences.getBoolean("badgeNumber", true)) { + setBadge(total_unread_count); + } + } + }); + } + + public void setBadgeEnabled(boolean enabled) { + setBadge(enabled ? total_unread_count : 0); + } + + private void setBadge(final int count) { + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + if (lastBadgeCount == count) { + return; + } + lastBadgeCount = count; + try { + ContentValues cv = new ContentValues(); + cv.put("tag", "org.telegram.messenger/org.telegram.ui.LaunchActivity"); + cv.put("count", count); + ApplicationLoader.applicationContext.getContentResolver().insert(Uri.parse("content://com.teslacoilsw.notifier/unread_count"), cv); + } catch (Throwable e) { + //ignore + } + try { + if (launcherClassName == null) { + launcherClassName = getLauncherClassName(ApplicationLoader.applicationContext); + } + if (launcherClassName == null) { + return; + } + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); + intent.putExtra("badge_count", count); + intent.putExtra("badge_count_package_name", ApplicationLoader.applicationContext.getPackageName()); + intent.putExtra("badge_count_class_name", launcherClassName); + ApplicationLoader.applicationContext.sendBroadcast(intent); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + } + }); } private String getStringForMessage(MessageObject messageObject, boolean shortMessage) { @@ -420,6 +840,119 @@ public class NotificationsController { } } + private static String getLauncherClassName(Context context) { + try { + PackageManager pm = context.getPackageManager(); + + Intent intent = new Intent(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + + List resolveInfos = pm.queryIntentActivities(intent, 0); + for (ResolveInfo resolveInfo : resolveInfos) { + String pkgName = resolveInfo.activityInfo.applicationInfo.packageName; + if (pkgName.equalsIgnoreCase(context.getPackageName())) { + return resolveInfo.activityInfo.name; + } + } + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + return null; + } + + private boolean isPersonalMessage(MessageObject messageObject) { + return messageObject.messageOwner.to_id != null && messageObject.messageOwner.to_id.chat_id == 0 && messageObject.messageOwner.to_id.channel_id == 0 + && (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty); + } + + private int getNotifyOverride(SharedPreferences preferences, long dialog_id) { + int notifyOverride = preferences.getInt("notify2_" + dialog_id, 0); + if (notifyOverride == 3) { + int muteUntil = preferences.getInt("notifyuntil_" + dialog_id, 0); + if (muteUntil >= ConnectionsManager.getInstance().getCurrentTime()) { + notifyOverride = 2; + } + } + return notifyOverride; + } + + private void dismissNotification() { + try { + notificationManager.cancel(1); + pushMessages.clear(); + pushMessagesDict.clear(); + for (HashMap.Entry entry : autoNotificationsIds.entrySet()) { + notificationManager.cancel(entry.getValue()); + } + autoNotificationsIds.clear(); + for (HashMap.Entry entry : wearNotificationsIds.entrySet()) { + notificationManager.cancel(entry.getValue()); + } + wearNotificationsIds.clear(); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.pushMessagesUpdated); + } + }); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + + private void playInChatSound() { + if (!inChatSoundEnabled) { + return; + } + try { + if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) { + return; + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + + try { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); + int notifyOverride = getNotifyOverride(preferences, openned_dialog_id); + if (notifyOverride == 2) { + return; + } + notificationsQueue.postRunnable(new Runnable() { + @Override + public void run() { + if (lastSoundPlay > System.currentTimeMillis() - 500) { + return; + } + try { + if (soundPool == null) { + soundPool = new SoundPool(2, AudioManager.STREAM_SYSTEM, 0); + soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() { + @Override + public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { + if (status == 0) { + soundPool.play(sampleId, 1.0f, 1.0f, 1, 0, 1.0f); + } + } + }); + } + if (soundIn == 0 && !soundInLoaded) { + soundInLoaded = true; + soundIn = soundPool.load(ApplicationLoader.applicationContext, R.raw.sound_in, 1); + } + if (soundIn != 0) { + soundPool.play(soundIn, 1.0f, 1.0f, 1, 0, 1.0f); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + private void scheduleNotificationDelay(boolean onlineReason) { try { FileLog.e("tmessages", "delay notification start, onlineReason = " + onlineReason); @@ -433,21 +966,16 @@ public class NotificationsController { } protected void repeatNotificationMaybe() { - int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); - if (hour >= 11 && hour <= 22) { - notificationManager.cancel(1); - showOrUpdateNotification(true); - } else { - scheduleNotificationRepeat(); - } - } - - public void setLastOnlineFromOtherDevice(final int time) { - AndroidUtilities.runOnUIThread(new Runnable() { + notificationsQueue.postRunnable(new Runnable() { @Override public void run() { - FileLog.e("tmessages", "set last online from other device = " + time); - lastOnlineFromOtherDevice = time; + int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); + if (hour >= 11 && hour <= 22) { + notificationManager.cancel(1); + showOrUpdateNotification(true); + } else { + scheduleNotificationRepeat(); + } } }); } @@ -614,7 +1142,7 @@ public class NotificationsController { if (chat.photo != null && chat.photo.photo_small != null && chat.photo.photo_small.volume_id != 0 && chat.photo.photo_small.local_id != 0) { photoPath = chat.photo.photo_small; } - } else { + } else if (user != null) { if (user.photo != null && user.photo.photo_small != null && user.photo.photo_small.volume_id != 0 && user.photo.photo_small.local_id != 0) { photoPath = user.photo.photo_small; } @@ -770,7 +1298,7 @@ public class NotificationsController { } @SuppressLint("InlinedApi") - public void showExtraNotifications(NotificationCompat.Builder notificationBuilder, boolean notifyAboutLast) { + private void showExtraNotifications(NotificationCompat.Builder notificationBuilder, boolean notifyAboutLast) { if (Build.VERSION.SDK_INT < 18) { return; } @@ -953,143 +1481,6 @@ public class NotificationsController { } } - private void dismissNotification() { - try { - notificationManager.cancel(1); - pushMessages.clear(); - pushMessagesDict.clear(); - for (HashMap.Entry entry : autoNotificationsIds.entrySet()) { - notificationManager.cancel(entry.getValue()); - } - autoNotificationsIds.clear(); - for (HashMap.Entry entry : wearNotificationsIds.entrySet()) { - notificationManager.cancel(entry.getValue()); - } - wearNotificationsIds.clear(); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.pushMessagesUpdated); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - - public void processReadMessages(SparseArray inbox, long dialog_id, int max_date, int max_id, boolean isPopup) { - int oldCount = popupMessages.size(); - if (inbox != null) { - for (int b = 0; b < inbox.size(); b++) { - int key = inbox.keyAt(b); - long messageId = inbox.get(key); - for (int a = 0; a < pushMessages.size(); a++) { - MessageObject messageObject = pushMessages.get(a); - if (messageObject.getDialogId() == key && messageObject.getId() <= (int) messageId) { - if (isPersonalMessage(messageObject)) { - personal_count--; - } - popupMessages.remove(messageObject); - pushMessagesDict.remove(messageObject.getId()); - delayedPushMessages.remove(messageObject); - pushMessages.remove(a); - a--; - } - } - } - if (pushMessages.isEmpty() && !popupMessages.isEmpty()) { - popupMessages.clear(); - } - } - if (dialog_id != 0 && (max_id != 0 || max_date != 0)) { - for (int a = 0; a < pushMessages.size(); a++) { - MessageObject messageObject = pushMessages.get(a); - if (messageObject.getDialogId() == dialog_id) { - boolean remove = false; - if (max_date != 0) { - if (messageObject.messageOwner.date <= max_date) { - remove = true; - } - } else { - if (!isPopup) { - if (messageObject.getId() <= max_id || max_id < 0) { - remove = true; - } - } else { - if (messageObject.getId() == max_id || max_id < 0) { - remove = true; - } - } - } - if (remove) { - if (isPersonalMessage(messageObject)) { - personal_count--; - } - pushMessages.remove(a); - delayedPushMessages.remove(messageObject); - popupMessages.remove(messageObject); - pushMessagesDict.remove(messageObject.getId()); - a--; - } - } - } - if (pushMessages.isEmpty() && !popupMessages.isEmpty()) { - popupMessages.clear(); - } - } - if (oldCount != popupMessages.size()) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.pushMessagesUpdated); - } - } - - private void playInChatSound() { - if (!inChatSoundEnabled) { - return; - } - try { - if (audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT) { - return; - } - } catch (Exception e) { - FileLog.e("tmessages", e); - } - - try { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); - int notifyOverride = getNotifyOverride(preferences, openned_dialog_id); - if (notifyOverride == 2) { - return; - } - notificationsQueue.postRunnable(new Runnable() { - @Override - public void run() { - if (lastSoundPlay > System.currentTimeMillis() - 500) { - return; - } - try { - if (soundPool == null) { - soundPool = new SoundPool(2, AudioManager.STREAM_SYSTEM, 0); - soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() { - @Override - public void onLoadComplete(SoundPool soundPool, int sampleId, int status) { - if (status == 0) { - soundPool.play(sampleId, 1.0f, 1.0f, 1, 0, 1.0f); - } - } - }); - } - if (soundIn == 0 && !soundInLoaded) { - soundInLoaded = true; - soundIn = soundPool.load(ApplicationLoader.applicationContext, R.raw.sound_in, 1); - } - if (soundIn != 0) { - soundPool.play(soundIn, 1.0f, 1.0f, 1, 0, 1.0f); - } - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - }); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - public void playOutChatSound() { if (!inChatSoundEnabled) { return; @@ -1134,300 +1525,6 @@ public class NotificationsController { }); } - private int getNotifyOverride(SharedPreferences preferences, long dialog_id) { - int notifyOverride = preferences.getInt("notify2_" + dialog_id, 0); - if (notifyOverride == 3) { - int muteUntil = preferences.getInt("notifyuntil_" + dialog_id, 0); - if (muteUntil >= ConnectionsManager.getInstance().getCurrentTime()) { - notifyOverride = 2; - } - } - return notifyOverride; - } - - public void processNewMessages(ArrayList messageObjects, boolean isLast) { - if (messageObjects.isEmpty()) { - return; - } - boolean added = false; - - int oldCount = popupMessages.size(); - HashMap settingsCache = new HashMap<>(); - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); - int popup = 0; - - for (int a = 0; a < messageObjects.size(); a++) { - MessageObject messageObject = messageObjects.get(a); - if (pushMessagesDict.containsKey(messageObject.getId())) { - continue; - } - long dialog_id = messageObject.getDialogId(); - long original_dialog_id = dialog_id; - if (dialog_id == openned_dialog_id && ApplicationLoader.isScreenOn) { - playInChatSound(); - continue; - } - if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) { - dialog_id = messageObject.messageOwner.from_id; - } - if (isPersonalMessage(messageObject)) { - personal_count++; - } - added = true; - - Boolean value = settingsCache.get(dialog_id); - boolean isChat = (int)dialog_id < 0; - popup = (int)dialog_id == 0 ? 0 : preferences.getInt(isChat ? "popupGroup" : "popupAll", 0); - if (value == null) { - int notifyOverride = getNotifyOverride(preferences, dialog_id); - value = !(notifyOverride == 2 || (!preferences.getBoolean("EnableAll", true) || isChat && !preferences.getBoolean("EnableGroup", true)) && notifyOverride == 0); - settingsCache.put(dialog_id, value); - } - if (value) { - if (popup != 0) { - popupMessages.add(0, messageObject); - } - delayedPushMessages.add(messageObject); - pushMessages.add(0, messageObject); - pushMessagesDict.put(messageObject.getId(), messageObject); - if (original_dialog_id != dialog_id) { - pushDialogsOverrideMention.put(original_dialog_id, 1); - } - } - } - - if (added) { - notifyCheck = isLast; - } - - if (!popupMessages.isEmpty() && oldCount != popupMessages.size() && !AndroidUtilities.needShowPasscode(false) && !UserConfig.isWaitingForPasscodeEnter) { - if (ApplicationLoader.mainInterfacePaused || !ApplicationLoader.isScreenOn) { - MessageObject messageObject = messageObjects.get(0); - if (popup == 3 || popup == 1 && ApplicationLoader.isScreenOn || popup == 2 && !ApplicationLoader.isScreenOn) { - Intent popupIntent = new Intent(ApplicationLoader.applicationContext, PopupNotificationActivity.class); - popupIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_FROM_BACKGROUND); - ApplicationLoader.applicationContext.startActivity(popupIntent); - } - } - } - } - - public void processDialogsUpdateRead(final HashMap dialogsToUpdate) { - int old_unread_count = total_unread_count; - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); - for (HashMap.Entry entry : dialogsToUpdate.entrySet()) { - long dialog_id = entry.getKey(); - - int notifyOverride = getNotifyOverride(preferences, dialog_id); - if (notifyCheck) { - Integer override = pushDialogsOverrideMention.get(dialog_id); - if (override != null && override == 1) { - pushDialogsOverrideMention.put(dialog_id, 0); - notifyOverride = 1; - } - } - boolean canAddValue = !(notifyOverride == 2 || (!preferences.getBoolean("EnableAll", true) || ((int)dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notifyOverride == 0); - - Integer currentCount = pushDialogs.get(dialog_id); - Integer newCount = entry.getValue(); - if (newCount == 0) { - smartNotificationsDialogs.remove(dialog_id); - } - - if (newCount < 0) { - if (currentCount == null) { - continue; - } - newCount = currentCount + newCount; - } - if (canAddValue || newCount == 0) { - if (currentCount != null) { - total_unread_count -= currentCount; - } - } - if (newCount == 0) { - pushDialogs.remove(dialog_id); - pushDialogsOverrideMention.remove(dialog_id); - for (int a = 0; a < pushMessages.size(); a++) { - MessageObject messageObject = pushMessages.get(a); - if (messageObject.getDialogId() == dialog_id) { - if (isPersonalMessage(messageObject)) { - personal_count--; - } - pushMessages.remove(a); - a--; - delayedPushMessages.remove(messageObject); - pushMessagesDict.remove(messageObject.getId()); - popupMessages.remove(messageObject); - } - } - if (pushMessages.isEmpty() && !popupMessages.isEmpty()) { - popupMessages.clear(); - } - } else if (canAddValue) { - total_unread_count += newCount; - pushDialogs.put(dialog_id, newCount); - } - } - if (old_unread_count != total_unread_count) { - if (!notifyCheck) { - delayedPushMessages.clear(); - showOrUpdateNotification(notifyCheck); - } else { - scheduleNotificationDelay(lastOnlineFromOtherDevice > ConnectionsManager.getInstance().getCurrentTime()); - } - } - notifyCheck = false; - if (preferences.getBoolean("badgeNumber", true)) { - setBadge(total_unread_count); - } - } - - public void processLoadedUnreadMessages(HashMap dialogs, ArrayList messages, ArrayList users, ArrayList chats, ArrayList encryptedChats) { - MessagesController.getInstance().putUsers(users, true); - MessagesController.getInstance().putChats(chats, true); - MessagesController.getInstance().putEncryptedChats(encryptedChats, true); - - pushDialogs.clear(); - pushMessages.clear(); - pushMessagesDict.clear(); - total_unread_count = 0; - personal_count = 0; - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); - HashMap settingsCache = new HashMap<>(); - - if (messages != null) { - for (TLRPC.Message message : messages) { - if (pushMessagesDict.containsKey(message.id)) { - continue; - } - MessageObject messageObject = new MessageObject(message, null, false); - if (isPersonalMessage(messageObject)) { - personal_count++; - } - long dialog_id = messageObject.getDialogId(); - long original_dialog_id = dialog_id; - if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) { - dialog_id = messageObject.messageOwner.from_id; - } - Boolean value = settingsCache.get(dialog_id); - if (value == null) { - int notifyOverride = getNotifyOverride(preferences, dialog_id); - value = !(notifyOverride == 2 || (!preferences.getBoolean("EnableAll", true) || ((int) dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notifyOverride == 0); - settingsCache.put(dialog_id, value); - } - if (!value || dialog_id == openned_dialog_id && ApplicationLoader.isScreenOn) { - continue; - } - pushMessagesDict.put(messageObject.getId(), messageObject); - pushMessages.add(0, messageObject); - if (original_dialog_id != dialog_id) { - pushDialogsOverrideMention.put(original_dialog_id, 1); - } - } - } - for (HashMap.Entry entry : dialogs.entrySet()) { - long dialog_id = entry.getKey(); - Boolean value = settingsCache.get(dialog_id); - if (value == null) { - int notifyOverride = getNotifyOverride(preferences, dialog_id); - Integer override = pushDialogsOverrideMention.get(dialog_id); - if (override != null && override == 1) { - pushDialogsOverrideMention.put(dialog_id, 0); - notifyOverride = 1; - } - value = !(notifyOverride == 2 || (!preferences.getBoolean("EnableAll", true) || ((int) dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notifyOverride == 0); - settingsCache.put(dialog_id, value); - } - if (!value) { - continue; - } - int count = entry.getValue(); - pushDialogs.put(dialog_id, count); - total_unread_count += count; - } - if (total_unread_count == 0) { - popupMessages.clear(); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.pushMessagesUpdated); - } - showOrUpdateNotification(SystemClock.uptimeMillis() / 1000 < 60); - - if (preferences.getBoolean("badgeNumber", true)) { - setBadge(total_unread_count); - } - } - - public void setBadgeEnabled(boolean enabled) { - setBadge(enabled ? total_unread_count : 0); - } - - private void setBadge(final int count) { - notificationsQueue.postRunnable(new Runnable() { - @Override - public void run() { - if (lastBadgeCount == count) { - return; - } - lastBadgeCount = count; - try { - ContentValues cv = new ContentValues(); - cv.put("tag", "org.telegram.messenger/org.telegram.ui.LaunchActivity"); - cv.put("count", count); - ApplicationLoader.applicationContext.getContentResolver().insert(Uri.parse("content://com.teslacoilsw.notifier/unread_count"), cv); - } catch (Throwable e) { - //ignore - } - try { - launcherClassName = getLauncherClassName(ApplicationLoader.applicationContext); - if (launcherClassName == null) { - return; - } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - try { - Intent intent = new Intent("android.intent.action.BADGE_COUNT_UPDATE"); - intent.putExtra("badge_count", count); - intent.putExtra("badge_count_package_name", ApplicationLoader.applicationContext.getPackageName()); - intent.putExtra("badge_count_class_name", launcherClassName); - ApplicationLoader.applicationContext.sendBroadcast(intent); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - }); - } catch (Throwable e) { - FileLog.e("tmessages", e); - } - } - }); - } - - public static String getLauncherClassName(Context context) { - try { - PackageManager pm = context.getPackageManager(); - - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - - List resolveInfos = pm.queryIntentActivities(intent, 0); - for (ResolveInfo resolveInfo : resolveInfos) { - String pkgName = resolveInfo.activityInfo.applicationInfo.packageName; - if (pkgName.equalsIgnoreCase(context.getPackageName())) { - return resolveInfo.activityInfo.name; - } - } - } catch (Throwable e) { - FileLog.e("tmessages", e); - } - return null; - } - - private boolean isPersonalMessage(MessageObject messageObject) { - return messageObject.messageOwner.to_id != null && messageObject.messageOwner.to_id.chat_id == 0 && messageObject.messageOwner.to_id.channel_id == 0 - && (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty); - } - public static void updateServerNotificationsSettings(long dialog_id) { NotificationCenter.getInstance().postNotificationName(NotificationCenter.notificationsSettingsUpdated); if ((int)dialog_id == 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsService.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsService.java index 5195ef7d8..857577cfd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsService.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ScreenReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ScreenReceiver.java index 22feeb4b2..099167152 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ScreenReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ScreenReceiver.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java index 6a2081348..cada60538 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -969,6 +969,9 @@ public class SecretChatHelper { newMessage.media.document.size = file.size; newMessage.media.document.key = decryptedMessage.media.key; newMessage.media.document.iv = decryptedMessage.media.iv; + if (newMessage.media.document.mime_type == null) { + newMessage.media.document.mime_type = ""; + } byte[] thumb = ((TLRPC.TL_decryptedMessageMediaDocument) decryptedMessage.media).thumb; if (thumb != null && thumb.length != 0 && thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { newMessage.media.document.thumb = new TLRPC.TL_photoCachedSize(); @@ -993,6 +996,9 @@ public class SecretChatHelper { newMessage.media.document.dc_id = decryptedMessage.media.dc_id; newMessage.media.document.size = decryptedMessage.media.size; newMessage.media.document.thumb = ((TLRPC.TL_decryptedMessageMediaExternalDocument) decryptedMessage.media).thumb; + if (newMessage.media.document.mime_type == null) { + newMessage.media.document.mime_type = ""; + } } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaAudio) { if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { return null; @@ -1233,7 +1239,24 @@ public class SecretChatHelper { } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionNoop) { //do nothing } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionResend) { - + final TLRPC.TL_encryptedChatDiscarded newChat = new TLRPC.TL_encryptedChatDiscarded(); + newChat.id = chat.id; + newChat.user_id = chat.user_id; + newChat.auth_key = chat.auth_key; + newChat.key_create_date = chat.key_create_date; + newChat.key_use_count_in = chat.key_use_count_in; + newChat.key_use_count_out = chat.key_use_count_out; + newChat.seq_in = chat.seq_in; + newChat.seq_out = chat.seq_out; + MessagesStorage.getInstance().updateEncryptedChat(newChat); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + MessagesController.getInstance().putEncryptedChat(newChat, false); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); + } + }); + declineSecretChat(chat.id); } else { return null; } @@ -1337,6 +1360,10 @@ public class SecretChatHelper { chat.seq_in = 1; } } + if (layer.random_bytes.length < 15) { + FileLog.e("tmessages", "got random bytes less than needed"); + return null; + } FileLog.e("tmessages", "current chat in_seq = " + chat.seq_in + " out_seq = " + chat.seq_out); FileLog.e("tmessages", "got message with in_seq = " + layer.in_seq_no + " out_seq = " + layer.out_seq_no); if (layer.out_seq_no < chat.seq_in) { @@ -1349,7 +1376,7 @@ public class SecretChatHelper { arr = new ArrayList<>(); secretHolesQueue.put(chat.id, arr); } - if (arr.size() >= 10) { + if (arr.size() >= 4) { secretHolesQueue.remove(chat.id); final TLRPC.TL_encryptedChatDiscarded newChat = new TLRPC.TL_encryptedChatDiscarded(); newChat.id = chat.id; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index c38b98dbe..a5a0f5b11 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; @@ -143,6 +143,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter arr.remove(a); a--; } else if (encryptedFile != null && message.sendEncryptedRequest != null) { + if (message.sendEncryptedRequest.media instanceof TLRPC.TL_decryptedMessageMediaVideo) { + long size = (Long) args[5]; + message.sendEncryptedRequest.media.size = (int) size; + } message.sendEncryptedRequest.media.key = (byte[]) args[3]; message.sendEncryptedRequest.media.iv = (byte[]) args[4]; SecretChatHelper.getInstance().performSendEncryptedRequest(message.sendEncryptedRequest, message.obj.messageOwner, message.encryptedChat, encryptedFile, message.originalPath); @@ -289,6 +293,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter Bitmap bitmap = ImageLoader.loadBitmap(cacheFile.getAbsolutePath(), null, 90, 90, true); if (bitmap != null) { message.documentLocation.thumb = ImageLoader.scaleAndSaveImage(bitmap, 90, 90, 55, message.sendEncryptedRequest != null); + bitmap.recycle(); } } catch (Exception e) { message.documentLocation.thumb = null; @@ -497,6 +502,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter newDocument.size = document.size; newDocument.dc_id = document.dc_id; newDocument.attributes = document.attributes; + if (newDocument.mime_type == null) { + newDocument.mime_type = ""; + } document = newDocument; } catch (Exception e) { FileLog.e("tmessages", e); @@ -764,6 +772,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } TLRPC.Message newMsg = null; + MessageObject newMsgObj = null; int type = -1; int lower_id = (int) peer; int high_id = (int) (peer >> 32); @@ -783,257 +792,257 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } - if (retry) { - newMsg = msgObj.messageOwner; + try { + if (retry) { + newMsg = msgObj.messageOwner; - if (msgObj.type == 0) { - if (msgObj.isForwarded()) { - type = 4; - } else { - message = newMsg.message; - type = 0; - } - } else if (msgObj.type == 4) { - location = newMsg.media; - type = 1; - } else if (msgObj.type == 1) { - if (msgObj.isForwarded()) { - type = 4; - } else { - photo = (TLRPC.TL_photo) newMsg.media.photo; - type = 2; - } - } else if (msgObj.type == 3) { - if (msgObj.isForwarded()) { - type = 4; - } else { - type = 3; - video = (TLRPC.TL_video) newMsg.media.video; - } - } else if (msgObj.type == 12) { - user = new TLRPC.TL_userRequest_old2(); - user.phone = newMsg.media.phone_number; - user.first_name = newMsg.media.first_name; - user.last_name = newMsg.media.last_name; - user.id = newMsg.media.user_id; - type = 6; - } else if (msgObj.type == 8 || msgObj.type == 9 || msgObj.type == 13) { - document = (TLRPC.TL_document) newMsg.media.document; - type = 7; - } else if (msgObj.type == 2) { - audio = (TLRPC.TL_audio) newMsg.media.audio; - type = 8; - } - } else { - if (message != null) { - if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - newMsg = new TLRPC.TL_message_secret(); - } else { - newMsg = new TLRPC.TL_message(); - } - if (encryptedChat != null || webPage == null) { - newMsg.media = new TLRPC.TL_messageMediaEmpty(); - } else { - newMsg.media = new TLRPC.TL_messageMediaWebPage(); - newMsg.media.webpage = webPage; - } - type = 0; - newMsg.message = message; - } else if (location != null) { - if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - newMsg = new TLRPC.TL_message_secret(); - } else { - newMsg = new TLRPC.TL_message(); - } - newMsg.media = location; - newMsg.message = ""; - type = 1; - } else if (photo != null) { - if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - newMsg = new TLRPC.TL_message_secret(); - } else { - newMsg = new TLRPC.TL_message(); - } - newMsg.media = new TLRPC.TL_messageMediaPhoto(); - newMsg.media.caption = photo.caption != null ? photo.caption : ""; - newMsg.media.photo = photo; - type = 2; - newMsg.message = "-1"; - if (path != null && path.length() > 0 && path.startsWith("http")) { - newMsg.attachPath = path; - } else { - TLRPC.FileLocation location1 = photo.sizes.get(photo.sizes.size() - 1).location; - newMsg.attachPath = FileLoader.getPathToAttach(location1, true).toString(); - } - } else if (video != null) { - if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - newMsg = new TLRPC.TL_message_secret(); - } else { - newMsg = new TLRPC.TL_message(); - } - newMsg.media = new TLRPC.TL_messageMediaVideo(); - newMsg.media.caption = video.caption != null ? video.caption : ""; - newMsg.media.video = video; - type = 3; - if (videoEditedInfo == null) { - newMsg.message = "-1"; - } else { - newMsg.message = videoEditedInfo.getString(); - } - newMsg.attachPath = path; - } else if (msgObj != null) { - newMsg = new TLRPC.TL_message(); - newMsg.flags |= TLRPC.MESSAGE_FLAG_FWD; - if (msgObj.isForwarded()) { - newMsg.fwd_from_id = msgObj.messageOwner.fwd_from_id; - newMsg.fwd_date = msgObj.messageOwner.fwd_date; - } else { - newMsg.fwd_from_id = new TLRPC.TL_peerUser(); - newMsg.fwd_from_id.user_id = msgObj.messageOwner.from_id; - newMsg.fwd_date = msgObj.messageOwner.date; - } - newMsg.media = msgObj.messageOwner.media; - newMsg.message = msgObj.messageOwner.message; - newMsg.fwd_msg_id = msgObj.getId(); - newMsg.attachPath = msgObj.messageOwner.attachPath; - type = 4; - } else if (user != null) { - if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - newMsg = new TLRPC.TL_message_secret(); - } else { - newMsg = new TLRPC.TL_message(); - } - newMsg.media = new TLRPC.TL_messageMediaContact(); - newMsg.media.phone_number = user.phone; - newMsg.media.first_name = user.first_name; - newMsg.media.last_name = user.last_name; - newMsg.media.user_id = user.id; - if (newMsg.media.first_name == null) { - user.first_name = newMsg.media.first_name = ""; - } - if (newMsg.media.last_name == null) { - user.last_name = newMsg.media.last_name = ""; - } - newMsg.message = ""; - type = 6; - } else if (document != null) { - if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - newMsg = new TLRPC.TL_message_secret(); - } else { - newMsg = new TLRPC.TL_message(); - } - newMsg.media = new TLRPC.TL_messageMediaDocument(); - newMsg.media.document = document; - type = 7; - newMsg.message = "-1"; - newMsg.attachPath = path; - } else if (audio != null) { - if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - newMsg = new TLRPC.TL_message_secret(); - } else { - newMsg = new TLRPC.TL_message(); - } - newMsg.media = new TLRPC.TL_messageMediaAudio(); - newMsg.media.audio = audio; - type = 8; - newMsg.message = "-1"; - newMsg.attachPath = path; - } - if (newMsg.attachPath == null) { - newMsg.attachPath = ""; - } - newMsg.local_id = newMsg.id = UserConfig.getNewMessageId(); - newMsg.flags |= TLRPC.MESSAGE_FLAG_OUT; - if (asAdmin && sendToPeer != null && sendToPeer.channel_id != 0) { - newMsg.from_id = -sendToPeer.channel_id; - } else { - newMsg.from_id = UserConfig.getClientUserId(); - newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_FROM_ID; - } - UserConfig.saveConfig(false); - } - if (newMsg.random_id == 0) { - newMsg.random_id = getNextRandomId(); - } - newMsg.date = ConnectionsManager.getInstance().getCurrentTime(); - newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_MEDIA; - if (encryptedChat == null && high_id != 1 && newMsg.media instanceof TLRPC.TL_messageMediaAudio) { - newMsg.flags |= TLRPC.MESSAGE_FLAG_CONTENT_UNREAD; - } - if (sendToPeer instanceof TLRPC.TL_inputPeerChannel) { - if (asAdmin) { - newMsg.views = 1; - newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS; - } - } else { - newMsg.flags |= TLRPC.MESSAGE_FLAG_UNREAD; - } - newMsg.dialog_id = peer; - if (reply_to_msg != null) { - newMsg.flags |= TLRPC.MESSAGE_FLAG_REPLY; - newMsg.reply_to_msg_id = reply_to_msg.getId(); - } - if (lower_id != 0) { - if (high_id == 1) { - if (currentChatInfo == null) { - MessagesStorage.getInstance().markMessageAsSendError(newMsg); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsg.id); - processSentMessage(newMsg.id); - return; - } - sendToPeers = new ArrayList<>(); - for (TLRPC.TL_chatParticipant participant : currentChatInfo.participants.participants) { - TLRPC.User sendToUser = MessagesController.getInstance().getUser(participant.user_id); - TLRPC.InputUser peerUser = MessagesController.getInputUser(sendToUser); - if (peerUser != null) { - sendToPeers.add(peerUser); + if (msgObj.type == 0) { + if (msgObj.isForwarded()) { + type = 4; + } else { + message = newMsg.message; + type = 0; } + } else if (msgObj.type == 4) { + location = newMsg.media; + type = 1; + } else if (msgObj.type == 1) { + if (msgObj.isForwarded()) { + type = 4; + } else { + photo = (TLRPC.TL_photo) newMsg.media.photo; + type = 2; + } + } else if (msgObj.type == 3) { + if (msgObj.isForwarded()) { + type = 4; + } else { + type = 3; + video = (TLRPC.TL_video) newMsg.media.video; + } + } else if (msgObj.type == 12) { + user = new TLRPC.TL_userRequest_old2(); + user.phone = newMsg.media.phone_number; + user.first_name = newMsg.media.first_name; + user.last_name = newMsg.media.last_name; + user.id = newMsg.media.user_id; + type = 6; + } else if (msgObj.type == 8 || msgObj.type == 9 || msgObj.type == 13) { + document = (TLRPC.TL_document) newMsg.media.document; + type = 7; + } else if (msgObj.type == 2) { + audio = (TLRPC.TL_audio) newMsg.media.audio; + type = 8; } - newMsg.to_id = new TLRPC.TL_peerChat(); - newMsg.to_id.chat_id = lower_id; } else { - newMsg.to_id = MessagesController.getPeer(lower_id); - if (lower_id > 0) { - TLRPC.User sendToUser = MessagesController.getInstance().getUser(lower_id); - if (sendToUser == null) { + if (message != null) { + if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + newMsg = new TLRPC.TL_message_secret(); + } else { + newMsg = new TLRPC.TL_message(); + } + if (encryptedChat != null || webPage == null) { + newMsg.media = new TLRPC.TL_messageMediaEmpty(); + } else { + newMsg.media = new TLRPC.TL_messageMediaWebPage(); + newMsg.media.webpage = webPage; + } + type = 0; + newMsg.message = message; + } else if (location != null) { + if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + newMsg = new TLRPC.TL_message_secret(); + } else { + newMsg = new TLRPC.TL_message(); + } + newMsg.media = location; + newMsg.message = ""; + type = 1; + } else if (photo != null) { + if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + newMsg = new TLRPC.TL_message_secret(); + } else { + newMsg = new TLRPC.TL_message(); + } + newMsg.media = new TLRPC.TL_messageMediaPhoto(); + newMsg.media.caption = photo.caption != null ? photo.caption : ""; + newMsg.media.photo = photo; + type = 2; + newMsg.message = "-1"; + if (path != null && path.length() > 0 && path.startsWith("http")) { + newMsg.attachPath = path; + } else { + TLRPC.FileLocation location1 = photo.sizes.get(photo.sizes.size() - 1).location; + newMsg.attachPath = FileLoader.getPathToAttach(location1, true).toString(); + } + } else if (video != null) { + if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + newMsg = new TLRPC.TL_message_secret(); + } else { + newMsg = new TLRPC.TL_message(); + } + newMsg.media = new TLRPC.TL_messageMediaVideo(); + newMsg.media.caption = video.caption != null ? video.caption : ""; + newMsg.media.video = video; + type = 3; + if (videoEditedInfo == null) { + newMsg.message = "-1"; + } else { + newMsg.message = videoEditedInfo.getString(); + } + newMsg.attachPath = path; + } else if (msgObj != null) { + newMsg = new TLRPC.TL_message(); + newMsg.flags |= TLRPC.MESSAGE_FLAG_FWD; + if (msgObj.isForwarded()) { + newMsg.fwd_from_id = msgObj.messageOwner.fwd_from_id; + newMsg.fwd_date = msgObj.messageOwner.fwd_date; + } else { + newMsg.fwd_from_id = new TLRPC.TL_peerUser(); + newMsg.fwd_from_id.user_id = msgObj.messageOwner.from_id; + newMsg.fwd_date = msgObj.messageOwner.date; + } + newMsg.media = msgObj.messageOwner.media; + newMsg.message = msgObj.messageOwner.message; + newMsg.fwd_msg_id = msgObj.getId(); + newMsg.attachPath = msgObj.messageOwner.attachPath; + type = 4; + } else if (user != null) { + if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + newMsg = new TLRPC.TL_message_secret(); + } else { + newMsg = new TLRPC.TL_message(); + } + newMsg.media = new TLRPC.TL_messageMediaContact(); + newMsg.media.phone_number = user.phone; + newMsg.media.first_name = user.first_name; + newMsg.media.last_name = user.last_name; + newMsg.media.user_id = user.id; + if (newMsg.media.first_name == null) { + user.first_name = newMsg.media.first_name = ""; + } + if (newMsg.media.last_name == null) { + user.last_name = newMsg.media.last_name = ""; + } + newMsg.message = ""; + type = 6; + } else if (document != null) { + if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + newMsg = new TLRPC.TL_message_secret(); + } else { + newMsg = new TLRPC.TL_message(); + } + newMsg.media = new TLRPC.TL_messageMediaDocument(); + newMsg.media.document = document; + type = 7; + newMsg.message = "-1"; + newMsg.attachPath = path; + } else if (audio != null) { + if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + newMsg = new TLRPC.TL_message_secret(); + } else { + newMsg = new TLRPC.TL_message(); + } + newMsg.media = new TLRPC.TL_messageMediaAudio(); + newMsg.media.audio = audio; + type = 8; + newMsg.message = "-1"; + newMsg.attachPath = path; + } + if (newMsg.attachPath == null) { + newMsg.attachPath = ""; + } + newMsg.local_id = newMsg.id = UserConfig.getNewMessageId(); + newMsg.flags |= TLRPC.MESSAGE_FLAG_OUT; + if (asAdmin && sendToPeer != null && sendToPeer.channel_id != 0) { + newMsg.from_id = -sendToPeer.channel_id; + } else { + newMsg.from_id = UserConfig.getClientUserId(); + newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_FROM_ID; + } + UserConfig.saveConfig(false); + } + if (newMsg.random_id == 0) { + newMsg.random_id = getNextRandomId(); + } + newMsg.date = ConnectionsManager.getInstance().getCurrentTime(); + newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_MEDIA; + if (encryptedChat == null && high_id != 1 && newMsg.media instanceof TLRPC.TL_messageMediaAudio) { + newMsg.flags |= TLRPC.MESSAGE_FLAG_CONTENT_UNREAD; + } + if (sendToPeer instanceof TLRPC.TL_inputPeerChannel) { + if (asAdmin) { + newMsg.views = 1; + newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_VIEWS; + } + } else { + newMsg.flags |= TLRPC.MESSAGE_FLAG_UNREAD; + } + newMsg.dialog_id = peer; + if (reply_to_msg != null) { + newMsg.flags |= TLRPC.MESSAGE_FLAG_REPLY; + newMsg.reply_to_msg_id = reply_to_msg.getId(); + } + if (lower_id != 0) { + if (high_id == 1) { + if (currentChatInfo == null) { + MessagesStorage.getInstance().markMessageAsSendError(newMsg); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsg.id); processSentMessage(newMsg.id); return; } - if ((sendToUser.flags & TLRPC.USER_FLAG_BOT) != 0) { - newMsg.flags &= ~TLRPC.MESSAGE_FLAG_UNREAD; + sendToPeers = new ArrayList<>(); + for (TLRPC.TL_chatParticipant participant : currentChatInfo.participants.participants) { + TLRPC.User sendToUser = MessagesController.getInstance().getUser(participant.user_id); + TLRPC.InputUser peerUser = MessagesController.getInputUser(sendToUser); + if (peerUser != null) { + sendToPeers.add(peerUser); + } + } + newMsg.to_id = new TLRPC.TL_peerChat(); + newMsg.to_id.chat_id = lower_id; + } else { + newMsg.to_id = MessagesController.getPeer(lower_id); + if (lower_id > 0) { + TLRPC.User sendToUser = MessagesController.getInstance().getUser(lower_id); + if (sendToUser == null) { + processSentMessage(newMsg.id); + return; + } + if ((sendToUser.flags & TLRPC.USER_FLAG_BOT) != 0) { + newMsg.flags &= ~TLRPC.MESSAGE_FLAG_UNREAD; + } + } + } + } else { + newMsg.to_id = new TLRPC.TL_peerUser(); + if (encryptedChat.participant_id == UserConfig.getClientUserId()) { + newMsg.to_id.user_id = encryptedChat.admin_id; + } else { + newMsg.to_id.user_id = encryptedChat.participant_id; + } + newMsg.ttl = encryptedChat.ttl; + if (newMsg.ttl != 0) { + if (newMsg.media instanceof TLRPC.TL_messageMediaAudio) { + newMsg.ttl = Math.max(encryptedChat.ttl, newMsg.media.audio.duration + 1); + } else if (newMsg.media instanceof TLRPC.TL_messageMediaVideo) { + newMsg.ttl = Math.max(encryptedChat.ttl, newMsg.media.video.duration + 1); } } } - } else { - newMsg.to_id = new TLRPC.TL_peerUser(); - if (encryptedChat.participant_id == UserConfig.getClientUserId()) { - newMsg.to_id.user_id = encryptedChat.admin_id; - } else { - newMsg.to_id.user_id = encryptedChat.participant_id; - } - newMsg.ttl = encryptedChat.ttl; - if (newMsg.ttl != 0) { - if (newMsg.media instanceof TLRPC.TL_messageMediaAudio) { - newMsg.ttl = Math.max(encryptedChat.ttl, newMsg.media.audio.duration + 1); - } else if (newMsg.media instanceof TLRPC.TL_messageMediaVideo) { - newMsg.ttl = Math.max(encryptedChat.ttl, newMsg.media.video.duration + 1); - } - } - } - MessageObject newMsgObj = new MessageObject(newMsg, null, true); - newMsgObj.replyMessageObject = reply_to_msg; - newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; + newMsgObj = new MessageObject(newMsg, null, true); + newMsgObj.replyMessageObject = reply_to_msg; + newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; - ArrayList objArr = new ArrayList<>(); - objArr.add(newMsgObj); - ArrayList arr = new ArrayList<>(); - arr.add(newMsg); - MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); - MessagesController.getInstance().updateInterfaceWithMessages(peer, objArr); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + ArrayList objArr = new ArrayList<>(); + objArr.add(newMsgObj); + ArrayList arr = new ArrayList<>(); + arr.add(newMsg); + MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); + MessagesController.getInstance().updateInterfaceWithMessages(peer, objArr); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - try { if (type == 0) { if (encryptedChat == null) { if (sendToPeers != null) { @@ -1447,10 +1456,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } catch (Exception e) { FileLog.e("tmessages", e); - MessagesStorage.getInstance().markMessageAsSendError(newMsgObj.messageOwner); - newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.getId()); - processSentMessage(newMsgObj.getId()); + MessagesStorage.getInstance().markMessageAsSendError(newMsg); + if (newMsgObj != null) { + newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; + } + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsg.id); + processSentMessage(newMsg.id); } } @@ -1718,7 +1729,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter MessagesStorage.getInstance().putSentFile(originalPath, sentMessage.media.photo, 0); for (TLRPC.PhotoSize size : sentMessage.media.photo.sizes) { - if (size == null || size instanceof TLRPC.TL_photoSizeEmpty || size.type == null) { + if (size == null || size.location == null || size instanceof TLRPC.TL_photoSizeEmpty || size.type == null) { continue; } for (TLRPC.PhotoSize size2 : newMsg.media.photo.sizes) { @@ -1754,7 +1765,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.PhotoSize size2 = newMsg.media.video.thumb; TLRPC.PhotoSize size = sentMessage.media.video.thumb; - if (size2.location != null && size2.location.volume_id == Integer.MIN_VALUE && size.location != null && !(size instanceof TLRPC.TL_photoSizeEmpty) && !(size2 instanceof TLRPC.TL_photoSizeEmpty)) { + if (size2 != null && size2.location != null && size2.location.volume_id == Integer.MIN_VALUE && size != null && size.location != null && !(size instanceof TLRPC.TL_photoSizeEmpty) && !(size2 instanceof TLRPC.TL_photoSizeEmpty)) { String fileName = size2.location.volume_id + "_" + size2.location.local_id; String fileName2 = size.location.volume_id + "_" + size.location.local_id; if (!fileName.equals(fileName2)) { @@ -2007,6 +2018,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (bitmap != null) { fileName.file_name = "animation.gif"; document.thumb = ImageLoader.scaleAndSaveImage(bitmap, 90, 90, 55, isEncrypted); + bitmap.recycle(); } } catch (Exception e) { FileLog.e("tmessages", e); @@ -2018,7 +2030,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter bmOptions.inJustDecodeBounds = true; RandomAccessFile file = new RandomAccessFile(path, "r"); ByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, path.length()); - Utilities.loadWebpImage(buffer, buffer.limit(), bmOptions); + Utilities.loadWebpImage(null, buffer, buffer.limit(), bmOptions, true); file.close(); } catch (Exception e) { FileLog.e("tmessages", e); @@ -2223,6 +2235,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter Bitmap bitmap = ImageLoader.loadBitmap(thumbFile.getAbsolutePath(), null, 90, 90, true); if (bitmap != null) { document.thumb = ImageLoader.scaleAndSaveImage(bitmap, 90, 90, 55, isEncrypted); + bitmap.recycle(); } } catch (Exception e) { FileLog.e("tmessages", e); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SmsListener.java b/TMessagesProj/src/main/java/org/telegram/messenger/SmsListener.java index 53ae12959..bb7fad473 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SmsListener.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SmsListener.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java b/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java new file mode 100644 index 000000000..94a2a167a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TgChooserTargetService.java @@ -0,0 +1,174 @@ +/* + * This is the source code of Telegram for Android v. 3.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.messenger; + +import android.annotation.TargetApi; +import android.content.ComponentName; +import android.content.IntentFilter; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.Icon; +import android.os.Build; +import android.os.Bundle; +import android.service.chooser.ChooserTarget; +import android.service.chooser.ChooserTargetService; +import android.text.TextUtils; + +import org.telegram.SQLite.SQLiteCursor; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.LaunchActivity; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.Semaphore; + +@TargetApi(Build.VERSION_CODES.M) +public class TgChooserTargetService extends ChooserTargetService { + + private Paint roundPaint; + private RectF bitmapRect; + + @Override + public List onGetChooserTargets(ComponentName targetActivityName, IntentFilter matchedFilter) { + final List targets = new ArrayList<>(); + if (!UserConfig.isClientActivated()) { + return targets; + } + ImageLoader imageLoader = ImageLoader.getInstance(); + final Semaphore semaphore = new Semaphore(0); + final ComponentName componentName = new ComponentName(getPackageName(), LaunchActivity.class.getCanonicalName()); + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + ArrayList dialogs = new ArrayList<>(); + ArrayList chats = new ArrayList<>(); + ArrayList users = new ArrayList<>(); + try { + ArrayList usersToLoad = new ArrayList<>(); + usersToLoad.add(UserConfig.getClientUserId()); + ArrayList chatsToLoad = new ArrayList<>(); + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT did FROM dialogs ORDER BY date DESC LIMIT %d,%d", 0, 20)); + while (cursor.next()) { + long id = cursor.longValue(0); + + int lower_id = (int) id; + int high_id = (int) (id >> 32); + if (lower_id != 0) { + if (high_id == 1) { + continue; + } else { + if (lower_id > 0) { + if (!usersToLoad.contains(lower_id)) { + usersToLoad.add(lower_id); + } + } else { + if (!chatsToLoad.contains(-lower_id)) { + chatsToLoad.add(-lower_id); + } + } + } + } else { + continue; + } + dialogs.add(lower_id); + if (dialogs.size() == 8) { + break; + } + } + cursor.dispose(); + if (!chatsToLoad.isEmpty()) { + MessagesStorage.getInstance().getChatsInternal(TextUtils.join(",", chatsToLoad), chats); + } + if (!usersToLoad.isEmpty()) { + MessagesStorage.getInstance().getUsersInternal(TextUtils.join(",", usersToLoad), users); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + for (int a = 0; a < dialogs.size(); a++) { + float score = (a + 1) / 20.0f; + Bundle extras = new Bundle(); + Icon icon = null; + String name = null; + int id = dialogs.get(a); + if (id > 0) { + for (int b = 0; b < users.size(); b++) { + TLRPC.User user = users.get(b); + if (user.id == id) { + extras.putLong("dialogId", (long) id); + if (user.photo != null && user.photo.photo_small != null) { + icon = createRoundBitmap(FileLoader.getPathToAttach(user.photo.photo_small, true)); + } + name = ContactsController.formatName(user.first_name, user.last_name); + break; + } + } + } else { + for (int b = 0; b < chats.size(); b++) { + TLRPC.Chat chat = chats.get(b); + if (chat.id == -id) { + extras.putLong("dialogId", (long) id); + if (chat.photo != null && chat.photo.photo_small != null) { + icon = createRoundBitmap(FileLoader.getPathToAttach(chat.photo.photo_small, true)); + } + name = chat.title; + break; + } + } + } + if (name != null) { + if (icon == null) { + icon = Icon.createWithResource(ApplicationLoader.applicationContext, R.drawable.logo_avatar); + } + targets.add(new ChooserTarget(name, icon, score, componentName, extras)); + } + } + semaphore.release(); + } + }); + try { + semaphore.acquire(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + return targets; + } + + private Icon createRoundBitmap(File path) { + try { + Bitmap bitmap = BitmapFactory.decodeFile(path.toString()); + if (bitmap != null) { + Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); + result.eraseColor(Color.TRANSPARENT); + Canvas canvas = new Canvas(result); + BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + if (roundPaint == null) { + roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + bitmapRect = new RectF(); + } + roundPaint.setShader(shader); + bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); + canvas.drawRoundRect(bitmapRect, bitmap.getWidth(), bitmap.getHeight(), roundPaint); + return Icon.createWithBitmap(result); + } + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + return null; + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index eb8acd4d9..8b8563a1b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -38,6 +38,7 @@ public class UserConfig { public static int autoLockIn = 60 * 60; public static int lastPauseTime = 0; public static boolean isWaitingForPasscodeEnter = false; + public static boolean useFingerprint = true; public static int lastUpdateVersion; public static int lastContactsSyncTime; public static boolean channelsLoaded = false; @@ -79,6 +80,7 @@ public class UserConfig { editor.putInt("lastUpdateVersion", lastUpdateVersion); editor.putInt("lastContactsSyncTime", lastContactsSyncTime); editor.putBoolean("channelsLoaded", channelsLoaded); + editor.putBoolean("useFingerprint", useFingerprint); if (currentUser != null) { if (withFile) { @@ -128,7 +130,7 @@ public class UserConfig { public static void loadConfig() { synchronized (sync) { - final File configFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "user.dat"); + final File configFile = new File(ApplicationLoader.getFilesDirFixed(), "user.dat"); if (configFile.exists()) { try { SerializedData data = new SerializedData(configFile); @@ -207,6 +209,7 @@ public class UserConfig { passcodeType = preferences.getInt("passcodeType", 0); autoLockIn = preferences.getInt("autoLockIn", 60 * 60); lastPauseTime = preferences.getInt("lastPauseTime", 0); + useFingerprint = preferences.getBoolean("useFingerprint", true); lastUpdateVersion = preferences.getInt("lastUpdateVersion", 511); lastContactsSyncTime = preferences.getInt("lastContactsSyncTime", (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60); channelsLoaded = preferences.getBoolean("channelsLoaded", false); @@ -281,6 +284,7 @@ public class UserConfig { passcodeSalt = new byte[0]; autoLockIn = 60 * 60; lastPauseTime = 0; + useFingerprint = true; isWaitingForPasscodeEnter = false; lastUpdateVersion = BuildVars.BUILD_VERSION; lastContactsSyncTime = (int) (System.currentTimeMillis() / 1000) - 23 * 60 * 60; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java index 882339fbd..c4c4e2e0b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index ab94d2ad5..b8a415250 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -46,17 +46,11 @@ public class Utilities { } public native static void loadBitmap(String path, Bitmap bitmap, int scale, int width, int height, int stride); - public native static int pinBitmap(Bitmap bitmap); - public native static void blurBitmap(Object bitmap, int radius, int unpin); - public native static void calcCDT(ByteBuffer hsvBuffer, int width, int height, ByteBuffer buffer); - - public native static Bitmap loadWebpImage(ByteBuffer buffer, int len, BitmapFactory.Options options); - + public native static boolean loadWebpImage(Bitmap bitmap, ByteBuffer buffer, int len, BitmapFactory.Options options, boolean unpin); public native static int convertVideoFrame(ByteBuffer src, ByteBuffer dest, int destFormat, int width, int height, int padding, int swap); - private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length); public static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, boolean changeIv, int offset, int length) { @@ -155,6 +149,11 @@ public class Utilities { } } + String hex = bytesToHex(prime); + if (hex.equals("C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B")) { + return true; + } + BigInteger dhBI2 = dhBI.subtract(BigInteger.valueOf(1)).divide(BigInteger.valueOf(2)); return !(!dhBI.isProbablePrime(30) || !dhBI2.isProbablePrime(30)); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java index cc258b89d..39bccc1e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java index 82bc00181..9176c2f12 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java index 15b393445..37b122bca 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/WearReplyReceiver.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/query/BotQuery.java b/TMessagesProj/src/main/java/org/telegram/messenger/query/BotQuery.java index 91f46880b..c4678265d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/query/BotQuery.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/query/BotQuery.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/query/MessagesSearchQuery.java b/TMessagesProj/src/main/java/org/telegram/messenger/query/MessagesSearchQuery.java index 4d9145287..60becdf6a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/query/MessagesSearchQuery.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/query/MessagesSearchQuery.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/query/ReplyMessageQuery.java b/TMessagesProj/src/main/java/org/telegram/messenger/query/ReplyMessageQuery.java index 50d7a5ad0..6111eb99d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/query/ReplyMessageQuery.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/query/ReplyMessageQuery.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/query/SharedMediaQuery.java b/TMessagesProj/src/main/java/org/telegram/messenger/query/SharedMediaQuery.java index 9c31b1a47..179071c3e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/query/SharedMediaQuery.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/query/SharedMediaQuery.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.query; @@ -37,7 +37,8 @@ public class SharedMediaQuery { public final static int MEDIA_FILE = 1; public final static int MEDIA_AUDIO = 2; public final static int MEDIA_URL = 3; - public final static int MEDIA_TYPES_COUNT = 4; + public final static int MEDIA_MUSIC = 4; + public final static int MEDIA_TYPES_COUNT = 5; public static void loadMedia(final long uid, final int offset, final int count, final int max_id, final int type, final boolean fromCache, final int classGuid) { final boolean isChannel = (int) uid < 0 && ChatObject.isChannel(-(int) uid); @@ -58,6 +59,8 @@ public class SharedMediaQuery { req.filter = new TLRPC.TL_inputMessagesFilterAudio(); } else if (type == MEDIA_URL) { req.filter = new TLRPC.TL_inputMessagesFilterUrl(); + } else if (type == MEDIA_MUSIC) { + req.filter = new TLRPC.TL_inputMessagesFilterAudioDocuments(); } req.q = ""; req.peer = MessagesController.getInputPeer(lower_part); @@ -101,6 +104,8 @@ public class SharedMediaQuery { req.filter = new TLRPC.TL_inputMessagesFilterAudio(); } else if (type == MEDIA_URL) { req.filter = new TLRPC.TL_inputMessagesFilterUrl(); + } else if (type == MEDIA_MUSIC) { + req.filter = new TLRPC.TL_inputMessagesFilterAudioDocuments(); } req.q = ""; req.peer = MessagesController.getInputPeer(lower_part); @@ -144,6 +149,8 @@ public class SharedMediaQuery { } else if (message.media instanceof TLRPC.TL_messageMediaDocument) { if (MessageObject.isStickerMessage(message)) { return -1; + } else if (MessageObject.isMusicMessage(message)) { + return MEDIA_MUSIC; } else { return MEDIA_FILE; } @@ -367,9 +374,9 @@ public class SharedMediaQuery { } cursor.dispose(); if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, messageMaxId, holeMessageId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid > 0 AND mid < %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, messageMaxId, holeMessageId, type, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, messageMaxId, type, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid > 0 AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, messageMaxId, type, countToLoad)); } } else { long holeMessageId = 0; @@ -382,9 +389,9 @@ public class SharedMediaQuery { } cursor.dispose(); if (holeMessageId > 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND type = %d AND mid >= %d ORDER BY date DESC, mid DESC LIMIT %d,%d", uid, type, holeMessageId, offset, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid >= %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d,%d", uid, holeMessageId, type, offset, countToLoad)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d,%d", uid, type, offset, countToLoad)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid > 0 AND type = %d ORDER BY date DESC, mid DESC LIMIT %d,%d", uid, type, offset, countToLoad)); } } } else { @@ -500,7 +507,7 @@ public class SharedMediaQuery { public void run() { final ArrayList arrayList = new ArrayList<>(); try { - SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", uid, max_id, MEDIA_FILE)); + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", uid, max_id, MEDIA_MUSIC)); while (cursor.next()) { NativeByteBuffer data = new NativeByteBuffer(cursor.byteArrayLength(0)); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/query/StickersQuery.java b/TMessagesProj/src/main/java/org/telegram/messenger/query/StickersQuery.java index 378d72a0e..db9711919 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/query/StickersQuery.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/query/StickersQuery.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerView.java b/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerView.java index 3ace50994..f780729bf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerView.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/support/widget/RecyclerView.java @@ -58,8 +58,13 @@ import android.view.ViewParent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.Interpolator; +import android.widget.AbsListView; +import android.widget.EdgeEffect; + +import org.telegram.messenger.FileLog; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; @@ -312,6 +317,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro private int mLayoutOrScrollCounter = 0; private int topGlowOffset = 0; + private int glowColor = 0; private EdgeEffectCompat mLeftGlow, mTopGlow, mRightGlow, mBottomGlow; ItemAnimator mItemAnimator = new DefaultItemAnimator(); @@ -1852,6 +1858,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } else { mLeftGlow.setSize(getMeasuredHeight(), getMeasuredWidth()); } + applyEdgeEffectColor(mLeftGlow); } void ensureRightGlow() { @@ -1865,6 +1872,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } else { mRightGlow.setSize(getMeasuredHeight(), getMeasuredWidth()); } + applyEdgeEffectColor(mRightGlow); } void ensureTopGlow() { @@ -1878,7 +1886,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } else { mTopGlow.setSize(getMeasuredWidth(), getMeasuredHeight()); } - + applyEdgeEffectColor(mTopGlow); } void ensureBottomGlow() { @@ -1892,6 +1900,22 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro } else { mBottomGlow.setSize(getMeasuredWidth(), getMeasuredHeight()); } + applyEdgeEffectColor(mBottomGlow); + } + + void applyEdgeEffectColor(EdgeEffectCompat edgeEffectCompat) { + if (Build.VERSION.SDK_INT >= 21 && glowColor != 0) { + try { + Field field = EdgeEffectCompat.class.getDeclaredField("mEdgeEffect"); + field.setAccessible(true); + EdgeEffect edgeEffect = (EdgeEffect) field.get(edgeEffectCompat); + if (edgeEffect != null) { + edgeEffect.setColor(glowColor); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } } void invalidateGlows() { @@ -3141,6 +3165,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro topGlowOffset = offset; } + public void setGlowColor(int color) { + glowColor = color; + } + void markItemDecorInsetsDirty() { final int childCount = mChildHelper.getUnfilteredChildCount(); for (int i = 0; i < childCount; i++) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java index c2c8bd625..eae9c50b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.video; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/Mp4Movie.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/Mp4Movie.java index 7571c5c03..fcdc92232 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/Mp4Movie.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/Mp4Movie.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.video; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/Sample.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/Sample.java index 566c7ef2c..ca0850bc0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/Sample.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/Sample.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.video; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/Track.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/Track.java index fe7c937c4..4285fd347 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/Track.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/Track.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.messenger.video; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/ImageLoader.java deleted file mode 100644 index f5225e60a..000000000 --- a/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/ImageLoader.java +++ /dev/null @@ -1,507 +0,0 @@ -/** - * Copyright (C) 2013 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.messenger.volley.toolbox; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.os.Handler; -import android.os.Looper; -import android.widget.ImageView; -import android.widget.ImageView.ScaleType; -import org.telegram.messenger.volley.Request; -import org.telegram.messenger.volley.RequestQueue; -import org.telegram.messenger.volley.Response.ErrorListener; -import org.telegram.messenger.volley.Response.Listener; -import org.telegram.messenger.volley.VolleyError; - -import java.util.HashMap; -import java.util.LinkedList; - -/** - * Helper that handles loading and caching images from remote URLs. - * - * The simple way to use this class is to call {@link ImageLoader#get(String, ImageListener)} - * and to pass in the default image listener provided by - * {@link ImageLoader#getImageListener(ImageView, int, int)}. Note that all function calls to - * this class must be made from the main thead, and all responses will be delivered to the main - * thread as well. - */ -public class ImageLoader { - /** RequestQueue for dispatching ImageRequests onto. */ - private final RequestQueue mRequestQueue; - - /** Amount of time to wait after first response arrives before delivering all responses. */ - private int mBatchResponseDelayMs = 100; - - /** The cache implementation to be used as an L1 cache before calling into volley. */ - private final ImageCache mCache; - - /** - * HashMap of Cache keys -> BatchedImageRequest used to track in-flight requests so - * that we can coalesce multiple requests to the same URL into a single network request. - */ - private final HashMap mInFlightRequests = - new HashMap(); - - /** HashMap of the currently pending responses (waiting to be delivered). */ - private final HashMap mBatchedResponses = - new HashMap(); - - /** Handler to the main thread. */ - private final Handler mHandler = new Handler(Looper.getMainLooper()); - - /** Runnable for in-flight response delivery. */ - private Runnable mRunnable; - - /** - * Simple cache adapter interface. If provided to the ImageLoader, it - * will be used as an L1 cache before dispatch to Volley. Implementations - * must not block. Implementation with an LruCache is recommended. - */ - public interface ImageCache { - public Bitmap getBitmap(String url); - public void putBitmap(String url, Bitmap bitmap); - } - - /** - * Constructs a new ImageLoader. - * @param queue The RequestQueue to use for making image requests. - * @param imageCache The cache to use as an L1 cache. - */ - public ImageLoader(RequestQueue queue, ImageCache imageCache) { - mRequestQueue = queue; - mCache = imageCache; - } - - /** - * The default implementation of ImageListener which handles basic functionality - * of showing a default image until the network response is received, at which point - * it will switch to either the actual image or the error image. - * @param view The imageView that the listener is associated with. - * @param defaultImageResId Default image resource ID to use, or 0 if it doesn't exist. - * @param errorImageResId Error image resource ID to use, or 0 if it doesn't exist. - */ - public static ImageListener getImageListener(final ImageView view, - final int defaultImageResId, final int errorImageResId) { - return new ImageListener() { - @Override - public void onErrorResponse(VolleyError error) { - if (errorImageResId != 0) { - view.setImageResource(errorImageResId); - } - } - - @Override - public void onResponse(ImageContainer response, boolean isImmediate) { - if (response.getBitmap() != null) { - view.setImageBitmap(response.getBitmap()); - } else if (defaultImageResId != 0) { - view.setImageResource(defaultImageResId); - } - } - }; - } - - /** - * Interface for the response handlers on image requests. - * - * The call flow is this: - * 1. Upon being attached to a request, onResponse(response, true) will - * be invoked to reflect any cached data that was already available. If the - * data was available, response.getBitmap() will be non-null. - * - * 2. After a network response returns, only one of the following cases will happen: - * - onResponse(response, false) will be called if the image was loaded. - * or - * - onErrorResponse will be called if there was an error loading the image. - */ - public interface ImageListener extends ErrorListener { - /** - * Listens for non-error changes to the loading of the image request. - * - * @param response Holds all information pertaining to the request, as well - * as the bitmap (if it is loaded). - * @param isImmediate True if this was called during ImageLoader.get() variants. - * This can be used to differentiate between a cached image loading and a network - * image loading in order to, for example, run an animation to fade in network loaded - * images. - */ - public void onResponse(ImageContainer response, boolean isImmediate); - } - - /** - * Checks if the item is available in the cache. - * @param requestUrl The url of the remote image - * @param maxWidth The maximum width of the returned image. - * @param maxHeight The maximum height of the returned image. - * @return True if the item exists in cache, false otherwise. - */ - public boolean isCached(String requestUrl, int maxWidth, int maxHeight) { - return isCached(requestUrl, maxWidth, maxHeight, ScaleType.CENTER_INSIDE); - } - - /** - * Checks if the item is available in the cache. - * - * @param requestUrl The url of the remote image - * @param maxWidth The maximum width of the returned image. - * @param maxHeight The maximum height of the returned image. - * @param scaleType The scaleType of the imageView. - * @return True if the item exists in cache, false otherwise. - */ - public boolean isCached(String requestUrl, int maxWidth, int maxHeight, ScaleType scaleType) { - throwIfNotOnMainThread(); - - String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight, scaleType); - return mCache.getBitmap(cacheKey) != null; - } - - /** - * Returns an ImageContainer for the requested URL. - * - * The ImageContainer will contain either the specified default bitmap or the loaded bitmap. - * If the default was returned, the {@link ImageLoader} will be invoked when the - * request is fulfilled. - * - * @param requestUrl The URL of the image to be loaded. - */ - public ImageContainer get(String requestUrl, final ImageListener listener) { - return get(requestUrl, listener, 0, 0); - } - - /** - * Equivalent to calling {@link #get(String, ImageListener, int, int, ScaleType)} with - * {@code Scaletype == ScaleType.CENTER_INSIDE}. - */ - public ImageContainer get(String requestUrl, ImageListener imageListener, - int maxWidth, int maxHeight) { - return get(requestUrl, imageListener, maxWidth, maxHeight, ScaleType.CENTER_INSIDE); - } - - /** - * Issues a bitmap request with the given URL if that image is not available - * in the cache, and returns a bitmap container that contains all of the data - * relating to the request (as well as the default image if the requested - * image is not available). - * @param requestUrl The url of the remote image - * @param imageListener The listener to call when the remote image is loaded - * @param maxWidth The maximum width of the returned image. - * @param maxHeight The maximum height of the returned image. - * @param scaleType The ImageViews ScaleType used to calculate the needed image size. - * @return A container object that contains all of the properties of the request, as well as - * the currently available image (default if remote is not loaded). - */ - public ImageContainer get(String requestUrl, ImageListener imageListener, - int maxWidth, int maxHeight, ScaleType scaleType) { - - // only fulfill requests that were initiated from the main thread. - throwIfNotOnMainThread(); - - final String cacheKey = getCacheKey(requestUrl, maxWidth, maxHeight, scaleType); - - // Try to look up the request in the cache of remote images. - Bitmap cachedBitmap = mCache.getBitmap(cacheKey); - if (cachedBitmap != null) { - // Return the cached bitmap. - ImageContainer container = new ImageContainer(cachedBitmap, requestUrl, null, null); - imageListener.onResponse(container, true); - return container; - } - - // The bitmap did not exist in the cache, fetch it! - ImageContainer imageContainer = - new ImageContainer(null, requestUrl, cacheKey, imageListener); - - // Update the caller to let them know that they should use the default bitmap. - imageListener.onResponse(imageContainer, true); - - // Check to see if a request is already in-flight. - BatchedImageRequest request = mInFlightRequests.get(cacheKey); - if (request != null) { - // If it is, add this request to the list of listeners. - request.addContainer(imageContainer); - return imageContainer; - } - - // The request is not already in flight. Send the new request to the network and - // track it. - Request newRequest = makeImageRequest(requestUrl, maxWidth, maxHeight, scaleType, - cacheKey); - - mRequestQueue.add(newRequest); - mInFlightRequests.put(cacheKey, - new BatchedImageRequest(newRequest, imageContainer)); - return imageContainer; - } - - protected Request makeImageRequest(String requestUrl, int maxWidth, int maxHeight, - ScaleType scaleType, final String cacheKey) { - return new ImageRequest(requestUrl, new Listener() { - @Override - public void onResponse(Bitmap response) { - onGetImageSuccess(cacheKey, response); - } - }, maxWidth, maxHeight, scaleType, Config.RGB_565, new ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - onGetImageError(cacheKey, error); - } - }); - } - - /** - * Sets the amount of time to wait after the first response arrives before delivering all - * responses. Batching can be disabled entirely by passing in 0. - * @param newBatchedResponseDelayMs The time in milliseconds to wait. - */ - public void setBatchedResponseDelay(int newBatchedResponseDelayMs) { - mBatchResponseDelayMs = newBatchedResponseDelayMs; - } - - /** - * Handler for when an image was successfully loaded. - * @param cacheKey The cache key that is associated with the image request. - * @param response The bitmap that was returned from the network. - */ - protected void onGetImageSuccess(String cacheKey, Bitmap response) { - // cache the image that was fetched. - mCache.putBitmap(cacheKey, response); - - // remove the request from the list of in-flight requests. - BatchedImageRequest request = mInFlightRequests.remove(cacheKey); - - if (request != null) { - // Update the response bitmap. - request.mResponseBitmap = response; - - // Send the batched response - batchResponse(cacheKey, request); - } - } - - /** - * Handler for when an image failed to load. - * @param cacheKey The cache key that is associated with the image request. - */ - protected void onGetImageError(String cacheKey, VolleyError error) { - // Notify the requesters that something failed via a null result. - // Remove this request from the list of in-flight requests. - BatchedImageRequest request = mInFlightRequests.remove(cacheKey); - - if (request != null) { - // Set the error for this request - request.setError(error); - - // Send the batched response - batchResponse(cacheKey, request); - } - } - - /** - * Container object for all of the data surrounding an image request. - */ - public class ImageContainer { - /** - * The most relevant bitmap for the container. If the image was in cache, the - * Holder to use for the final bitmap (the one that pairs to the requested URL). - */ - private Bitmap mBitmap; - - private final ImageListener mListener; - - /** The cache key that was associated with the request */ - private final String mCacheKey; - - /** The request URL that was specified */ - private final String mRequestUrl; - - /** - * Constructs a BitmapContainer object. - * @param bitmap The final bitmap (if it exists). - * @param requestUrl The requested URL for this container. - * @param cacheKey The cache key that identifies the requested URL for this container. - */ - public ImageContainer(Bitmap bitmap, String requestUrl, - String cacheKey, ImageListener listener) { - mBitmap = bitmap; - mRequestUrl = requestUrl; - mCacheKey = cacheKey; - mListener = listener; - } - - /** - * Releases interest in the in-flight request (and cancels it if no one else is listening). - */ - public void cancelRequest() { - if (mListener == null) { - return; - } - - BatchedImageRequest request = mInFlightRequests.get(mCacheKey); - if (request != null) { - boolean canceled = request.removeContainerAndCancelIfNecessary(this); - if (canceled) { - mInFlightRequests.remove(mCacheKey); - } - } else { - // check to see if it is already batched for delivery. - request = mBatchedResponses.get(mCacheKey); - if (request != null) { - request.removeContainerAndCancelIfNecessary(this); - if (request.mContainers.size() == 0) { - mBatchedResponses.remove(mCacheKey); - } - } - } - } - - /** - * Returns the bitmap associated with the request URL if it has been loaded, null otherwise. - */ - public Bitmap getBitmap() { - return mBitmap; - } - - /** - * Returns the requested URL for this container. - */ - public String getRequestUrl() { - return mRequestUrl; - } - } - - /** - * Wrapper class used to map a Request to the set of active ImageContainer objects that are - * interested in its results. - */ - private class BatchedImageRequest { - /** The request being tracked */ - private final Request mRequest; - - /** The result of the request being tracked by this item */ - private Bitmap mResponseBitmap; - - /** Error if one occurred for this response */ - private VolleyError mError; - - /** List of all of the active ImageContainers that are interested in the request */ - private final LinkedList mContainers = new LinkedList(); - - /** - * Constructs a new BatchedImageRequest object - * @param request The request being tracked - * @param container The ImageContainer of the person who initiated the request. - */ - public BatchedImageRequest(Request request, ImageContainer container) { - mRequest = request; - mContainers.add(container); - } - - /** - * Set the error for this response - */ - public void setError(VolleyError error) { - mError = error; - } - - /** - * Get the error for this response - */ - public VolleyError getError() { - return mError; - } - - /** - * Adds another ImageContainer to the list of those interested in the results of - * the request. - */ - public void addContainer(ImageContainer container) { - mContainers.add(container); - } - - /** - * Detatches the bitmap container from the request and cancels the request if no one is - * left listening. - * @param container The container to remove from the list - * @return True if the request was canceled, false otherwise. - */ - public boolean removeContainerAndCancelIfNecessary(ImageContainer container) { - mContainers.remove(container); - if (mContainers.size() == 0) { - mRequest.cancel(); - return true; - } - return false; - } - } - - /** - * Starts the runnable for batched delivery of responses if it is not already started. - * @param cacheKey The cacheKey of the response being delivered. - * @param request The BatchedImageRequest to be delivered. - */ - private void batchResponse(String cacheKey, BatchedImageRequest request) { - mBatchedResponses.put(cacheKey, request); - // If we don't already have a batch delivery runnable in flight, make a new one. - // Note that this will be used to deliver responses to all callers in mBatchedResponses. - if (mRunnable == null) { - mRunnable = new Runnable() { - @Override - public void run() { - for (BatchedImageRequest bir : mBatchedResponses.values()) { - for (ImageContainer container : bir.mContainers) { - // If one of the callers in the batched request canceled the request - // after the response was received but before it was delivered, - // skip them. - if (container.mListener == null) { - continue; - } - if (bir.getError() == null) { - container.mBitmap = bir.mResponseBitmap; - container.mListener.onResponse(container, false); - } else { - container.mListener.onErrorResponse(bir.getError()); - } - } - } - mBatchedResponses.clear(); - mRunnable = null; - } - - }; - // Post the runnable. - mHandler.postDelayed(mRunnable, mBatchResponseDelayMs); - } - } - - private void throwIfNotOnMainThread() { - if (Looper.myLooper() != Looper.getMainLooper()) { - throw new IllegalStateException("ImageLoader must be invoked from the main thread."); - } - } - /** - * Creates a cache key for use with the L1 cache. - * @param url The URL of the request. - * @param maxWidth The max-width of the output. - * @param maxHeight The max-height of the output. - * @param scaleType The scaleType of the imageView. - */ - private static String getCacheKey(String url, int maxWidth, int maxHeight, ScaleType scaleType) { - return new StringBuilder(url.length() + 12).append("#W").append(maxWidth) - .append("#H").append(maxHeight).append("#S").append(scaleType.ordinal()).append(url) - .toString(); - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/ImageRequest.java b/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/ImageRequest.java deleted file mode 100644 index 2b3ae2cd9..000000000 --- a/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/ImageRequest.java +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2011 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.messenger.volley.toolbox; - -import org.telegram.messenger.volley.DefaultRetryPolicy; -import org.telegram.messenger.volley.NetworkResponse; -import org.telegram.messenger.volley.ParseError; -import org.telegram.messenger.volley.Request; -import org.telegram.messenger.volley.Response; -import org.telegram.messenger.volley.VolleyLog; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.widget.ImageView.ScaleType; - -/** - * A canned request for getting an image at a given URL and calling - * back with a decoded Bitmap. - */ -public class ImageRequest extends Request { - /** Socket timeout in milliseconds for image requests */ - private static final int IMAGE_TIMEOUT_MS = 1000; - - /** Default number of retries for image requests */ - private static final int IMAGE_MAX_RETRIES = 2; - - /** Default backoff multiplier for image requests */ - private static final float IMAGE_BACKOFF_MULT = 2f; - - private final Response.Listener mListener; - private final Config mDecodeConfig; - private final int mMaxWidth; - private final int mMaxHeight; - private ScaleType mScaleType; - - /** Decoding lock so that we don't decode more than one image at a time (to avoid OOM's) */ - private static final Object sDecodeLock = new Object(); - - /** - * Creates a new image request, decoding to a maximum specified width and - * height. If both width and height are zero, the image will be decoded to - * its natural size. If one of the two is nonzero, that dimension will be - * clamped and the other one will be set to preserve the image's aspect - * ratio. If both width and height are nonzero, the image will be decoded to - * be fit in the rectangle of dimensions width x height while keeping its - * aspect ratio. - * - * @param url URL of the image - * @param listener Listener to receive the decoded bitmap - * @param maxWidth Maximum width to decode this bitmap to, or zero for none - * @param maxHeight Maximum height to decode this bitmap to, or zero for - * none - * @param scaleType The ImageViews ScaleType used to calculate the needed image size. - * @param decodeConfig Format to decode the bitmap to - * @param errorListener Error listener, or null to ignore errors - */ - public ImageRequest(String url, Response.Listener listener, int maxWidth, int maxHeight, - ScaleType scaleType, Config decodeConfig, Response.ErrorListener errorListener) { - super(Method.GET, url, errorListener); - setRetryPolicy( - new DefaultRetryPolicy(IMAGE_TIMEOUT_MS, IMAGE_MAX_RETRIES, IMAGE_BACKOFF_MULT)); - mListener = listener; - mDecodeConfig = decodeConfig; - mMaxWidth = maxWidth; - mMaxHeight = maxHeight; - mScaleType = scaleType; - } - - /** - * For API compatibility with the pre-ScaleType variant of the constructor. Equivalent to - * the normal constructor with {@code ScaleType.CENTER_INSIDE}. - */ - @Deprecated - public ImageRequest(String url, Response.Listener listener, int maxWidth, int maxHeight, - Config decodeConfig, Response.ErrorListener errorListener) { - this(url, listener, maxWidth, maxHeight, - ScaleType.CENTER_INSIDE, decodeConfig, errorListener); - } - @Override - public Priority getPriority() { - return Priority.LOW; - } - - /** - * Scales one side of a rectangle to fit aspect ratio. - * - * @param maxPrimary Maximum size of the primary dimension (i.e. width for - * max width), or zero to maintain aspect ratio with secondary - * dimension - * @param maxSecondary Maximum size of the secondary dimension, or zero to - * maintain aspect ratio with primary dimension - * @param actualPrimary Actual size of the primary dimension - * @param actualSecondary Actual size of the secondary dimension - * @param scaleType The ScaleType used to calculate the needed image size. - */ - private static int getResizedDimension(int maxPrimary, int maxSecondary, int actualPrimary, - int actualSecondary, ScaleType scaleType) { - - // If no dominant value at all, just return the actual. - if ((maxPrimary == 0) && (maxSecondary == 0)) { - return actualPrimary; - } - - // If ScaleType.FIT_XY fill the whole rectangle, ignore ratio. - if (scaleType == ScaleType.FIT_XY) { - if (maxPrimary == 0) { - return actualPrimary; - } - return maxPrimary; - } - - // If primary is unspecified, scale primary to match secondary's scaling ratio. - if (maxPrimary == 0) { - double ratio = (double) maxSecondary / (double) actualSecondary; - return (int) (actualPrimary * ratio); - } - - if (maxSecondary == 0) { - return maxPrimary; - } - - double ratio = (double) actualSecondary / (double) actualPrimary; - int resized = maxPrimary; - - // If ScaleType.CENTER_CROP fill the whole rectangle, preserve aspect ratio. - if (scaleType == ScaleType.CENTER_CROP) { - if ((resized * ratio) < maxSecondary) { - resized = (int) (maxSecondary / ratio); - } - return resized; - } - - if ((resized * ratio) > maxSecondary) { - resized = (int) (maxSecondary / ratio); - } - return resized; - } - - @Override - protected Response parseNetworkResponse(NetworkResponse response) { - // Serialize all decode on a global lock to reduce concurrent heap usage. - synchronized (sDecodeLock) { - try { - return doParse(response); - } catch (OutOfMemoryError e) { - VolleyLog.e("Caught OOM for %d byte image, url=%s", response.data.length, getUrl()); - return Response.error(new ParseError(e)); - } - } - } - - /** - * The real guts of parseNetworkResponse. Broken out for readability. - */ - private Response doParse(NetworkResponse response) { - byte[] data = response.data; - BitmapFactory.Options decodeOptions = new BitmapFactory.Options(); - Bitmap bitmap = null; - if (mMaxWidth == 0 && mMaxHeight == 0) { - decodeOptions.inPreferredConfig = mDecodeConfig; - bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); - } else { - // If we have to resize this image, first get the natural bounds. - decodeOptions.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); - int actualWidth = decodeOptions.outWidth; - int actualHeight = decodeOptions.outHeight; - - // Then compute the dimensions we would ideally like to decode to. - int desiredWidth = getResizedDimension(mMaxWidth, mMaxHeight, - actualWidth, actualHeight, mScaleType); - int desiredHeight = getResizedDimension(mMaxHeight, mMaxWidth, - actualHeight, actualWidth, mScaleType); - - // Decode to the nearest power of two scaling factor. - decodeOptions.inJustDecodeBounds = false; - // TODO(ficus): Do we need this or is it okay since API 8 doesn't support it? - // decodeOptions.inPreferQualityOverSpeed = PREFER_QUALITY_OVER_SPEED; - decodeOptions.inSampleSize = - findBestSampleSize(actualWidth, actualHeight, desiredWidth, desiredHeight); - Bitmap tempBitmap = - BitmapFactory.decodeByteArray(data, 0, data.length, decodeOptions); - - // If necessary, scale down to the maximal acceptable size. - if (tempBitmap != null && (tempBitmap.getWidth() > desiredWidth || - tempBitmap.getHeight() > desiredHeight)) { - bitmap = Bitmap.createScaledBitmap(tempBitmap, - desiredWidth, desiredHeight, true); - tempBitmap.recycle(); - } else { - bitmap = tempBitmap; - } - } - - if (bitmap == null) { - return Response.error(new ParseError(response)); - } else { - return Response.success(bitmap, HttpHeaderParser.parseCacheHeaders(response)); - } - } - - @Override - protected void deliverResponse(Bitmap response) { - mListener.onResponse(response); - } - - /** - * Returns the largest power-of-two divisor for use in downscaling a bitmap - * that will not result in the scaling past the desired dimensions. - * - * @param actualWidth Actual width of the bitmap - * @param actualHeight Actual height of the bitmap - * @param desiredWidth Desired width of the bitmap - * @param desiredHeight Desired height of the bitmap - */ - // Visible for testing. - static int findBestSampleSize( - int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) { - double wr = (double) actualWidth / desiredWidth; - double hr = (double) actualHeight / desiredHeight; - double ratio = Math.min(wr, hr); - float n = 1.0f; - while ((n * 2) <= ratio) { - n *= 2; - } - - return (int) n; - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/NetworkImageView.java b/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/NetworkImageView.java deleted file mode 100644 index 465596a4c..000000000 --- a/TMessagesProj/src/main/java/org/telegram/messenger/volley/toolbox/NetworkImageView.java +++ /dev/null @@ -1,220 +0,0 @@ -/** - * Copyright (C) 2013 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.messenger.volley.toolbox; - -import android.content.Context; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.ViewGroup.LayoutParams; -import android.widget.ImageView; - -import org.telegram.messenger.volley.VolleyError; -import org.telegram.messenger.volley.toolbox.ImageLoader.ImageContainer; -import org.telegram.messenger.volley.toolbox.ImageLoader.ImageListener; - -/** - * Handles fetching an image from a URL as well as the life-cycle of the - * associated request. - */ -public class NetworkImageView extends ImageView { - /** The URL of the network image to load */ - private String mUrl; - - /** - * Resource ID of the image to be used as a placeholder until the network image is loaded. - */ - private int mDefaultImageId; - - /** - * Resource ID of the image to be used if the network response fails. - */ - private int mErrorImageId; - - /** Local copy of the ImageLoader. */ - private ImageLoader mImageLoader; - - /** Current ImageContainer. (either in-flight or finished) */ - private ImageContainer mImageContainer; - - public NetworkImageView(Context context) { - this(context, null); - } - - public NetworkImageView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public NetworkImageView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - /** - * Sets URL of the image that should be loaded into this view. Note that calling this will - * immediately either set the cached image (if available) or the default image specified by - * {@link NetworkImageView#setDefaultImageResId(int)} on the view. - * - * NOTE: If applicable, {@link NetworkImageView#setDefaultImageResId(int)} and - * {@link NetworkImageView#setErrorImageResId(int)} should be called prior to calling - * this function. - * - * @param url The URL that should be loaded into this ImageView. - * @param imageLoader ImageLoader that will be used to make the request. - */ - public void setImageUrl(String url, ImageLoader imageLoader) { - mUrl = url; - mImageLoader = imageLoader; - // The URL has potentially changed. See if we need to load it. - loadImageIfNecessary(false); - } - - /** - * Sets the default image resource ID to be used for this view until the attempt to load it - * completes. - */ - public void setDefaultImageResId(int defaultImage) { - mDefaultImageId = defaultImage; - } - - /** - * Sets the error image resource ID to be used for this view in the event that the image - * requested fails to load. - */ - public void setErrorImageResId(int errorImage) { - mErrorImageId = errorImage; - } - - /** - * Loads the image for the view if it isn't already loaded. - * @param isInLayoutPass True if this was invoked from a layout pass, false otherwise. - */ - void loadImageIfNecessary(final boolean isInLayoutPass) { - int width = getWidth(); - int height = getHeight(); - ScaleType scaleType = getScaleType(); - - boolean wrapWidth = false, wrapHeight = false; - if (getLayoutParams() != null) { - wrapWidth = getLayoutParams().width == LayoutParams.WRAP_CONTENT; - wrapHeight = getLayoutParams().height == LayoutParams.WRAP_CONTENT; - } - - // if the view's bounds aren't known yet, and this is not a wrap-content/wrap-content - // view, hold off on loading the image. - boolean isFullyWrapContent = wrapWidth && wrapHeight; - if (width == 0 && height == 0 && !isFullyWrapContent) { - return; - } - - // if the URL to be loaded in this view is empty, cancel any old requests and clear the - // currently loaded image. - if (TextUtils.isEmpty(mUrl)) { - if (mImageContainer != null) { - mImageContainer.cancelRequest(); - mImageContainer = null; - } - setDefaultImageOrNull(); - return; - } - - // if there was an old request in this view, check if it needs to be canceled. - if (mImageContainer != null && mImageContainer.getRequestUrl() != null) { - if (mImageContainer.getRequestUrl().equals(mUrl)) { - // if the request is from the same URL, return. - return; - } else { - // if there is a pre-existing request, cancel it if it's fetching a different URL. - mImageContainer.cancelRequest(); - setDefaultImageOrNull(); - } - } - - // Calculate the max image width / height to use while ignoring WRAP_CONTENT dimens. - int maxWidth = wrapWidth ? 0 : width; - int maxHeight = wrapHeight ? 0 : height; - - // The pre-existing content of this view didn't match the current URL. Load the new image - // from the network. - ImageContainer newContainer = mImageLoader.get(mUrl, - new ImageListener() { - @Override - public void onErrorResponse(VolleyError error) { - if (mErrorImageId != 0) { - setImageResource(mErrorImageId); - } - } - - @Override - public void onResponse(final ImageContainer response, boolean isImmediate) { - // If this was an immediate response that was delivered inside of a layout - // pass do not set the image immediately as it will trigger a requestLayout - // inside of a layout. Instead, defer setting the image by posting back to - // the main thread. - if (isImmediate && isInLayoutPass) { - post(new Runnable() { - @Override - public void run() { - onResponse(response, false); - } - }); - return; - } - - if (response.getBitmap() != null) { - setImageBitmap(response.getBitmap()); - } else if (mDefaultImageId != 0) { - setImageResource(mDefaultImageId); - } - } - }, maxWidth, maxHeight, scaleType); - - // update the ImageContainer to be the new bitmap container. - mImageContainer = newContainer; - } - - private void setDefaultImageOrNull() { - if(mDefaultImageId != 0) { - setImageResource(mDefaultImageId); - } - else { - setImageBitmap(null); - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - loadImageIfNecessary(true); - } - - @Override - protected void onDetachedFromWindow() { - if (mImageContainer != null) { - // If the view was bound to an image request, cancel it and clear - // out the image from the view. - mImageContainer.cancelRequest(); - setImageBitmap(null); - // also clear out the container so we can reload the image if necessary. - mImageContainer = null; - } - super.onDetachedFromWindow(); - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - invalidate(); - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index f3c6fb82f..f9aefbd8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -196,8 +196,8 @@ public class ConnectionsManager { native_setNetworkAvailable(isNetworkOnline()); } - public void init(int version, int layer, int apiId, String deviceModel, String systemVersion, String appVersion, String langCode, String configPath, int userId) { - native_init(version, layer, apiId, deviceModel, systemVersion, appVersion, langCode, configPath, userId); + public void init(int version, int layer, int apiId, String deviceModel, String systemVersion, String appVersion, String langCode, String configPath, String logPath, int userId) { + native_init(version, layer, apiId, deviceModel, systemVersion, appVersion, langCode, configPath, logPath, userId); checkConnection(); BroadcastReceiver networkStateReceiver = new BroadcastReceiver() { @Override @@ -363,7 +363,7 @@ public class ConnectionsManager { public static native void native_applyDatacenterAddress(int datacenterId, String ipAddress, int port); public static native int native_getConnectionState(); public static native void native_setUserId(int id); - public static native void native_init(int version, int layer, int apiId, String deviceModel, String systemVersion, String appVersion, String langCode, String configPath, int userId); + public static native void native_init(int version, int layer, int apiId, String deviceModel, String systemVersion, String appVersion, String langCode, String configPath, String logPath, int userId); public static native void native_setJava(boolean useJavaByteBuffers); public int generateClassGuid() { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/SerializedData.java b/TMessagesProj/src/main/java/org/telegram/tgnet/SerializedData.java index ceb89e13d..17c205e75 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/SerializedData.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/SerializedData.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLClassStore.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLClassStore.java index 17d515539..fe562afda 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLClassStore.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLClassStore.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLObject.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLObject.java index d7cb63b07..f320783be 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLObject.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLObject.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index b77764e81..bf045291c 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index 82cb6c55b..016d389e0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.ActionBar; @@ -22,10 +22,15 @@ import android.widget.ImageView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationCompat.AnimatorListenerAdapterProxy; +import org.telegram.messenger.AnimationCompat.AnimatorSetProxy; +import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; import org.telegram.ui.Components.LayoutHelper; +import java.util.ArrayList; + public class ActionBar extends FrameLayout { public static class ActionBarMenuOnItemClick { @@ -45,6 +50,8 @@ public class ActionBar extends FrameLayout { private ActionBarMenu menu; private ActionBarMenu actionMode; private boolean occupyStatusBar = Build.VERSION.SDK_INT >= 21; + private boolean actionModeVisible; + private boolean addToContainer = true; private boolean allowOverlayTitle; private CharSequence lastTitle; @@ -55,7 +62,6 @@ public class ActionBar extends FrameLayout { private boolean isBackOverlayVisible; protected BaseFragment parentFragment; public ActionBarMenuOnItemClick actionBarMenuOnItemClick; - private int extraHeight; public ActionBar(Context context) { super(context); @@ -68,6 +74,7 @@ public class ActionBar extends FrameLayout { backButtonImageView = new ImageView(getContext()); backButtonImageView.setScaleType(ImageView.ScaleType.CENTER); backButtonImageView.setBackgroundResource(itemsBackgroundResourceId); + backButtonImageView.setPadding(AndroidUtilities.dp(1), 0, 0, 0); addView(backButtonImageView, LayoutHelper.createFrame(54, 54, Gravity.LEFT | Gravity.TOP)); backButtonImageView.setOnClickListener(new OnClickListener() { @@ -90,6 +97,9 @@ public class ActionBar extends FrameLayout { } backButtonImageView.setVisibility(drawable == null ? GONE : VISIBLE); backButtonImageView.setImageDrawable(drawable); + if (drawable instanceof BackDrawable) { + ((BackDrawable) drawable).setRotation(isActionModeShowed() ? 1 : 0, false); + } } public void setBackButtonImage(int resource) { @@ -111,7 +121,15 @@ public class ActionBar extends FrameLayout { subTitleTextView.setLines(1); subTitleTextView.setMaxLines(1); subTitleTextView.setEllipsize(TextUtils.TruncateAt.END); - addView(subTitleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); + addView(subTitleTextView, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); + } + + public void setAddToContainer(boolean value) { + addToContainer = value; + } + + public boolean getAddToContainer() { + return addToContainer; } public void setSubtitle(CharSequence value) { @@ -136,7 +154,7 @@ public class ActionBar extends FrameLayout { titleTextView.setEllipsize(TextUtils.TruncateAt.END); titleTextView.setTextColor(0xffffffff); titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); + addView(titleTextView, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); } public void setTitle(CharSequence value) { @@ -174,12 +192,7 @@ public class ActionBar extends FrameLayout { return menu; } menu = new ActionBarMenu(getContext(), this); - addView(menu); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)menu.getLayoutParams(); - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.RIGHT; - menu.setLayoutParams(layoutParams); + addView(menu, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.RIGHT)); return menu; } @@ -192,8 +205,8 @@ public class ActionBar extends FrameLayout { return actionMode; } actionMode = new ActionBarMenu(getContext(), this); - actionMode.setBackgroundResource(R.drawable.editheader); - addView(actionMode); + actionMode.setBackgroundColor(0xffffffff); + addView(actionMode, indexOfChild(backButtonImageView)); actionMode.setPadding(0, occupyStatusBar ? AndroidUtilities.statusBarHeight : 0, 0, 0); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)actionMode.getLayoutParams(); layoutParams.height = LayoutHelper.MATCH_PARENT; @@ -218,34 +231,95 @@ public class ActionBar extends FrameLayout { } public void showActionMode() { - if (actionMode == null) { + if (actionMode == null || actionModeVisible) { return; } - actionMode.setVisibility(VISIBLE); - if (occupyStatusBar && actionModeTop != null) { - actionModeTop.setVisibility(VISIBLE); - } - if (titleTextView != null) { - titleTextView.setVisibility(INVISIBLE); - } - if (subTitleTextView != null) { - subTitleTextView.setVisibility(INVISIBLE); + actionModeVisible = true; + if (Build.VERSION.SDK_INT >= 14) { + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimatorProxy.ofFloat(actionMode, "alpha", 0.0f, 1.0f)); + if (occupyStatusBar && actionModeTop != null) { + animators.add(ObjectAnimatorProxy.ofFloat(actionModeTop, "alpha", 0.0f, 1.0f)); + } + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether(animators); + animatorSetProxy.setDuration(200); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationStart(Object animation) { + actionMode.setVisibility(VISIBLE); + if (occupyStatusBar && actionModeTop != null) { + actionModeTop.setVisibility(VISIBLE); + } + } + + @Override + public void onAnimationEnd(Object animation) { + if (titleTextView != null) { + titleTextView.setVisibility(INVISIBLE); + } + if (subTitleTextView != null) { + subTitleTextView.setVisibility(INVISIBLE); + } + if (menu != null) { + menu.setVisibility(INVISIBLE); + } + } + }); + animatorSetProxy.start(); + } else { + actionMode.setVisibility(VISIBLE); + if (occupyStatusBar && actionModeTop != null) { + actionModeTop.setVisibility(VISIBLE); + } + if (titleTextView != null) { + titleTextView.setVisibility(INVISIBLE); + } + if (subTitleTextView != null) { + subTitleTextView.setVisibility(INVISIBLE); + } + if (menu != null) { + menu.setVisibility(INVISIBLE); + } } if (backButtonImageView != null) { - backButtonImageView.setVisibility(INVISIBLE); - } - if (menu != null) { - menu.setVisibility(INVISIBLE); + Drawable drawable = backButtonImageView.getDrawable(); + if (drawable instanceof BackDrawable) { + ((BackDrawable) drawable).setRotation(1, true); + } + backButtonImageView.setBackgroundResource(R.drawable.bar_selector_mode); } } public void hideActionMode() { - if (actionMode == null) { + if (actionMode == null || !actionModeVisible) { return; } - actionMode.setVisibility(INVISIBLE); - if (occupyStatusBar && actionModeTop != null) { - actionModeTop.setVisibility(INVISIBLE); + actionModeVisible = false; + if (Build.VERSION.SDK_INT >= 14) { + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimatorProxy.ofFloat(actionMode, "alpha", 0.0f)); + if (occupyStatusBar && actionModeTop != null) { + animators.add(ObjectAnimatorProxy.ofFloat(actionModeTop, "alpha", 0.0f)); + } + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether(animators); + animatorSetProxy.setDuration(200); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + actionMode.setVisibility(INVISIBLE); + if (occupyStatusBar && actionModeTop != null) { + actionModeTop.setVisibility(INVISIBLE); + } + } + }); + animatorSetProxy.start(); + } else { + actionMode.setVisibility(INVISIBLE); + if (occupyStatusBar && actionModeTop != null) { + actionModeTop.setVisibility(INVISIBLE); + } } if (titleTextView != null) { titleTextView.setVisibility(VISIBLE); @@ -253,12 +327,16 @@ public class ActionBar extends FrameLayout { if (subTitleTextView != null) { subTitleTextView.setVisibility(VISIBLE); } - if (backButtonImageView != null) { - backButtonImageView.setVisibility(VISIBLE); - } if (menu != null) { menu.setVisibility(VISIBLE); } + if (backButtonImageView != null) { + Drawable drawable = backButtonImageView.getDrawable(); + if (drawable instanceof BackDrawable) { + ((BackDrawable) drawable).setRotation(0, true); + } + backButtonImageView.setBackgroundResource(itemsBackgroundResourceId); + } } public void showActionModeTop() { @@ -275,7 +353,7 @@ public class ActionBar extends FrameLayout { } public boolean isActionModeShowed() { - return actionMode != null && actionMode.getVisibility() == VISIBLE; + return actionMode != null && actionModeVisible; } protected void onSearchFieldVisibilityChanged(boolean visible) { @@ -288,7 +366,7 @@ public class ActionBar extends FrameLayout { } Drawable drawable = backButtonImageView.getDrawable(); if (drawable != null && drawable instanceof MenuDrawable) { - ((MenuDrawable)drawable).setRotation(visible ? 1 : 0, true); + ((MenuDrawable) drawable).setRotation(visible ? 1 : 0, true); } } @@ -313,7 +391,7 @@ public class ActionBar extends FrameLayout { int actionBarHeight = getCurrentActionBarHeight(); int actionBarHeightSpec = MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.EXACTLY); - setMeasuredDimension(width, actionBarHeight + extraHeight + (occupyStatusBar ? AndroidUtilities.statusBarHeight : 0)); + setMeasuredDimension(width, actionBarHeight + (occupyStatusBar ? AndroidUtilities.statusBarHeight : 0)); int textLeft; if (backButtonImageView != null && backButtonImageView.getVisibility() != GONE) { @@ -474,17 +552,6 @@ public class ActionBar extends FrameLayout { return isSearchFieldVisible; } - public void setExtraHeight(int value, boolean layout) { - extraHeight = value; - if (layout) { - requestLayout(); - } - } - - public int getExtraHeight() { - return extraHeight; - } - public void setOccupyStatusBar(boolean value) { occupyStatusBar = value; if (actionMode != null) { @@ -526,4 +593,9 @@ public class ActionBar extends FrameLayout { return AndroidUtilities.dp(56); } } + + @Override + public boolean hasOverlappingRendering() { + return false; + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index 5a70d96c2..492f75978 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.ActionBar; @@ -59,7 +59,6 @@ public class ActionBarLayout extends FrameLayout { if (child instanceof ActionBar) { return super.drawChild(canvas, child, drawingTime); } else { - //boolean wasActionBar = false; int actionBarHeight = 0; int childCount = getChildCount(); for (int a = 0; a < childCount; a++) { @@ -70,24 +69,10 @@ public class ActionBarLayout extends FrameLayout { if (view instanceof ActionBar && view.getVisibility() == VISIBLE) { if (((ActionBar) view).getCastShadows()) { actionBarHeight = view.getMeasuredHeight(); - //wasActionBar = true; } break; } } - /*if (!wasActionBar) { - if (child instanceof ViewGroup) { - ViewGroup viewGroup = (ViewGroup) child; - childCount = viewGroup.getChildCount(); - for (int a = 0; a < childCount; a++) { - View possibleActionBar = viewGroup.getChildAt(a); - if (possibleActionBar instanceof ActionBar) { - actionBarHeight = possibleActionBar.getMeasuredHeight(); - break; - } - } - } - }*/ boolean result = super.drawChild(canvas, child, drawingTime); if (actionBarHeight != 0 && headerShadowDrawable != null) { headerShadowDrawable.setBounds(0, actionBarHeight, getMeasuredWidth(), actionBarHeight + headerShadowDrawable.getIntrinsicHeight()); @@ -96,6 +81,11 @@ public class ActionBarLayout extends FrameLayout { return result; } } + + @Override + public boolean hasOverlappingRendering() { + return false; + } } private static Drawable headerShadowDrawable; @@ -129,6 +119,7 @@ public class ActionBarLayout extends FrameLayout { private boolean useAlphaAnimations; private View backgroundView; private boolean removeActionBarExtraHeight; + private Runnable animationRunnable; private float animationProgress = 0.0f; private long lastFrameTime; @@ -257,7 +248,7 @@ public class ActionBarLayout extends FrameLayout { } final int restoreCount = canvas.save(); - if (!transitionAnimationInProgress) { + if (!transitionAnimationInProgress && clipLeft != 0 && clipRight != 0) { canvas.clipRect(clipLeft, 0, clipRight, getHeight()); } final boolean result = super.drawChild(canvas, child, drawingTime); @@ -312,7 +303,7 @@ public class ActionBarLayout extends FrameLayout { parent.removeView(lastFragment.fragmentView); } } - if (lastFragment.needAddActionBar() && lastFragment.actionBar != null) { + if (lastFragment.actionBar != null && lastFragment.actionBar.getAddToContainer()) { ViewGroup parent = (ViewGroup) lastFragment.actionBar.getParent(); if (parent != null) { parent.removeView(lastFragment.actionBar); @@ -320,7 +311,6 @@ public class ActionBarLayout extends FrameLayout { } } containerViewBack.setVisibility(View.GONE); - //AndroidUtilities.unlockOrientation(parentActivity); startedTracking = false; animationInProgress = false; @@ -350,7 +340,7 @@ public class ActionBarLayout extends FrameLayout { if (parent != null) { parent.removeView(fragmentView); } - if (lastFragment.needAddActionBar() && lastFragment.actionBar != null) { + if (lastFragment.actionBar != null && lastFragment.actionBar.getAddToContainer()) { parent = (ViewGroup) lastFragment.actionBar.getParent(); if (parent != null) { parent.removeView(lastFragment.actionBar); @@ -370,8 +360,6 @@ public class ActionBarLayout extends FrameLayout { fragmentView.setBackgroundColor(0xffffffff); } lastFragment.onResume(); - - //AndroidUtilities.lockOrientation(parentActivity); } public boolean onTouchEvent(MotionEvent ev) { @@ -516,6 +504,10 @@ public class ActionBarLayout extends FrameLayout { } currentAnimation = null; } + if (animationRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(animationRunnable); + animationRunnable = null; + } ViewProxy.setAlpha(this, 1.0f); ViewProxy.setAlpha(containerView, 1.0f); ViewProxy.setScaleX(containerView, 1.0f); @@ -548,7 +540,7 @@ public class ActionBarLayout extends FrameLayout { parent.removeView(fragment.fragmentView); } } - if (fragment.needAddActionBar() && fragment.actionBar != null) { + if (fragment.actionBar != null && fragment.actionBar.getAddToContainer()) { ViewGroup parent = (ViewGroup) fragment.actionBar.getParent(); if (parent != null) { parent.removeView(fragment.actionBar); @@ -570,17 +562,18 @@ public class ActionBarLayout extends FrameLayout { if (first) { animationProgress = 0.0f; lastFrameTime = System.nanoTime() / 1000000; - if (Build.VERSION.SDK_INT >= 11) { - if (open) { - containerView.setLayerType(LAYER_TYPE_HARDWARE, null); - } else { - containerViewBack.setLayerType(LAYER_TYPE_HARDWARE, null); - } + if (Build.VERSION.SDK_INT > 15) { + containerView.setLayerType(LAYER_TYPE_HARDWARE, null); + containerViewBack.setLayerType(LAYER_TYPE_HARDWARE, null); } } - AndroidUtilities.runOnUIThread(new Runnable() { + AndroidUtilities.runOnUIThread(animationRunnable = new Runnable() { @Override public void run() { + if (animationRunnable != this) { + return; + } + animationRunnable = null; if (first) { transitionAnimationStartTime = System.currentTimeMillis(); } @@ -632,7 +625,7 @@ public class ActionBarLayout extends FrameLayout { parent.removeView(fragmentView); } } - if (fragment.needAddActionBar() && fragment.actionBar != null) { + if (fragment.actionBar != null && fragment.actionBar.getAddToContainer()) { if (removeActionBarExtraHeight) { fragment.actionBar.setOccupyStatusBar(false); } @@ -663,7 +656,6 @@ public class ActionBarLayout extends FrameLayout { setInnerTranslationX(0); bringChildToFront(containerView); - if (!needAnimation) { presentFragmentInternalRemoveOld(removeLast, currentFragment); if (backgroundView != null) { @@ -680,7 +672,7 @@ public class ActionBarLayout extends FrameLayout { onOpenAnimationEndRunnable = new Runnable() { @Override public void run() { - fragment.onOpenAnimationEnd(); + fragment.onTransitionAnimationEnd(true, false); fragment.onBecomeFullyVisible(); } }; @@ -691,7 +683,7 @@ public class ActionBarLayout extends FrameLayout { animators.add(ObjectAnimatorProxy.ofFloat(backgroundView, "alpha", 0.0f, 1.0f)); } - fragment.onOpenAnimationStart(); + fragment.onTransitionAnimationStart(true, false); currentAnimation = new AnimatorSetProxy(); currentAnimation.playTogether(animators); currentAnimation.setInterpolator(accelerateDecelerateInterpolator); @@ -714,50 +706,44 @@ public class ActionBarLayout extends FrameLayout { onOpenAnimationEndRunnable = new Runnable() { @Override public void run() { - if (Build.VERSION.SDK_INT >= 18) { + if (Build.VERSION.SDK_INT > 15) { containerView.setLayerType(LAYER_TYPE_NONE, null); + containerViewBack.setLayerType(LAYER_TYPE_NONE, null); } presentFragmentInternalRemoveOld(removeLast, currentFragment); - fragment.onOpenAnimationEnd(); + fragment.onTransitionAnimationEnd(true, false); fragment.onBecomeFullyVisible(); ViewProxy.setTranslationX(containerView, 0); } }; - ViewProxy.setAlpha(containerView, 0.0f); - ViewProxy.setTranslationX(containerView, 48.0f); - fragment.onOpenAnimationStart(); - startLayoutAnimation(true, true); - /*currentAnimation = new AnimatorSetProxy(); - currentAnimation.playTogether( - ObjectAnimatorProxy.ofFloat(containerView, "alpha", 0.0f, 1.0f), - ObjectAnimatorProxy.ofFloat(containerView, "translationX", AndroidUtilities.dp(48), 0)); - currentAnimation.setInterpolator(decelerateInterpolator); - currentAnimation.setDuration(200); - currentAnimation.addListener(new AnimatorListenerAdapterProxy() { + fragment.onTransitionAnimationStart(true, false); + AnimatorSetProxy animation = fragment.onCustomTransitionAnimation(true, new Runnable() { @Override - public void onAnimationStart(Object animation) { - transitionAnimationStartTime = System.currentTimeMillis(); - } - - @Override - public void onAnimationEnd(Object animation) { - onAnimationEndCheck(false); - } - - @Override - public void onAnimationCancel(Object animation) { + public void run() { onAnimationEndCheck(false); } }); - currentAnimation.start();*/ + if (animation == null) { + ViewProxy.setAlpha(containerView, 0.0f); + ViewProxy.setTranslationX(containerView, 48.0f); + startLayoutAnimation(true, true); + } else { + if (Build.VERSION.SDK_INT > 15) { + //containerView.setLayerType(LAYER_TYPE_HARDWARE, null); + //containerViewBack.setLayerType(LAYER_TYPE_HARDWARE, null); + } + ViewProxy.setAlpha(containerView, 1.0f); + ViewProxy.setTranslationX(containerView, 0.0f); + currentAnimation = animation; + } } } else { if (backgroundView != null) { ViewProxy.setAlpha(backgroundView, 1.0f); backgroundView.setVisibility(VISIBLE); } - fragment.onOpenAnimationStart(); - fragment.onOpenAnimationEnd(); + fragment.onTransitionAnimationStart(true, false); + fragment.onTransitionAnimationEnd(true, false); fragment.onBecomeFullyVisible(); } return true; @@ -836,7 +822,7 @@ public class ActionBarLayout extends FrameLayout { parent.removeView(fragmentView); } } - if (previousFragment.needAddActionBar() && previousFragment.actionBar != null) { + if (previousFragment.actionBar != null && previousFragment.actionBar.getAddToContainer()) { if (removeActionBarExtraHeight) { previousFragment.actionBar.setOccupyStatusBar(false); } @@ -852,7 +838,8 @@ public class ActionBarLayout extends FrameLayout { layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = LayoutHelper.MATCH_PARENT; fragmentView.setLayoutParams(layoutParams); - previousFragment.onOpenAnimationStart(); + previousFragment.onTransitionAnimationStart(true, true); + currentFragment.onTransitionAnimationStart(false, false); previousFragment.onResume(); currentActionBar = previousFragment.actionBar; if (!previousFragment.hasOwnBackground && fragmentView.getBackground() == null) { @@ -870,42 +857,35 @@ public class ActionBarLayout extends FrameLayout { onCloseAnimationEndRunnable = new Runnable() { @Override public void run() { - if (Build.VERSION.SDK_INT >= 18) { + if (Build.VERSION.SDK_INT > 15) { + containerView.setLayerType(LAYER_TYPE_NONE, null); containerViewBack.setLayerType(LAYER_TYPE_NONE, null); } closeLastFragmentInternalRemoveOld(currentFragment); ViewProxy.setTranslationX(containerViewBack, 0); - previousFragmentFinal.onOpenAnimationEnd(); + currentFragment.onTransitionAnimationEnd(false, false); + previousFragmentFinal.onTransitionAnimationEnd(true, true); previousFragmentFinal.onBecomeFullyVisible(); } }; - startLayoutAnimation(false, true); - - /*currentAnimation = new AnimatorSetProxy(); - currentAnimation.playTogether( - ObjectAnimatorProxy.ofFloat(containerViewBack, "alpha", 1.0f, 0.0f), - ObjectAnimatorProxy.ofFloat(containerViewBack, "translationX", 0, AndroidUtilities.dp(48))); - currentAnimation.setInterpolator(decelerateInterpolator); - currentAnimation.setDuration(200); - currentAnimation.addListener(new AnimatorListenerAdapterProxy() { + AnimatorSetProxy animation = currentFragment.onCustomTransitionAnimation(false, new Runnable() { @Override - public void onAnimationStart(Object animation) { - transitionAnimationStartTime = System.currentTimeMillis(); - } - - @Override - public void onAnimationEnd(Object animation) { - onAnimationEndCheck(false); - } - - @Override - public void onAnimationCancel(Object animation) { + public void run() { onAnimationEndCheck(false); } }); - currentAnimation.start();*/ + if (animation == null) { + startLayoutAnimation(false, true); + } else { + if (Build.VERSION.SDK_INT > 15) { + //containerView.setLayerType(LAYER_TYPE_HARDWARE, null); + //containerViewBack.setLayerType(LAYER_TYPE_HARDWARE, null); + } + currentAnimation = animation; + } } else { - previousFragment.onOpenAnimationEnd(); + currentFragment.onTransitionAnimationEnd(false, false); + previousFragment.onTransitionAnimationEnd(true, true); previousFragment.onBecomeFullyVisible(); } } else { @@ -968,6 +948,22 @@ public class ActionBarLayout extends FrameLayout { if (fragmentsStack.isEmpty()) { return; } + for (int a = 0; a < fragmentsStack.size() - 1; a++) { + BaseFragment previousFragment = fragmentsStack.get(a); + if (previousFragment.actionBar != null) { + ViewGroup parent = (ViewGroup) previousFragment.actionBar.getParent(); + if (parent != null) { + parent.removeView(previousFragment.actionBar); + } + } + if (previousFragment.fragmentView != null) { + ViewGroup parent = (ViewGroup) previousFragment.fragmentView.getParent(); + if (parent != null) { + previousFragment.onPause(); + parent.removeView(previousFragment.fragmentView); + } + } + } BaseFragment previousFragment = fragmentsStack.get(fragmentsStack.size() - 1); previousFragment.setParentLayout(this); View fragmentView = previousFragment.fragmentView; @@ -979,7 +975,7 @@ public class ActionBarLayout extends FrameLayout { parent.removeView(fragmentView); } } - if (previousFragment.needAddActionBar() && previousFragment.actionBar != null) { + if (previousFragment.actionBar != null && previousFragment.actionBar.getAddToContainer()) { if (removeActionBarExtraHeight) { previousFragment.actionBar.setOccupyStatusBar(false); } @@ -1136,4 +1132,9 @@ public class ActionBarLayout extends FrameLayout { } } } + + @Override + public boolean hasOverlappingRendering() { + return false; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java index 74f6575e0..adfd31f8f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.ActionBar; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java index 91ede040d..0a2d4eb22 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.ActionBar; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java index 36f3dd0d0..fb6c27cac 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ //Thanks to https://github.com/JakeWharton/ActionBarSherlock/ diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java new file mode 100644 index 000000000..c19dd92a0 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BackDrawable.java @@ -0,0 +1,130 @@ +/* + * This is the source code of Telegram for Android v. 3.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.ActionBar; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; +import android.view.animation.DecelerateInterpolator; + +import org.telegram.messenger.AndroidUtilities; + +public class BackDrawable extends Drawable { + + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private boolean reverseAngle = false; + private long lastFrameTime; + private boolean animationInProgress; + private float finalRotation; + private float currentRotation; + private int currentAnimationTime; + private boolean alwaysClose; + private DecelerateInterpolator interpolator = new DecelerateInterpolator(); + + public BackDrawable(boolean close) { + super(); + paint.setColor(0xffffffff); + paint.setStrokeWidth(AndroidUtilities.dp(2)); + alwaysClose = close; + } + + public void setRotation(float rotation, boolean animated) { + lastFrameTime = 0; + if (currentRotation == 1) { + reverseAngle = true; + } else if (currentRotation == 0) { + reverseAngle = false; + } + lastFrameTime = 0; + if (animated) { + if (currentRotation < rotation) { + currentAnimationTime = (int) (currentRotation * 300); + } else { + currentAnimationTime = (int) ((1.0f - currentRotation) * 300); + } + lastFrameTime = System.currentTimeMillis(); + finalRotation = rotation; + } else { + finalRotation = currentRotation = rotation; + } + invalidateSelf(); + } + + @Override + public void draw(Canvas canvas) { + if (currentRotation != finalRotation) { + if (lastFrameTime != 0) { + long dt = System.currentTimeMillis() - lastFrameTime; + + currentAnimationTime += dt; + if (currentAnimationTime >= 300) { + currentRotation = finalRotation; + } else { + if (currentRotation < finalRotation) { + currentRotation = interpolator.getInterpolation(currentAnimationTime / 300.0f) * finalRotation; + } else { + currentRotation = 1.0f - interpolator.getInterpolation(currentAnimationTime / 300.0f); + } + } + } + lastFrameTime = System.currentTimeMillis(); + invalidateSelf(); + } + + int rD = (int) ((117 - 255) * currentRotation); + int c = Color.rgb(255 + rD, 255 + rD, 255 + rD); + paint.setColor(c); + + canvas.save(); + canvas.translate(getIntrinsicWidth() / 2, getIntrinsicHeight() / 2); + float rotation = currentRotation; + if (!alwaysClose) { + canvas.rotate(currentRotation * (reverseAngle ? -225 : 135)); + } else { + canvas.rotate(135 + currentRotation * (reverseAngle ? -180 : 180)); + rotation = 1.0f; + } + canvas.drawLine(-AndroidUtilities.dp(7) - AndroidUtilities.dp(1) * rotation, 0, AndroidUtilities.dp(8), 0, paint); + float startYDiff = -AndroidUtilities.dp(0.5f); + float endYDiff = AndroidUtilities.dp(7) + AndroidUtilities.dp(1) * rotation; + float startXDiff = -AndroidUtilities.dp(7.0f) + AndroidUtilities.dp(7.0f) * rotation; + float endXDiff = AndroidUtilities.dp(0.5f) - AndroidUtilities.dp(0.5f) * rotation; + canvas.drawLine(startXDiff, -startYDiff, endXDiff, -endYDiff, paint); + canvas.drawLine(startXDiff, startYDiff, endXDiff, endYDiff, paint); + canvas.restore(); + } + + @Override + public void setAlpha(int alpha) { + + } + + @Override + public void setColorFilter(ColorFilter cf) { + + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + @Override + public int getIntrinsicWidth() { + return AndroidUtilities.dp(24); + } + + @Override + public int getIntrinsicHeight() { + return AndroidUtilities.dp(24); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java index 68103b395..3e62a22c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.ActionBar; @@ -17,6 +17,7 @@ import android.os.Bundle; import android.view.View; import android.view.ViewGroup; +import org.telegram.messenger.AnimationCompat.AnimatorSetProxy; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.tgnet.ConnectionsManager; @@ -43,6 +44,14 @@ public class BaseFragment { classGuid = ConnectionsManager.getInstance().generateClassGuid(); } + public ActionBar getActionBar() { + return actionBar; + } + + public View getFragmentView() { + return fragmentView; + } + public View createView(Context context) { return null; } @@ -154,7 +163,7 @@ public class BaseFragment { actionBar.onPause(); } try { - if (visibleDialog != null && visibleDialog.isShowing()) { + if (visibleDialog != null && visibleDialog.isShowing() && dismissDialogOnPause(visibleDialog)) { visibleDialog.dismiss(); visibleDialog = null; } @@ -175,6 +184,10 @@ public class BaseFragment { } + public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { + + } + public void saveSelfArgs(Bundle args) { } @@ -208,6 +221,10 @@ public class BaseFragment { } } + public boolean dismissDialogOnPause(Dialog dialog) { + return true; + } + public void onBeginSlide() { try { if (visibleDialog != null && visibleDialog.isShowing()) { @@ -222,11 +239,11 @@ public class BaseFragment { } } - protected void onOpenAnimationEnd() { + protected void onTransitionAnimationStart(boolean isOpen, boolean backward) { } - protected void onOpenAnimationStart() { + protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) { } @@ -234,12 +251,12 @@ public class BaseFragment { } - public void onLowMemory() { - + protected AnimatorSetProxy onCustomTransitionAnimation(boolean isOpen, final Runnable callback) { + return null; } - public boolean needAddActionBar() { - return true; + public void onLowMemory() { + } public Dialog showDialog(Dialog dialog) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java index 1e9125554..3add2a8ef 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -296,6 +296,10 @@ public class BottomSheet extends Dialog { } }); container.setBackgroundDrawable(backgroundDrawable); + if (Build.VERSION.SDK_INT >= 21) { + container.setFitsSystemWindows(true); + container.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + } } @Override @@ -418,15 +422,13 @@ public class BottomSheet extends Dialog { } WindowManager.LayoutParams params = getWindow().getAttributes(); - params.height = ViewGroup.LayoutParams.MATCH_PARENT; params.width = ViewGroup.LayoutParams.MATCH_PARENT; params.gravity = Gravity.TOP | Gravity.LEFT; params.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; params.dimAmount = 0; params.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND; - if (Build.VERSION.SDK_INT >= 21) { - params.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; - params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; + if (Build.VERSION.SDK_INT < 21) { + params.height = ViewGroup.LayoutParams.MATCH_PARENT; } getWindow().setAttributes(params); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java index d7f12cb23..985be1645 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java @@ -1,13 +1,14 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.ActionBar; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; @@ -69,12 +70,14 @@ public class DrawerLayoutContainer extends FrameLayout { if (Build.VERSION.SDK_INT >= 21) { setFitsSystemWindows(true); - configureApplyInsets(this); + setOnApplyWindowInsetsListener(new InsetsListener()); + setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } shadowLeft = getResources().getDrawable(R.drawable.menu_shadow); } + @SuppressLint("NewApi") private class InsetsListener implements View.OnApplyWindowInsetsListener { @Override public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { @@ -84,13 +87,7 @@ public class DrawerLayoutContainer extends FrameLayout { } } - private void configureApplyInsets(View drawerLayout) { - if (Build.VERSION.SDK_INT >= 21) { - drawerLayout.setOnApplyWindowInsetsListener(new InsetsListener()); - drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); - } - } - + @SuppressLint("NewApi") private void dispatchChildInsets(View child, Object insets, int drawerGravity) { WindowInsets wi = (WindowInsets) insets; if (drawerGravity == Gravity.LEFT) { @@ -101,6 +98,7 @@ public class DrawerLayoutContainer extends FrameLayout { child.dispatchApplyWindowInsets(wi); } + @SuppressLint("NewApi") private void applyMarginInsets(MarginLayoutParams lp, Object insets, int drawerGravity, boolean topOnly) { WindowInsets wi = (WindowInsets) insets; if (drawerGravity == Gravity.LEFT) { @@ -413,6 +411,7 @@ public class DrawerLayoutContainer extends FrameLayout { } } + @SuppressLint("NewApi") @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); @@ -435,7 +434,7 @@ public class DrawerLayoutContainer extends FrameLayout { if (applyInsets) { if (child.getFitsSystemWindows()) { dispatchChildInsets(child, lastInsets, lp.gravity); - } else { + } else if (child.getTag() == null) { applyMarginInsets(lp, lastInsets, lp.gravity, Build.VERSION.SDK_INT >= 21); } } @@ -460,6 +459,7 @@ public class DrawerLayoutContainer extends FrameLayout { } final int height = getHeight(); final boolean drawingContent = child != drawerLayout; + int lastVisibleChild = 0; int clipLeft = 0, clipRight = getWidth(); final int restoreCount = canvas.save(); @@ -467,6 +467,9 @@ public class DrawerLayoutContainer extends FrameLayout { final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View v = getChildAt(i); + if (v.getVisibility() == VISIBLE && v != drawerLayout) { + lastVisibleChild = i; + } if (v == child || v.getVisibility() != VISIBLE || v != drawerLayout || v.getHeight() < height) { continue; } @@ -476,14 +479,18 @@ public class DrawerLayoutContainer extends FrameLayout { clipLeft = vright; } } - canvas.clipRect(clipLeft, 0, clipRight, getHeight()); + if (clipLeft != 0) { + canvas.clipRect(clipLeft, 0, clipRight, getHeight()); + } } final boolean result = super.drawChild(canvas, child, drawingTime); canvas.restoreToCount(restoreCount); if (scrimOpacity > 0 && drawingContent) { - scrimPaint.setColor((int) (((0x99000000 & 0xff000000) >>> 24) * scrimOpacity) << 24); - canvas.drawRect(clipLeft, 0, clipRight, getHeight(), scrimPaint); + if (indexOfChild(child) == lastVisibleChild) { + scrimPaint.setColor((int) (((0x99000000 & 0xff000000) >>> 24) * scrimOpacity) << 24); + canvas.drawRect(clipLeft, 0, clipRight, getHeight(), scrimPaint); + } } else if (shadowLeft != null) { final float alpha = Math.max(0, Math.min(drawerPosition / AndroidUtilities.dp(20), 1.0f)); if (alpha != 0) { @@ -494,4 +501,9 @@ public class DrawerLayoutContainer extends FrameLayout { } return result; } + + @Override + public boolean hasOverlappingRendering() { + return false; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java index c75bc7b42..46137f3bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/MenuDrawable.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.ActionBar; @@ -11,6 +11,7 @@ package org.telegram.ui.ActionBar; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.view.animation.DecelerateInterpolator; @@ -79,11 +80,11 @@ public class MenuDrawable extends Drawable { canvas.save(); canvas.translate(getIntrinsicWidth() / 2, getIntrinsicHeight() / 2); canvas.rotate(currentRotation * (reverseAngle ? -180 : 180)); - canvas.drawLine(-AndroidUtilities.dp(9), 0, AndroidUtilities.dp(9) - AndroidUtilities.dp(1) * currentRotation, 0, paint); + canvas.drawLine(-AndroidUtilities.dp(9), 0, AndroidUtilities.dp(9) - AndroidUtilities.dp(3.0f) * currentRotation, 0, paint); float endYDiff = AndroidUtilities.dp(5) * (1 - Math.abs(currentRotation)) - AndroidUtilities.dp(0.5f) * Math.abs(currentRotation); - float endXDiff = AndroidUtilities.dp(9) - AndroidUtilities.dp(0.5f) * Math.abs(currentRotation); - float startYDiff = AndroidUtilities.dp(5) + AndroidUtilities.dp(3.5f) * Math.abs(currentRotation); - float startXDiff = -AndroidUtilities.dp(9) + AndroidUtilities.dp(8.5f) * Math.abs(currentRotation); + float endXDiff = AndroidUtilities.dp(9) - AndroidUtilities.dp(2.5f) * Math.abs(currentRotation); + float startYDiff = AndroidUtilities.dp(5) + AndroidUtilities.dp(2.0f) * Math.abs(currentRotation); + float startXDiff = -AndroidUtilities.dp(9) + AndroidUtilities.dp(7.5f) * Math.abs(currentRotation); canvas.drawLine(startXDiff, -startYDiff, endXDiff, -endYDiff, paint); canvas.drawLine(startXDiff, startYDiff, endXDiff, endYDiff, paint); canvas.restore(); @@ -101,7 +102,7 @@ public class MenuDrawable extends Drawable { @Override public int getOpacity() { - return 0; + return PixelFormat.TRANSPARENT; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseFragmentAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseFragmentAdapter.java index 131961344..57bd70eba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseFragmentAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseFragmentAdapter.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseLocationAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseLocationAdapter.java index c80eb04b8..bfd0457ed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseLocationAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseLocationAdapter.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapter.java index 011144e6e..36f36779c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapterRecycler.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapterRecycler.java index edd0b8614..5f343e675 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapterRecycler.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSearchAdapterRecycler.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSectionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSectionsAdapter.java index f9b75addc..a6b493290 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSectionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/BaseSectionsAdapter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java index afe18248d..91049dbe5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ChatActivityAdapter.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java index 4fcff0663..f2b0fe225 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java index 3c577880d..216f27c8d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java index b7da3404d..0282d9df7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index bb4bcad60..bdb6d7b30 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index 6fcf25d82..8e6543794 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; @@ -178,7 +178,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler { } public boolean isRecentSearchDisplayed() { - return (lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty(); + return needMessagesSearch != 2 && (lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty(); } public void loadRecentSearch() { @@ -776,7 +776,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler { @Override public int getItemCount() { - if ((lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { + if (needMessagesSearch != 2 && (lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { return recentSearchObjects.size() + 1; } if (!searchResultHashtags.isEmpty()) { @@ -795,7 +795,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler { } public Object getItem(int i) { - if ((lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { + if (needMessagesSearch != 2 && (lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { if (i > 0 && i - 1 < recentSearchObjects.size()) { return recentSearchObjects.get(i - 1).object; } else { @@ -880,7 +880,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler { user = MessagesController.getInstance().getUser(encryptedChat.user_id); } - if ((lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { + if (needMessagesSearch != 2 && (lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { isRecent = true; cell.useSeparator = position != getItemCount() - 1; } else { @@ -914,7 +914,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler { } case 1: { GreySectionCell cell = (GreySectionCell) holder.itemView; - if ((lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { + if (needMessagesSearch != 2 && (lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { cell.setText(LocaleController.getString("Recent", R.string.Recent).toUpperCase()); } else if (!searchResultHashtags.isEmpty()) { cell.setText(LocaleController.getString("Hashtags", R.string.Hashtags).toUpperCase()); @@ -946,7 +946,7 @@ public class DialogsSearchAdapter extends BaseSearchAdapterRecycler { @Override public int getItemViewType(int i) { - if ((lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { + if (needMessagesSearch != 2 && (lastSearchText == null || lastSearchText.length() == 0) && !recentSearchObjects.isEmpty()) { return i == 0 ? 1 : 0; } if (!searchResultHashtags.isEmpty()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java index e46e504af..efc5c3d3a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java index a0efeae93..dbdadeba7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivityAdapter.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java index bc030a09c..94669e132 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/LocationActivitySearchAdapter.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java index 370c02687..65b94218e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java index 633a1cef0..ae6904606 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -41,6 +41,12 @@ public class PhotoAttachAdapter extends RecyclerView.Adapter { public void clearSelectedPhotos() { if (!selectedPhotos.isEmpty()) { + for (HashMap.Entry entry : selectedPhotos.entrySet()) { + MediaController.PhotoEntry photoEntry = entry.getValue(); + photoEntry.imagePath = null; + photoEntry.thumbPath = null; + photoEntry.caption = null; + } selectedPhotos.clear(); delegate.selectedPhotosChanged(); notifyDataSetChanged(); @@ -57,54 +63,45 @@ public class PhotoAttachAdapter extends RecyclerView.Adapter { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { - //if (position != 0) { - PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) holder.itemView; - MediaController.PhotoEntry photoEntry = MediaController.allPhotosAlbumEntry.photos.get(position/* - 1*/); - cell.setPhotoEntry(photoEntry, position == MediaController.allPhotosAlbumEntry.photos.size()); - cell.setChecked(selectedPhotos.containsKey(photoEntry.imageId), false); - //} + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) holder.itemView; + MediaController.PhotoEntry photoEntry = MediaController.allPhotosAlbumEntry.photos.get(position); + cell.setPhotoEntry(photoEntry, position == MediaController.allPhotosAlbumEntry.photos.size() - 1); + cell.setChecked(selectedPhotos.containsKey(photoEntry.imageId), false); + cell.getImageView().setTag(position); + cell.setTag(position); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view; - /*if (viewType == 0) { - view = new PhotoAttachCameraCell(mContext); - } else {*/ - PhotoAttachPhotoCell cell = new PhotoAttachPhotoCell(mContext); - /*cell.setOnCheckClickLisnener(new View.OnClickListener() { - @Override - public void onClick(View v) { - onItemClick((PhotoAttachPhotoCell) v.getParent()); + PhotoAttachPhotoCell cell = new PhotoAttachPhotoCell(mContext); + cell.setOnCheckClickLisnener(new View.OnClickListener() { + @Override + public void onClick(View v) { + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) v.getParent(); + MediaController.PhotoEntry photoEntry = cell.getPhotoEntry(); + if (selectedPhotos.containsKey(photoEntry.imageId)) { + selectedPhotos.remove(photoEntry.imageId); + cell.setChecked(false, true); + photoEntry.imagePath = null; + photoEntry.thumbPath = null; + cell.setPhotoEntry(photoEntry, cell.getTag() == MediaController.allPhotosAlbumEntry.photos.size() - 1); + } else { + selectedPhotos.put(photoEntry.imageId, photoEntry); + cell.setChecked(true, true); } - }); - view = cell;*/ - //} + delegate.selectedPhotosChanged(); + } + }); return new Holder(cell); } - public void onItemClick(PhotoAttachPhotoCell cell) { - MediaController.PhotoEntry photoEntry = cell.getPhotoEntry(); - if (selectedPhotos.containsKey(photoEntry.imageId)) { - selectedPhotos.remove(photoEntry.imageId); - cell.setChecked(false, true); - } else { - selectedPhotos.put(photoEntry.imageId, photoEntry); - cell.setChecked(true, true); - } - delegate.selectedPhotosChanged(); - } - @Override public int getItemCount() { - return /*1 + */(MediaController.allPhotosAlbumEntry != null ? MediaController.allPhotosAlbumEntry.photos.size() : 0); + return (MediaController.allPhotosAlbumEntry != null ? MediaController.allPhotosAlbumEntry.photos.size() : 0); } @Override public int getItemViewType(int position) { - //if (position == 0) { - return 0; - //} - //return 1; + return 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java index 09fd654b6..ceb802014 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java index 4bbe6a5e6..326e207a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -3,12 +3,13 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Adapters; import android.content.Context; +import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; @@ -87,8 +88,18 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio } public void loadStikersForEmoji(CharSequence emoji) { - boolean search = emoji != null && emoji.length() > 0 && emoji.length() <= 4; + boolean search = emoji != null && emoji.length() > 0 && emoji.length() <= 14; if (search) { + int length = emoji.length(); + for (int a = 0; a < length; a++) { + if (a < length - 1 && emoji.charAt(a) == 0xD83C && emoji.charAt(a + 1) >= 0xDFFB && emoji.charAt(a + 1) <= 0xDFFF) { + emoji = TextUtils.concat(emoji.subSequence(0, a), emoji.subSequence(a + 2, emoji.length())); + break; + } else if (emoji.charAt(a) == 0xfe0f) { + emoji = TextUtils.concat(emoji.subSequence(0, a), emoji.subSequence(a + 1, emoji.length())); + length--; + } + } lastSticker = emoji.toString(); HashMap> allStickers = StickersQuery.getAllStickers(); if (allStickers != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java index 1b4c9edf8..d0498c332 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java index 286929828..cd0f53146 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -77,7 +77,7 @@ public class AudioSelectActivity extends BaseFragment implements NotificationCen NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeChats); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset); if (playingAudio != null && MediaController.getInstance().isPlayingAudio(playingAudio)) { - MediaController.getInstance().clenupPlayer(true, true); + MediaController.getInstance().cleanupPlayer(true, true); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java index c5d1bf60d..fcc9a4d06 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AddMemberCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AddMemberCell.java index a8157c9f0..0b63fc8c4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AddMemberCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AddMemberCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -9,7 +9,9 @@ package org.telegram.ui.Cells; import android.content.Context; +import android.os.Build; import android.view.Gravity; +import android.view.MotionEvent; import android.widget.FrameLayout; import android.widget.ImageView; @@ -38,9 +40,19 @@ public class AddMemberCell extends FrameLayout { addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 28 : 129, 22.5f, LocaleController.isRTL ? 129 : 28, 0)); } + @Override + public boolean onTouchEvent(MotionEvent event) { + if (Build.VERSION.SDK_INT >= 21 && getBackground() != null) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { + getBackground().setHotspot(event.getX(), event.getY()); + } + } + return super.onTouchEvent(event); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64), MeasureSpec.EXACTLY)); } public void setText(String text) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java index 27d770638..b0c88b3a6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java index 92505cdb2..147128959 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java @@ -3,7 +3,7 @@ * 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. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -33,11 +33,11 @@ public class BaseCell extends View { public void run() { if (checkingForLongPress && getParent() != null && currentPressCount == pressCount) { checkingForLongPress = false; + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + onLongPress(); MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); onTouchEvent(event); event.recycle(); - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - onLongPress(); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java index fcb5e997e..f6bb96fa9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java index b08d2349f..d944b1f37 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java index 6163d997b..e1f5f33dd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -144,6 +144,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega invalidate(); } } else if (buttonState == 2) { + radialProgress.setProgress(0, false); FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.audio, true); buttonState = 3; radialProgress.setBackground(getDrawableForCurrentState(), true, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java index fb48e4c5b..bd5414189 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -48,7 +48,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo void didPressedCancelSendButton(ChatBaseCell cell); void didLongPressed(ChatBaseCell cell); void didPressReplyMessage(ChatBaseCell cell, int id); - void didPressUrl(MessageObject messageObject, ClickableSpan url); + void didPressUrl(MessageObject messageObject, ClickableSpan url, boolean longPress); void needOpenWebView(String url, String title, String originalUrl, int w, int h); void didClickedImage(ChatBaseCell cell); boolean canPerformActions(); @@ -69,6 +69,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo private boolean wasLayout = false; protected boolean isAvatarVisible = false; protected boolean drawBackground = true; + protected boolean allowAssistant = false; protected MessageObject currentMessageObject; private static TextPaint timePaintIn; @@ -117,11 +118,16 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo private StaticLayout timeLayout; protected int timeWidth; + private int timeTextWidth; private int timeX; private TextPaint currentTimePaint; private String currentTimeString; protected boolean drawTime = true; + private StaticLayout viewsLayout; + private int viewsTextWidth; + private String currentViewsString; + private TLRPC.User currentUser; private TLRPC.Chat currentChat; private TLRPC.FileLocation currentPhoto; @@ -226,6 +232,10 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo invalidate(); } + public void setAllowAssistant(boolean value) { + allowAssistant = value; + } + protected boolean isUserDataChanged() { if (currentMessageObject == null || currentUser == null && currentChat == null) { return false; @@ -296,27 +306,11 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } protected void measureTime(MessageObject messageObject) { - if (!media) { - if (messageObject.isOutOwner()) { - currentTimePaint = timePaintOut; - } else { - currentTimePaint = timePaintIn; - } - } else { - currentTimePaint = timeMediaPaint; - } - String timeString = LocaleController.formatterDay.format((long) (messageObject.messageOwner.date) * 1000); + currentTimeString = LocaleController.formatterDay.format((long) (messageObject.messageOwner.date) * 1000); + timeTextWidth = timeWidth = (int) Math.ceil(timeMediaPaint.measureText(currentTimeString)); if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - currentTimeString = String.format("%s ", LocaleController.formatShortNumber(messageObject.messageOwner.views, null)) + timeString; - } else { - currentTimeString = timeString; - } - timeWidth = (int) Math.ceil(currentTimePaint.measureText(currentTimeString)); - if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - timeWidth += ResourceLoader.viewsCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(4); - } - if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 && (messageObject.isSending() || messageObject.isSendError())) { - currentTimeString = timeString; + currentViewsString = String.format("%s", LocaleController.formatShortNumber(Math.max(1, messageObject.messageOwner.views), null)); + timeWidth += (int) Math.ceil(timeMediaPaint.measureText(currentViewsString)) + ResourceLoader.viewsCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); } } @@ -385,18 +379,12 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo currentTimePaint = timeMediaPaint; } - String timeString = LocaleController.formatterDay.format((long) (currentMessageObject.messageOwner.date) * 1000); - if ((currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - currentTimeString = String.format("%s ", LocaleController.formatShortNumber(currentMessageObject.messageOwner.views, null)) + timeString; - } else { - currentTimeString = timeString; - } - timeWidth = (int)Math.ceil(currentTimePaint.measureText(currentTimeString)); - if ((currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { - timeWidth += ResourceLoader.viewsCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(4); - } - if ((currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0 && (currentMessageObject.isSending() || currentMessageObject.isSendError())) { - currentTimeString = timeString; + currentTimeString = LocaleController.formatterDay.format((long) (messageObject.messageOwner.date) * 1000); + timeTextWidth = timeWidth = (int)Math.ceil(currentTimePaint.measureText(currentTimeString)); + if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { + currentViewsString = String.format("%s", LocaleController.formatShortNumber(Math.max(1, messageObject.messageOwner.views), null)); + viewsTextWidth = (int) Math.ceil(currentTimePaint.measureText(currentViewsString)); + timeWidth += viewsTextWidth + ResourceLoader.viewsCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(10); } namesOffset = 0; @@ -678,7 +666,7 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo layoutWidth = getMeasuredWidth(); layoutHeight = getMeasuredHeight(); - timeLayout = new StaticLayout(currentTimeString, currentTimePaint, timeWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + timeLayout = new StaticLayout(currentTimeString, currentTimePaint, timeTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (!media) { if (!currentMessageObject.isOutOwner()) { timeX = backgroundWidth - AndroidUtilities.dp(9) - timeWidth + (isChat && currentMessageObject.messageOwner.from_id > 0 ? AndroidUtilities.dp(52) : 0); @@ -693,6 +681,12 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } } + if ((currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { + viewsLayout = new StaticLayout(currentViewsString, currentTimePaint, viewsTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } else { + viewsLayout = null; + } + if (isAvatarVisible) { avatarImage.setImageCoords(AndroidUtilities.dp(6), layoutHeight - AndroidUtilities.dp(45), AndroidUtilities.dp(42), AndroidUtilities.dp(42)); } @@ -899,6 +893,13 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo } else { setDrawableBounds(ResourceLoader.viewsMediaCountDrawable, timeX, layoutHeight - AndroidUtilities.dp(10) - timeLayout.getHeight()); ResourceLoader.viewsMediaCountDrawable.draw(canvas); + + if (viewsLayout != null) { + canvas.save(); + canvas.translate(timeX + ResourceLoader.viewsMediaCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(12.0f) - timeLayout.getHeight()); + viewsLayout.draw(canvas); + canvas.restore(); + } } } @@ -929,6 +930,13 @@ public class ChatBaseCell extends BaseCell implements MediaController.FileDownlo setDrawableBounds(ResourceLoader.viewsOutCountDrawable, timeX, layoutHeight - AndroidUtilities.dp(4.5f) - timeLayout.getHeight()); ResourceLoader.viewsOutCountDrawable.draw(canvas); } + + if (viewsLayout != null) { + canvas.save(); + canvas.translate(timeX + ResourceLoader.viewsOutCountDrawable.getIntrinsicWidth() + AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(6.5f) - timeLayout.getHeight()); + viewsLayout.draw(canvas); + canvas.restore(); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java index cf183af2a..eab4e6a74 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatLoadingCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatLoadingCell.java index 1e1a7e609..732ae8909 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatLoadingCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatLoadingCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java index 91f7e7009..a0eee1a8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -38,6 +38,7 @@ import org.telegram.messenger.MessageObject; import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.Components.StaticLayoutEx; +import org.telegram.ui.Components.URLSpanBotCommand; import org.telegram.ui.PhotoViewer; import org.telegram.ui.Components.GifDrawable; import org.telegram.messenger.ImageReceiver; @@ -89,6 +90,7 @@ public class ChatMediaCell extends ChatBaseCell { private StaticLayout nameLayout; private int nameWidth = 0; + private int nameOffsetX = 0; private String currentNameString; private ChatMediaCellDelegate mediaDelegate = null; @@ -180,7 +182,11 @@ public class ChatMediaCell extends ChatBaseCell { if (left <= x2 && left + nameLayout.getLineWidth(line) >= x2) { Spannable buffer = (Spannable) currentMessageObject.caption; ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); - if (link.length != 0) { + boolean ignore = false; + if (link.length == 0 || link.length != 0 && link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { + ignore = true; + } + if (!ignore) { resetPressedLink(); pressedLink = link[0]; linkPreviewPressed = true; @@ -204,7 +210,7 @@ public class ChatMediaCell extends ChatBaseCell { } } else if (linkPreviewPressed) { try { - delegate.didPressUrl(currentMessageObject, pressedLink); + delegate.didPressUrl(currentMessageObject, pressedLink, false); } catch (Exception e) { FileLog.e("tmessages", e); } @@ -444,7 +450,7 @@ public class ChatMediaCell extends ChatBaseCell { } double lat = object.messageOwner.media.geo.lat; double lon = object.messageOwner.media.geo._long; - String url = String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=13&size=100x100&maptype=roadmap&scale=%d&markers=color:red|size:big|%f,%f&sensor=false", lat, lon, Math.min(2, (int) Math.ceil(AndroidUtilities.density)), lat, lon); + String url = String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=15&size=100x100&maptype=roadmap&scale=%d&markers=color:red|size:big|%f,%f&sensor=false", lat, lon, Math.min(2, (int) Math.ceil(AndroidUtilities.density)), lat, lon); if (!url.equals(currentUrl)) { return true; } @@ -463,6 +469,7 @@ public class ChatMediaCell extends ChatBaseCell { public void setMessageObject(MessageObject messageObject) { boolean dataChanged = currentMessageObject == messageObject && (isUserDataChanged() || photoNotSet); if (currentMessageObject != messageObject || isPhotoDataChanged(messageObject) || dataChanged) { + drawForwardedName = (messageObject.type == 3 || messageObject.type == 1) && messageObject.messageOwner.fwd_from_id != null && messageObject.messageOwner.fwd_from_id.channel_id != 0; media = messageObject.type != 9; cancelLoading = false; additionHeight = 0; @@ -493,23 +500,13 @@ public class ChatMediaCell extends ChatBaseCell { nameLayout = StaticLayoutEx.createStaticLayout(currentNameString, namePaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, maxWidth, 1); if (nameLayout.getLineCount() > 0) { nameWidth = Math.min(maxWidth, (int) Math.ceil(nameLayout.getLineWidth(0))); + nameOffsetX = (int) Math.ceil(-nameLayout.getLineLeft(0)); } else { nameWidth = maxWidth; } } - String fileName = messageObject.getFileName(); - int idx = fileName.lastIndexOf("."); - String ext = null; - if (idx != -1) { - ext = fileName.substring(idx + 1); - } - if (ext == null || ext.length() == 0) { - ext = messageObject.messageOwner.media.document.mime_type; - } - ext = ext.toUpperCase(); - - String str = AndroidUtilities.formatFileSize(messageObject.messageOwner.media.document.size) + " " + ext; + String str = AndroidUtilities.formatFileSize(messageObject.messageOwner.media.document.size) + " " + messageObject.getExtension(); if (currentInfoString == null || !currentInfoString.equals(str)) { currentInfoString = str; @@ -548,7 +545,7 @@ public class ChatMediaCell extends ChatBaseCell { currentNameString = null; infoLayout = null; nameLayout = null; - updateSecretTimeText(); + updateSecretTimeText(messageObject); } if (messageObject.type == 9) { //doc photoWidth = AndroidUtilities.dp(86); @@ -592,12 +589,12 @@ public class ChatMediaCell extends ChatBaseCell { } } backgroundWidth = photoWidth + AndroidUtilities.dp(21) + maxWidth; - currentUrl = String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=13&size=72x72&maptype=roadmap&scale=%d&markers=color:red|size:big|%f,%f&sensor=false", lat, lon, Math.min(2, (int) Math.ceil(AndroidUtilities.density)), lat, lon); + currentUrl = String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=15&size=72x72&maptype=roadmap&scale=%d&markers=color:red|size:big|%f,%f&sensor=false", lat, lon, Math.min(2, (int) Math.ceil(AndroidUtilities.density)), lat, lon); } else { photoWidth = AndroidUtilities.dp(200); photoHeight = AndroidUtilities.dp(100); backgroundWidth = photoWidth + AndroidUtilities.dp(12); - currentUrl = String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=13&size=200x100&maptype=roadmap&scale=%d&markers=color:red|size:big|%f,%f&sensor=false", lat, lon, Math.min(2, (int) Math.ceil(AndroidUtilities.density)), lat, lon); + currentUrl = String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=15&size=200x100&maptype=roadmap&scale=%d&markers=color:red|size:big|%f,%f&sensor=false", lat, lon, Math.min(2, (int) Math.ceil(AndroidUtilities.density)), lat, lon); } photoImage.setNeedsQualityThumb(false); @@ -814,11 +811,20 @@ public class ChatMediaCell extends ChatBaseCell { } super.setMessageObject(messageObject); + if (drawForwardedName) { + namesOffset += AndroidUtilities.dp(5); + } + invalidate(); } updateButtonState(dataChanged); } + @Override + protected int getMaxNameWidth() { + return backgroundWidth - AndroidUtilities.dp(14); + } + @Override public ImageReceiver getPhotoImage() { return photoImage; @@ -936,12 +942,13 @@ public class ChatMediaCell extends ChatBaseCell { deleteProgressRect.set(buttonX + AndroidUtilities.dp(3), buttonY + AndroidUtilities.dp(3), buttonX + AndroidUtilities.dp(45), buttonY + AndroidUtilities.dp(45)); } - private void updateSecretTimeText() { - if (currentMessageObject == null || currentMessageObject.isOut()) { + private void updateSecretTimeText(MessageObject messageObject) { + if (messageObject == null || messageObject.isOut()) { return; } - String str = currentMessageObject.getSecretTimeString(); + String str = messageObject.getSecretTimeString(); if (str == null) { + infoLayout = null; return; } if (currentInfoString == null || !currentInfoString.equals(str)) { @@ -1054,7 +1061,7 @@ public class ChatMediaCell extends ChatBaseCell { int offset = AndroidUtilities.dp(2); invalidate((int) deleteProgressRect.left - offset, (int) deleteProgressRect.top - offset, (int) deleteProgressRect.right + offset * 2, (int) deleteProgressRect.bottom + offset * 2); } - updateSecretTimeText(); + updateSecretTimeText(currentMessageObject); } } @@ -1067,7 +1074,11 @@ public class ChatMediaCell extends ChatBaseCell { if (pressedLink != null) { canvas.drawPath(urlPath, urlPaint); } - nameLayout.draw(canvas); + try { + nameLayout.draw(canvas); + } catch (Exception e) { + FileLog.e("tmessages", e); + } canvas.restore(); } if (infoLayout != null && (buttonState == 1 || buttonState == 0 || buttonState == 3 || currentMessageObject.isSecretPhoto())) { @@ -1090,7 +1101,7 @@ public class ChatMediaCell extends ChatBaseCell { locationAddressPaint.setColor(currentMessageObject.isOutOwner() ? 0xff70b15c : 0xff999999); canvas.save(); - canvas.translate(photoImage.getImageX() + photoImage.getImageWidth() + AndroidUtilities.dp(10), photoImage.getImageY() + AndroidUtilities.dp(3)); + canvas.translate(nameOffsetX + photoImage.getImageX() + photoImage.getImageWidth() + AndroidUtilities.dp(10), photoImage.getImageY() + AndroidUtilities.dp(3)); nameLayout.draw(canvas); canvas.restore(); @@ -1103,7 +1114,7 @@ public class ChatMediaCell extends ChatBaseCell { } } else if (nameLayout != null) { canvas.save(); - canvas.translate(photoImage.getImageX() + photoImage.getImageWidth() + AndroidUtilities.dp(10), photoImage.getImageY() + AndroidUtilities.dp(8)); + canvas.translate(nameOffsetX + photoImage.getImageX() + photoImage.getImageWidth() + AndroidUtilities.dp(10), photoImage.getImageY() + AndroidUtilities.dp(8)); nameLayout.draw(canvas); canvas.restore(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java index 5e8767bc6..1d2511841 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -3,7 +3,7 @@ * 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. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -25,6 +25,7 @@ import android.text.TextUtils; import android.text.style.ClickableSpan; import android.view.MotionEvent; import android.view.SoundEffectConstants; +import android.view.ViewStructure; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ImageLoader; @@ -38,6 +39,8 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.Components.StaticLayoutEx; +import org.telegram.ui.Components.URLSpanBotCommand; +import org.telegram.ui.Components.URLSpanNoUnderline; import java.io.File; import java.util.Locale; @@ -114,7 +117,11 @@ public class ChatMessageCell extends ChatBaseCell { if (left <= x && left + block.textLayout.getLineWidth(line) >= x) { Spannable buffer = (Spannable) currentMessageObject.messageText; ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); - if (link.length != 0) { + boolean ignore = false; + if (link.length == 0 || link.length != 0 && link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { + ignore = true; + } + if (!ignore) { if (event.getAction() == MotionEvent.ACTION_DOWN) { resetPressedLink(); pressedLink = link[0]; @@ -130,7 +137,7 @@ public class ChatMessageCell extends ChatBaseCell { } else { if (link[0] == pressedLink) { try { - delegate.didPressUrl(currentMessageObject, pressedLink); + delegate.didPressUrl(currentMessageObject, pressedLink, false); } catch (Exception e) { FileLog.e("tmessages", e); } @@ -174,7 +181,11 @@ public class ChatMessageCell extends ChatBaseCell { if (left <= x && left + descriptionLayout.getLineWidth(line) >= x) { Spannable buffer = (Spannable) currentMessageObject.linkDescription; ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); - if (link.length != 0) { + boolean ignore = false; + if (link.length == 0 || link.length != 0 && link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { + ignore = true; + } + if (!ignore) { resetPressedLink(); pressedLink = link[0]; linkPreviewPressed = true; @@ -350,6 +361,18 @@ public class ChatMessageCell extends ChatBaseCell { } } + @Override + protected void onLongPress() { + if (pressedLink instanceof URLSpanNoUnderline) { + URLSpanNoUnderline url = (URLSpanNoUnderline) pressedLink; + if (url.getURL().startsWith("/")) { + delegate.didPressUrl(currentMessageObject, pressedLink, true); + return; + } + } + super.onLongPress(); + } + @Override public void setMessageObject(MessageObject messageObject) { boolean dataChanged = currentMessageObject == messageObject && (isUserDataChanged() || photoNotSet); @@ -381,7 +404,7 @@ public class ChatMessageCell extends ChatBaseCell { maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(122); drawName = true; } else { - drawName = messageObject.messageOwner.to_id.channel_id != 0; + drawName = messageObject.messageOwner.to_id.channel_id != 0 && !messageObject.isOutOwner(); maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(80); } } else { @@ -390,7 +413,7 @@ public class ChatMessageCell extends ChatBaseCell { drawName = true; } else { maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(80); - drawName = messageObject.messageOwner.to_id.channel_id != 0; + drawName = messageObject.messageOwner.to_id.channel_id != 0 && !messageObject.isOutOwner(); } } @@ -554,7 +577,7 @@ public class ChatMessageCell extends ChatBaseCell { totalHeight += height; for (int a = 0; a < descriptionLayout.getLineCount(); a++) { int lineLeft = (int) Math.ceil(descriptionLayout.getLineLeft(a)); - if (descriptionX == 0) { + if (a == 0 && descriptionX == 0) { descriptionX = -lineLeft; } else { descriptionX = Math.max(descriptionX, -lineLeft); @@ -960,4 +983,12 @@ public class ChatMessageCell extends ChatBaseCell { updateButtonState(false); } } + + @Override + public void onProvideStructure(ViewStructure structure) { + super.onProvideStructure(structure); + if (allowAssistant && Build.VERSION.SDK_INT >= 23) { + structure.setText(currentMessageObject.messageText); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java index 24ab61f16..c79310643 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -158,6 +158,7 @@ public class ChatMusicCell extends ChatBaseCell implements SeekBar.SeekBarDelega invalidate(); } } else if (buttonState == 2) { + radialProgress.setProgress(0, false); FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true, false); buttonState = 3; radialProgress.setBackground(getDrawableForCurrentState(), true, false); @@ -234,7 +235,7 @@ public class ChatMusicCell extends ChatBaseCell implements SeekBar.SeekBarDelega File cacheFile = null; if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() > 0) { cacheFile = new File(currentMessageObject.messageOwner.attachPath); - if(!cacheFile.exists()) { + if (!cacheFile.exists()) { cacheFile = null; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatUnreadCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatUnreadCell.java index 0d8e34908..32e75f701 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatUnreadCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatUnreadCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java index da248b15c..6d55f2227 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -3,7 +3,7 @@ * 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. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -52,9 +52,11 @@ public class DialogCell extends BaseCell { private static Drawable errorDrawable; private static Drawable lockDrawable; private static Drawable countDrawable; + private static Drawable countDrawableGrey; private static Drawable groupDrawable; private static Drawable broadcastDrawable; private static Drawable muteDrawable; + private static Drawable verifiedDrawable; private static Paint linePaint; private static Paint backPaint; @@ -114,6 +116,8 @@ public class DialogCell extends BaseCell { private int countWidth; private StaticLayout countLayout; + private boolean drawVerified; + private int avatarTop = AndroidUtilities.dp(10); private boolean isSelected; @@ -167,9 +171,11 @@ public class DialogCell extends BaseCell { clockDrawable = getResources().getDrawable(R.drawable.msg_clock); errorDrawable = getResources().getDrawable(R.drawable.dialogs_warning); countDrawable = getResources().getDrawable(R.drawable.dialogs_badge); + countDrawableGrey = getResources().getDrawable(R.drawable.dialogs_badge2); groupDrawable = getResources().getDrawable(R.drawable.list_group); broadcastDrawable = getResources().getDrawable(R.drawable.list_broadcast); muteDrawable = getResources().getDrawable(R.drawable.mute_grey); + verifiedDrawable = getResources().getDrawable(R.drawable.check_list); } setBackgroundResource(R.drawable.list_selector); @@ -258,6 +264,7 @@ public class DialogCell extends BaseCell { drawNameGroup = false; drawNameBroadcast = false; drawNameLock = false; + drawVerified = false; if (encryptedChat != null) { drawNameLock = true; @@ -278,6 +285,7 @@ public class DialogCell extends BaseCell { drawNameGroup = true; nameLockTop = AndroidUtilities.dp(17.5f); } + drawVerified = (chat.flags & TLRPC.CHAT_FLAG_IS_VERIFIED) != 0; if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); @@ -357,7 +365,7 @@ public class DialogCell extends BaseCell { messageString = message.messageText; currentMessagePaint = messagePrintingPaint; } else { - if (chat != null && chat.id > 0) { + if (chat != null && chat.id > 0 && fromChat == null) { String name; if (message.isOutOwner()) { name = LocaleController.getString("FromYou", R.string.FromYou); @@ -522,12 +530,18 @@ public class DialogCell extends BaseCell { } } - if (dialogMuted) { + if (dialogMuted && !drawVerified) { int w = AndroidUtilities.dp(6) + muteDrawable.getIntrinsicWidth(); nameWidth -= w; if (LocaleController.isRTL) { nameLeft += w; } + } else if (drawVerified) { + int w = AndroidUtilities.dp(6) + verifiedDrawable.getIntrinsicWidth(); + nameWidth -= w; + if (LocaleController.isRTL) { + nameLeft += w; + } } nameWidth = Math.max(AndroidUtilities.dp(12), nameWidth); @@ -598,8 +612,10 @@ public class DialogCell extends BaseCell { if (nameLayout != null && nameLayout.getLineCount() > 0) { left = nameLayout.getLineLeft(0); widthpx = Math.ceil(nameLayout.getLineWidth(0)); - if (dialogMuted) { + if (dialogMuted && !drawVerified) { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - muteDrawable.getIntrinsicWidth()); + } else if (drawVerified) { + nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - verifiedDrawable.getIntrinsicWidth()); } if (left == 0) { if (widthpx < nameWidth) { @@ -625,7 +641,7 @@ public class DialogCell extends BaseCell { nameLeft -= (nameWidth - widthpx); } } - if (dialogMuted) { + if (dialogMuted || drawVerified) { nameMuteLeft = (int) (nameLeft + left + AndroidUtilities.dp(6)); } } @@ -839,17 +855,25 @@ public class DialogCell extends BaseCell { } } - if (dialogMuted) { + if (dialogMuted && !drawVerified) { setDrawableBounds(muteDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); muteDrawable.draw(canvas); + } else if (drawVerified) { + setDrawableBounds(verifiedDrawable, nameMuteLeft, AndroidUtilities.dp(16.5f)); + verifiedDrawable.draw(canvas); } if (drawError) { setDrawableBounds(errorDrawable, errorLeft, errorTop); errorDrawable.draw(canvas); } else if (drawCount) { - setDrawableBounds(countDrawable, countLeft - AndroidUtilities.dp(5.5f), countTop, countWidth + AndroidUtilities.dp(11), countDrawable.getIntrinsicHeight()); - countDrawable.draw(canvas); + if (dialogMuted) { + setDrawableBounds(countDrawableGrey, countLeft - AndroidUtilities.dp(5.5f), countTop, countWidth + AndroidUtilities.dp(11), countDrawable.getIntrinsicHeight()); + countDrawableGrey.draw(canvas); + } else { + setDrawableBounds(countDrawable, countLeft - AndroidUtilities.dp(5.5f), countTop, countWidth + AndroidUtilities.dp(11), countDrawable.getIntrinsicHeight()); + countDrawable.draw(canvas); + } canvas.save(); canvas.translate(countLeft, countTop + AndroidUtilities.dp(4)); countLayout.draw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java index 6db8d6a06..350417ceb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java index e9faabc65..756dab72f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerActionCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index f50a52ea9..d62ff2f76 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmptyCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmptyCell.java index 0458b98f2..53b3ca3a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmptyCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/EmptyCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java index 3495fa683..61e752237 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GreySectionCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java index f26c8e573..6c6ee1387 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HashtagSearchCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java index 46836e465..f59140098 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LastSeenRadioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LastSeenRadioCell.java new file mode 100644 index 000000000..e26e0ea49 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LastSeenRadioCell.java @@ -0,0 +1,87 @@ +/* + * This is the source code of Telegram for Android v. 3.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RadioButton; + +public class LastSeenRadioCell extends FrameLayout { + + private TextView textView; + private RadioButton radioButton; + private static Paint paint; + private boolean needDivider; + + public LastSeenRadioCell(Context context) { + super(context); + + if (paint == null) { + paint = new Paint(); + paint.setColor(0xffd9d9d9); + paint.setStrokeWidth(1); + } + + textView = new TextView(context); + textView.setTextColor(0xff212121); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setLines(1); + textView.setMaxLines(1); + textView.setSingleLine(true); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 0, 17, 0)); + + radioButton = new RadioButton(context); + radioButton.setSize(AndroidUtilities.dp(20)); + radioButton.setColor(0xffb3b3b3, 0xff37a9f0); + addView(radioButton, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, (LocaleController.isRTL ? 18 : 0), 13, (LocaleController.isRTL ? 0 : 18), 0)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(48) + (needDivider ? 1 : 0)); + + int availableWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - AndroidUtilities.dp(34); + radioButton.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(22), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(22), MeasureSpec.EXACTLY)); + textView.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); + } + + public void setTextColor(int color) { + textView.setTextColor(color); + } + + public void setText(String text, boolean checked, boolean divider) { + textView.setText(text); + radioButton.setChecked(checked, false); + needDivider = divider; + setWillNotDraw(!divider); + } + + public void setChecked(boolean checked, boolean animated) { + radioButton.setChecked(checked, animated); + } + + @Override + protected void onDraw(Canvas canvas) { + if (needDivider) { + canvas.drawLine(getPaddingLeft(), getHeight() - 1, getWidth() - getPaddingRight(), getHeight() - 1, paint); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java index 3cae8a321..62e414eaa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LetterSectionCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java index 6da6b9db5..6d8ba1d42 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LoadingCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationCell.java index a3bbf7ed2..548202dde 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationLoadingCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationLoadingCell.java index dbed1458b..84ab570d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationLoadingCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationLoadingCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationPoweredCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationPoweredCell.java index 3b3393f35..6b0b0677d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationPoweredCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationPoweredCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java index 7674c25ec..f952ae1a3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java index 69c255ea0..13e32de29 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java index b4ce6e08b..4fa39dbf8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -10,6 +10,7 @@ package org.telegram.ui.Cells; import android.content.Context; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; @@ -35,10 +36,14 @@ public class PhotoAttachPhotoCell extends FrameLayout { imageView = new BackupImageView(context); addView(imageView, LayoutHelper.createFrame(80, 80)); - - checkFrame = new FrameLayout(context); - //addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.LEFT | Gravity.TOP, 38, 0, 0, 0)); - addView(checkFrame, LayoutHelper.createFrame(80, 80, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); + checkFrame = new FrameLayout(context) { + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + getParent().requestDisallowInterceptTouchEvent(true); + return super.onInterceptTouchEvent(ev); + } + }; + addView(checkFrame, LayoutHelper.createFrame(42, 42, Gravity.LEFT | Gravity.TOP, 38, 0, 0, 0)); checkBox = new CheckBox(context, R.drawable.checkbig); checkBox.setSize(30); @@ -58,6 +63,14 @@ public class PhotoAttachPhotoCell extends FrameLayout { return photoEntry; } + public BackupImageView getImageView() { + return imageView; + } + + public CheckBox getCheckBox() { + return checkBox; + } + public void setPhotoEntry(MediaController.PhotoEntry entry, boolean last) { photoEntry = entry; isLast = last; @@ -81,6 +94,5 @@ public class PhotoAttachPhotoCell extends FrameLayout { public void setOnCheckClickLisnener(OnClickListener onCheckClickLisnener) { checkFrame.setOnClickListener(onCheckClickLisnener); - imageView.setOnClickListener(onCheckClickLisnener); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java index afc6128bb..8e16a1cc5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java index 458ffa321..fc45e904d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java index cda365f6b..620d2312c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerPhotoCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -13,6 +13,10 @@ import android.view.Gravity; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationCompat.AnimatorListenerAdapterProxy; +import org.telegram.messenger.AnimationCompat.AnimatorSetProxy; +import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; +import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.R; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CheckBox; @@ -23,6 +27,7 @@ public class PhotoPickerPhotoCell extends FrameLayout { public BackupImageView photoImage; public FrameLayout checkFrame; public CheckBox checkBox; + private AnimatorSetProxy animator; public int itemWidth; public PhotoPickerPhotoCell(Context context) { @@ -39,11 +44,44 @@ public class PhotoPickerPhotoCell extends FrameLayout { checkBox.setCheckOffset(AndroidUtilities.dp(1)); checkBox.setDrawBackground(true); checkBox.setColor(0xff3ccaef); - addView(checkBox, LayoutHelper.createFrame(30, 30, Gravity.RIGHT | Gravity.TOP, 0, 6, 6, 0)); + addView(checkBox, LayoutHelper.createFrame(30, 30, Gravity.RIGHT | Gravity.TOP, 0, 4, 4, 0)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY)); } + + public void setChecked(final boolean checked, boolean animated) { + checkBox.setChecked(checked, animated); + if (animator != null) { + animator.cancel(); + animator = null; + } + if (animated) { + if (checked) { + setBackgroundColor(0xff0A0A0A); + } + animator = new AnimatorSetProxy(); + animator.playTogether(ObjectAnimatorProxy.ofFloat(photoImage, "scaleX", checked ? 0.85f : 1.0f), + ObjectAnimatorProxy.ofFloat(photoImage, "scaleY", checked ? 0.85f : 1.0f)); + animator.setDuration(200); + animator.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (animator.equals(animation)) { + animator = null; + if (!checked) { + setBackgroundColor(0); + } + } + } + }); + animator.start(); + } else { + setBackgroundColor(checked ? 0xff0A0A0A : 0); + ViewProxy.setScaleX(photoImage, checked ? 0.85f : 1.0f); + ViewProxy.setScaleY(photoImage, checked ? 0.85f : 1.0f); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java index 7a81c153b..0b71286e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java index 09a7283c3..3ddc2d21b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -21,6 +21,7 @@ import android.view.MotionEvent; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; @@ -43,6 +44,7 @@ public class ProfileSearchCell extends BaseCell { private static Drawable broadcastDrawable; private static Drawable groupDrawable; private static Drawable countDrawable; + private static Drawable checkDrawable; private static Paint linePaint; private CharSequence currentName; @@ -78,6 +80,8 @@ public class ProfileSearchCell extends BaseCell { private int countWidth; private StaticLayout countLayout; + private boolean drawCheck; + private int onlineLeft; private StaticLayout onlineLayout; @@ -115,6 +119,7 @@ public class ProfileSearchCell extends BaseCell { lockDrawable = getResources().getDrawable(R.drawable.list_secret); groupDrawable = getResources().getDrawable(R.drawable.list_group); countDrawable = getResources().getDrawable(R.drawable.dialogs_badge); + checkDrawable = getResources().getDrawable(R.drawable.check_list); } avatarImage = new ImageReceiver(this); @@ -182,6 +187,7 @@ public class ProfileSearchCell extends BaseCell { drawNameBroadcast = false; drawNameLock = false; drawNameGroup = false; + drawCheck = false; if (encryptedChat != null) { drawNameLock = true; @@ -202,9 +208,15 @@ public class ProfileSearchCell extends BaseCell { nameLockTop = AndroidUtilities.dp(28.5f); } else { dialog_id = -chat.id; - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(30); + if (ChatObject.isChannel(chat)) { + drawNameBroadcast = true; + nameLockTop = AndroidUtilities.dp(28.5f); + } else { + drawNameGroup = true; + nameLockTop = AndroidUtilities.dp(30); + } } + drawCheck = (chat.flags & TLRPC.CHAT_FLAG_IS_VERIFIED) != 0; if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? groupDrawable.getIntrinsicWidth() : broadcastDrawable.getIntrinsicWidth()); @@ -487,6 +499,14 @@ public class ProfileSearchCell extends BaseCell { canvas.translate(nameLeft, nameTop); nameLayout.draw(canvas); canvas.restore(); + if (drawCheck) { + if (LocaleController.isRTL) { + setDrawableBounds(checkDrawable, nameLeft - AndroidUtilities.dp(4) - checkDrawable.getIntrinsicWidth(), nameLockTop); + } else { + setDrawableBounds(checkDrawable, nameLeft + (int) nameLayout.getLineWidth(0) + AndroidUtilities.dp(4), nameLockTop); + } + checkDrawable.draw(canvas); + } } if (onlineLayout != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioButtonCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioButtonCell.java index d27164def..1192e1c1a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioButtonCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioButtonCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java index ab3b1eba3..d6fe28335 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java index 01210d647..44ef5ff86 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java index b7a4d0dfa..e391e8d67 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowBottomSectionCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java index b3f238861..006463546 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -23,6 +23,6 @@ public class ShadowSectionCell extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(12), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(12), MeasureSpec.EXACTLY)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index a970671ab..870cf3380 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -204,7 +204,7 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F loaded = false; loading = false; - if (document != null && document.messageOwner.media != null) { + if (document != null && document.messageOwner.media != null && document.messageOwner.media.document != null) { int idx; String name = FileLoader.getDocumentFileName(document.messageOwner.media.document); placeholderImabeView.setVisibility(VISIBLE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java index 69b0bb2bb..915a3866f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java index 09495fc0b..b4631b4d6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java index 7748c7353..4ab37ad3c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -19,6 +19,10 @@ import android.widget.LinearLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationCompat.AnimatorListenerAdapterProxy; +import org.telegram.messenger.AnimationCompat.AnimatorSetProxy; +import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; +import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.MessageObject; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; @@ -51,21 +55,26 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { private LinearLayout videoInfoContainer; private View selector; private CheckBox checkBox; + private FrameLayoutFixed container; + private AnimatorSetProxy animator; public PhotoVideoView(Context context) { super(context); + container = new FrameLayoutFixed(context); + addView(container, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + imageView = new BackupImageView(context); imageView.getImageReceiver().setNeedsQualityThumb(true); imageView.getImageReceiver().setShouldGenerateQualityThumb(true); - addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + container.addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); videoInfoContainer = new LinearLayout(context); videoInfoContainer.setOrientation(LinearLayout.HORIZONTAL); videoInfoContainer.setBackgroundResource(R.drawable.phototime); videoInfoContainer.setPadding(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(3), 0); videoInfoContainer.setGravity(Gravity.CENTER_VERTICAL); - addView(videoInfoContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 16, Gravity.BOTTOM | Gravity.LEFT)); + container.addView(videoInfoContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 16, Gravity.BOTTOM | Gravity.LEFT)); ImageView imageView1 = new ImageView(context); imageView1.setImageResource(R.drawable.ic_video); @@ -83,7 +92,7 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { checkBox = new CheckBox(context, R.drawable.round_check2); checkBox.setVisibility(INVISIBLE); - addView(checkBox, LayoutHelper.createFrame(22, 22, Gravity.RIGHT | Gravity.TOP, 0, 6, 6, 0)); + addView(checkBox, LayoutHelper.createFrame(22, 22, Gravity.RIGHT | Gravity.TOP, 0, 2, 2, 0)); } @Override @@ -93,6 +102,51 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { } return super.onTouchEvent(event); } + + public void setChecked(final boolean checked, boolean animated) { + if (checkBox.getVisibility() != VISIBLE) { + checkBox.setVisibility(VISIBLE); + } + checkBox.setChecked(checked, animated); + if (animator != null) { + animator.cancel(); + animator = null; + } + if (animated) { + if (checked) { + setBackgroundColor(0xfff5f5f5); + } + animator = new AnimatorSetProxy(); + animator.playTogether(ObjectAnimatorProxy.ofFloat(container, "scaleX", checked ? 0.85f : 1.0f), + ObjectAnimatorProxy.ofFloat(container, "scaleY", checked ? 0.85f : 1.0f)); + animator.setDuration(200); + animator.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (animator.equals(animation)) { + animator = null; + if (!checked) { + setBackgroundColor(0); + } + } + } + }); + animator.start(); + } else { + setBackgroundColor(checked ? 0xfff5f5f5 : 0); + ViewProxy.setScaleX(container, checked ? 0.85f : 1.0f); + ViewProxy.setScaleY(container, checked ? 0.85f : 1.0f); + } + } + + @Override + public void clearAnimation() { + super.clearAnimation(); + if (animator != null) { + animator.cancel(); + animator = null; + } + } } public SharedPhotoVideoCell(Context context) { @@ -134,6 +188,7 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { public void setItemsCount(int count) { for (int a = 0; a < photoVideoViews.length; a++) { + photoVideoViews[a].clearAnimation(); photoVideoViews[a].setVisibility(a < count ? VISIBLE : INVISIBLE); } itemsCount = count; @@ -158,10 +213,7 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { } public void setChecked(int a, boolean checked, boolean animated) { - if (photoVideoViews[a].checkBox.getVisibility() != VISIBLE) { - photoVideoViews[a].checkBox.setVisibility(VISIBLE); - } - photoVideoViews[a].checkBox.setChecked(checked, animated); + photoVideoViews[a].setChecked(checked, animated); } public void setItem(int a, int index, MessageObject messageObject) { @@ -195,6 +247,7 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { photoVideoView.imageView.setImageResource(R.drawable.photo_placeholder_in); } } else { + photoVideoViews[a].clearAnimation(); photoVideoViews[a].setVisibility(INVISIBLE); messageObjects[a] = null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java index 5b4d57a52..af2d4bafc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerCell.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -45,7 +45,7 @@ public class StickerCell extends FrameLayoutFixed { } public void setSticker(TLRPC.Document document, int side) { - if (document != null) { + if (document != null && document.thumb != null) { imageView.setImage(document.thumb.location, null, "webp", null); } if (side == -1) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java index c6c8d9418..d450fe343 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -57,7 +57,9 @@ public class StickerEmojiCell extends FrameLayout { public void setSticker(TLRPC.Document document, boolean showEmoji) { if (document != null) { sticker = document; - imageView.setImage(document.thumb.location, null, "webp", null); + if (document.thumb != null) { + imageView.setImage(document.thumb.location, null, "webp", null); + } if (showEmoji) { boolean set = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java index 6e0437d3a..26fd698bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextBlockCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextBlockCell.java index 082d38c0d..3361937f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextBlockCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextBlockCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index 0ff9885e6..d0a318ada 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -63,7 +63,7 @@ public class TextCell extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, multiline ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) : MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), multiline ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) : MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); } public void setTextColor(int color) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java index abc2cf855..159dfeed8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java index e53356c55..87624c6f2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -30,7 +30,7 @@ public class TextColorCell extends FrameLayout { private boolean needDivider; private int currentColor; - private static Drawable colorDrawable; + private Drawable colorDrawable; private static Paint paint; public TextColorCell(Context context) { @@ -40,10 +40,10 @@ public class TextColorCell extends FrameLayout { paint = new Paint(); paint.setColor(0xffd9d9d9); paint.setStrokeWidth(1); - - colorDrawable = getResources().getDrawable(R.drawable.switch_to_on2); } + colorDrawable = getResources().getDrawable(R.drawable.switch_to_on2); + textView = new TextView(context); textView.setTextColor(0xff212121); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); @@ -65,6 +65,7 @@ public class TextColorCell extends FrameLayout { currentColor = color; colorDrawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); setWillNotDraw(!needDivider && currentColor == 0); + invalidate(); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java index eaac8ac81..bfc6e3cbb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -54,7 +54,7 @@ public class TextDetailCell extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64), View.MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64), View.MeasureSpec.EXACTLY)); } public void setTextAndValue(String text, String value) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java index 83ccaf93d..75dced8d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java index f8dec50bd..778f9c60b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java index c48542b97..9fdc79c31 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java index 8c14d5337..363a126ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java index 8e374535b..a6d61f238 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Cells; @@ -106,7 +106,7 @@ public class UserCell extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64), MeasureSpec.EXACTLY)); } public void setStatusColors(int color, int onlineColor) { @@ -215,4 +215,9 @@ public class UserCell extends FrameLayout { } avatarImageView.setImage(photo, "50_50", avatarDrawable); } + + @Override + public boolean hasOverlappingRendering() { + return false; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java index e5eb52b80..273d6f05f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java index ac1fcbdb2..86a18c5ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -137,9 +137,11 @@ public class ChangeChatNameActivity extends BaseFragment { } @Override - public void onOpenAnimationEnd() { - firstNameField.requestFocus(); - AndroidUtilities.showKeyboard(firstNameField); + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen) { + firstNameField.requestFocus(); + AndroidUtilities.showKeyboard(firstNameField); + } } private void saveName() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java index 9c1c9712e..73913744b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -185,8 +185,10 @@ public class ChangeNameActivity extends BaseFragment { } @Override - public void onOpenAnimationEnd() { - firstNameField.requestFocus(); - AndroidUtilities.showKeyboard(firstNameField); + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen) { + firstNameField.requestFocus(); + AndroidUtilities.showKeyboard(firstNameField); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java index 5e3ba8e2a..7e023085b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -175,9 +175,10 @@ public class ChangePhoneActivity extends BaseFragment { } @Override - public void onOpenAnimationEnd() { - super.onOpenAnimationEnd(); - views[currentViewNum].onShow(); + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen) { + views[currentViewNum].onShow(); + } } public void needShowAlert(final String text) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java index 3107c6ae2..ccc9104a1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java index 905a31b8d..874e197e0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -385,8 +385,10 @@ public class ChangeUsernameActivity extends BaseFragment { } @Override - public void onOpenAnimationEnd() { - firstNameField.requestFocus(); - AndroidUtilities.showKeyboard(firstNameField); + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen) { + firstNameField.requestFocus(); + AndroidUtilities.showKeyboard(firstNameField); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java index 7ee04976e..9a31e00ed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -155,7 +155,6 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC }); } }); - } else { if (currentStep == 1) { canCreatePublic = args.getBoolean("canCreatePublic", true); @@ -841,9 +840,11 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC ChipSpan span = createAndPutChipForUser(user); if (span != null) { span.uid = user.id; - return; } ignoreChange = false; + if (span == null) { + return; + } } actionBar.setSubtitle(LocaleController.formatPluralString("Members", selectedContacts.size())); if (searching || searchWas) { @@ -997,8 +998,8 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC } @Override - public void onOpenAnimationEnd() { - if (currentStep != 1) { + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen && currentStep != 1) { nameTextView.requestFocus(); AndroidUtilities.showKeyboard(nameTextView); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelEditActivity.java index ccbafce95..ed6fd6919 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelEditActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelIntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelIntroActivity.java index f9cdacdda..51ff8c81e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelIntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelIntroActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelUsersActivity.java index 21f160389..4e9e404e8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelUsersActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -139,7 +139,6 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { - if (type == 2) { if (isAdmin) { if (i == 0) { @@ -171,7 +170,7 @@ public class ChannelUsersActivity extends BaseFragment implements NotificationCe args.putBoolean("destroyAfterSelect", true); args.putBoolean("returnAsResult", true); args.putBoolean("needForwardCount", false); - args.putBoolean("allowUsernameSearch", false); + args.putBoolean("allowUsernameSearch", true); args.putString("selectAlertString", LocaleController.getString("ChannelAddUserAdminAlert", R.string.ChannelAddUserAdminAlert)); ContactsActivity fragment = new ContactsActivity(args); fragment.setDelegate(new ContactsActivity.ContactsActivityDelegate() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 6f5dce4e9..9d22acab6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -1,13 +1,14 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; +import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; @@ -81,6 +82,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; +import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.Adapters.MentionsAdapter; import org.telegram.ui.Adapters.StickersAdapter; @@ -108,8 +110,10 @@ import org.telegram.ui.Cells.BotHelpCell; import org.telegram.ui.Components.ChatActivityEnterView; import org.telegram.messenger.ImageReceiver; import org.telegram.ui.Components.ChatAttachView; +import org.telegram.ui.Components.PlayerView; import org.telegram.ui.Components.FrameLayoutFixed; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.NumberTextView; import org.telegram.ui.Components.RadioButton; import org.telegram.ui.Components.RecordStatusDrawable; import org.telegram.ui.Components.RecyclerListView; @@ -118,6 +122,7 @@ import org.telegram.ui.Components.SendingFileExDrawable; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.TimerDrawable; import org.telegram.ui.Components.TypingDotsDrawable; +import org.telegram.ui.Components.URLSpanBotCommand; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.URLSpanReplacement; import org.telegram.ui.Components.WebFrameLayout; @@ -171,7 +176,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private FrameLayout avatarContainer; private TextView bottomOverlayText; private TextView secretViewStatusTextView; - private TextView selectedMessagesCountTextView; + private NumberTextView selectedMessagesCountTextView; private RecyclerListView stickersListView; private StickersAdapter stickersAdapter; private FrameLayout stickersPanel; @@ -189,6 +194,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private LinearLayout reportSpamView; private TextView addToContactsButton; private TextView reportSpamButton; + private PlayerView playerView; + + private ObjectAnimatorProxy pagedownButtonAnimation; private TLRPC.User reportSpamUser; @@ -313,10 +321,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not RecyclerListView.OnItemLongClickListener onItemLongClickListener = new RecyclerListView.OnItemLongClickListener() { @Override - public void onItemClick(View view, int position) { + public boolean onItemClick(View view, int position) { if (!actionBar.isActionModeShowed()) { createMenu(view, false); + return true; } + return false; } }; @@ -517,14 +527,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + URLSpanBotCommand.enabled = false; if (userId != 0 && (currentUser.flags & TLRPC.USER_FLAG_BOT) != 0) { BotQuery.loadBotInfo(userId, true, classGuid); + URLSpanBotCommand.enabled = true; } else if (info instanceof TLRPC.TL_chatFull) { for (int a = 0; a < info.participants.participants.size(); a++) { TLRPC.TL_chatParticipant participant = info.participants.participants.get(a); TLRPC.User user = MessagesController.getInstance().getUser(participant.user_id); if (user != null && (user.flags & TLRPC.USER_FLAG_BOT) != 0) { BotQuery.loadBotInfo(user.id, true, classGuid); + URLSpanBotCommand.enabled = true; } } } @@ -637,18 +650,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ResourceLoader.loadRecources(context); - actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setBackButtonDrawable(new BackDrawable(false)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(final int id) { if (id == -1) { - finishFragment(); - } else if (id == -2) { - selectedMessagesIds.clear(); - selectedMessagesCanCopyIds.clear(); - cantDeleteMessagesCount = 0; - actionBar.hideActionMode(); - updateVisibleRows(); + if (actionBar.isActionModeShowed()) { + selectedMessagesIds.clear(); + selectedMessagesCanCopyIds.clear(); + cantDeleteMessagesCount = 0; + actionBar.hideActionMode(); + updateVisibleRows(); + } else { + finishFragment(); + } } else if (id == copy) { String str = ""; ArrayList ids = new ArrayList<>(selectedMessagesCanCopyIds.keySet()); @@ -823,8 +838,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ArrayList photos = new ArrayList<>(); ArrayList captions = new ArrayList<>(); for (HashMap.Entry entry : selectedPhotos.entrySet()) { - photos.add(entry.getValue().path); - captions.add(""); + MediaController.PhotoEntry photoEntry = entry.getValue(); + if (photoEntry.imagePath != null) { + photos.add(photoEntry.imagePath); + captions.add(photoEntry.caption != null ? photoEntry.caption.toString() : null); + } else if (photoEntry.path != null) { + photos.add(photoEntry.path); + captions.add(photoEntry.caption != null ? photoEntry.caption.toString() : null); + } + photoEntry.imagePath = null; + photoEntry.thumbPath = null; + photoEntry.caption = null; } SendMessagesHelper.prepareSendingPhotos(photos, null, dialog_id, replyingMessageObject, captions, chatActivityEnterView == null || chatActivityEnterView.asAdmin()); showReplyPanel(false, null, null, null, false, true); @@ -894,6 +918,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not args.putInt("chat_id", currentChat.id); ProfileActivity fragment = new ProfileActivity(args); fragment.setChatInfo(info); + fragment.setPlayProfileAnimation(true); presentFragment(fragment); } } @@ -902,7 +927,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not avatarContainer = new FrameLayoutFixed(context); avatarContainer.setBackgroundResource(R.drawable.bar_selector); avatarContainer.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); - actionBar.addView(avatarContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 56, 0, 40, 0)); + actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 56, 0, 40, 0)); avatarContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -913,12 +938,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentEncryptedChat != null) { args.putLong("dialog_id", dialog_id); } - presentFragment(new ProfileActivity(args)); + ProfileActivity fragment = new ProfileActivity(args); + fragment.setPlayProfileAnimation(true); + presentFragment(fragment); } else if (currentChat != null) { Bundle args = new Bundle(); args.putInt("chat_id", currentChat.id); ProfileActivity fragment = new ProfileActivity(args); fragment.setChatInfo(info); + fragment.setPlayProfileAnimation(true); presentFragment(fragment); } } else { @@ -1022,7 +1050,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchDownItem.setVisibility(View.GONE); highlightMessageId = Integer.MAX_VALUE; updateVisibleRows(); - scrollToLastMessage(); + scrollToLastMessage(false); } @Override @@ -1094,18 +1122,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionModeViews.clear(); final ActionBarMenu actionMode = actionBar.createActionMode(); - actionModeViews.add(actionMode.addItem(-2, R.drawable.ic_ab_back_grey, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); - selectedMessagesCountTextView = new TextView(actionMode.getContext()); + selectedMessagesCountTextView = new NumberTextView(actionMode.getContext()); selectedMessagesCountTextView.setTextSize(18); selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); selectedMessagesCountTextView.setTextColor(0xff737373); - selectedMessagesCountTextView.setSingleLine(true); - selectedMessagesCountTextView.setLines(1); - selectedMessagesCountTextView.setEllipsize(TextUtils.TruncateAt.END); - selectedMessagesCountTextView.setPadding(AndroidUtilities.dp(11), 0, 0, AndroidUtilities.dp(2)); - selectedMessagesCountTextView.setGravity(Gravity.CENTER_VERTICAL); - actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f)); + actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); selectedMessagesCountTextView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -1145,6 +1167,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int heightSize = MeasureSpec.getSize(heightMeasureSpec); setMeasuredDimension(widthSize, heightSize); + heightSize -= getPaddingTop(); int keyboardSize = getKeyboardHeight(); @@ -1220,7 +1243,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not switch (verticalGravity) { case Gravity.TOP: - childTop = lp.topMargin; + childTop = lp.topMargin + getPaddingTop(); break; case Gravity.CENTER_VERTICAL: childTop = ((b - paddingBottom) - t - height) / 2 + lp.topMargin - lp.bottomMargin; @@ -1399,21 +1422,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int visibleItemCount = firstVisibleItem == RecyclerView.NO_POSITION ? 0 : Math.abs(chatLayoutManager.findLastVisibleItemPosition() - firstVisibleItem) + 1; if (visibleItemCount > 0) { int totalItemCount = chatAdapter.getItemCount(); - if (firstVisibleItem <= 10) { - if (!endReached && !loading) { - if (messagesByDays.size() != 0) { - MessagesController.getInstance().loadMessages(dialog_id, 20, maxMessageId, !cacheEndReached, minDate, classGuid, 0, 0, channelMessagesImportant); - } else { - MessagesController.getInstance().loadMessages(dialog_id, 20, 0, !cacheEndReached, minDate, classGuid, 0, 0, channelMessagesImportant); - } - loading = true; + if (firstVisibleItem <= 25 && !endReached && !loading) { + if (messagesByDays.size() != 0) { + MessagesController.getInstance().loadMessages(dialog_id, 50, maxMessageId, !cacheEndReached, minDate, classGuid, 0, 0, channelMessagesImportant); + } else { + MessagesController.getInstance().loadMessages(dialog_id, 50, 0, !cacheEndReached, minDate, classGuid, 0, 0, channelMessagesImportant); } + loading = true; } - if (firstVisibleItem + visibleItemCount >= totalItemCount - 6) { - if (!forward_end_reached && !loadingForward) { - MessagesController.getInstance().loadMessages(dialog_id, 20, minMessageId, !cacheEndReached, maxDate, classGuid, 1, 0, channelMessagesImportant); - loadingForward = true; - } + if (!forward_end_reached && !loadingForward && firstVisibleItem + visibleItemCount >= totalItemCount - 10) { + MessagesController.getInstance().loadMessages(dialog_id, 50, minMessageId, !cacheEndReached, maxDate, classGuid, 1, 0, channelMessagesImportant); + loadingForward = true; } if (firstVisibleItem + visibleItemCount == totalItemCount && forward_end_reached) { showPagedownButton(false, true); @@ -1464,6 +1483,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AndroidUtilities.cancelRunOnUIThread(openSecretPhotoRunnable); openSecretPhotoRunnable = null; } + chatListView.setOnItemClickListener(onItemClickListener); + chatListView.setOnItemLongClickListener(onItemLongClickListener); + chatListView.setLongClickable(true); } } } @@ -1562,7 +1584,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not reportSpamButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if (reportSpamUser == null) { + if (reportSpamUser == null || getParentActivity() == null) { return; } AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); @@ -1575,6 +1597,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { + if (reportSpamUser == null) { + return; + } TLRPC.TL_messages_reportSpam req = new TLRPC.TL_messages_reportSpam(); req.peer = new TLRPC.TL_inputPeerUser(); req.peer.user_id = reportSpamUser.id; @@ -1761,12 +1786,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); } + pagedownButton = new ImageView(context); + pagedownButton.setVisibility(View.INVISIBLE); + pagedownButton.setImageResource(R.drawable.pagedown); + contentView.addView(pagedownButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 4)); + pagedownButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (returnToMessageId > 0) { + scrollToMessageId(returnToMessageId, 0, true); + } else { + scrollToLastMessage(true); + } + } + }); + chatActivityEnterView = new ChatActivityEnterView(getParentActivity(), contentView, this, true); chatActivityEnterView.setDialogId(dialog_id); chatActivityEnterView.addToAttachLayout(menuItem); chatActivityEnterView.setId(id_chat_compose_panel); chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands); - contentView.addView(chatActivityEnterView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); + contentView.addView(chatActivityEnterView, contentView.getChildCount() - 1, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { @Override public void onMessageSend(String message) { @@ -2072,21 +2112,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomOverlayChatText.setTextColor(0xff3e6fa1); bottomOverlayChat.addView(bottomOverlayChatText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); - pagedownButton = new ImageView(context); - pagedownButton.setVisibility(View.INVISIBLE); - pagedownButton.setImageResource(R.drawable.pagedown); - contentView.addView(pagedownButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 6, 4)); - pagedownButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (returnToMessageId > 0) { - scrollToMessageId(returnToMessageId, 0, true); - } else { - scrollToLastMessage(); - } - } - }); - if (loading && messages.isEmpty()) { progressView.setVisibility(View.VISIBLE); chatListView.setEmptyView(null); @@ -2097,6 +2122,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setButtons(botButtons); + if (!AndroidUtilities.isTablet() || AndroidUtilities.isSmallTablet()) { + contentView.addView(playerView = new PlayerView(context, this), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + } + updateContactStatus(); updateBottomOverlay(); updateSecretStatus(); @@ -2174,6 +2203,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not FileLog.e("tmessages", e); } } else if (which == attach_gallery) { + if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4); + return; + } PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(false, ChatActivity.this); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override @@ -2247,6 +2280,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); presentFragment(fragment); } else if (which == attach_document) { + if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4); + return; + } DocumentSelectActivity fragment = new DocumentSelectActivity(); fragment.setDelegate(new DocumentSelectActivity.DocumentSelectActivityDelegate() { @Override @@ -2269,6 +2306,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); presentFragment(fragment); } else if (which == attach_audio) { + if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4); + return; + } AudioSelectActivity fragment = new AudioSelectActivity(); fragment.setDelegate(new AudioSelectActivity.AudioSelectActivityDelegate() { @Override @@ -2279,6 +2320,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); presentFragment(fragment); } else if (which == attach_contact) { + if (Build.VERSION.SDK_INT >= 23) { + if (getParentActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { + getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 5); + return; + } + } try { Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); intent.setType(ContactsContract.CommonDataKinds.Phone.CONTENT_TYPE); @@ -2289,6 +2336,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + @Override + public boolean dismissDialogOnPause(Dialog dialog) { + return !(dialog == chatAttachViewSheet && PhotoViewer.getInstance().isVisible()) && super.dismissDialogOnPause(dialog); + } + private void searchLinks(CharSequence charSequence, boolean force) { if (currentEncryptedChat != null) { return; @@ -2631,9 +2683,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatAdapter.notifyDataSetChanged(); } - private void scrollToLastMessage() { + private void scrollToLastMessage(boolean pagedown) { if (forward_end_reached && first_unread_id == 0 && startLoadFromMessageId == 0) { - chatLayoutManager.scrollToPositionWithOffset(messages.size() - 1, -100000 - chatListView.getPaddingTop()); + if (pagedown && chatLayoutManager.findLastCompletelyVisibleItemPosition() == chatAdapter.getItemCount() - 1) { + showPagedownButton(false, true); + highlightMessageId = Integer.MAX_VALUE; + updateVisibleRows(); + } else { + chatLayoutManager.scrollToPositionWithOffset(messages.size() - 1, -100000 - chatListView.getPaddingTop()); + } } else { clearChatData(); MessagesController.getInstance().loadMessages(dialog_id, 30, 0, !cacheEndReached, 0, classGuid, 0, 0, channelMessagesImportant); @@ -2710,7 +2768,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatLayoutManager.scrollToPositionWithOffset(messages.size() - messages.indexOf(object), -chatListView.getPaddingTop() - AndroidUtilities.dp(7) + yOffset); } updateVisibleRows(); - showPagedownButton(true, true); + boolean found = false; + int count = chatListView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = chatListView.getChildAt(a); + if (view instanceof ChatBaseCell) { + ChatBaseCell cell = (ChatBaseCell) view; + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == object.getId()) { + found = true; + break; + } + } else if (view instanceof ChatActionCell) { + ChatActionCell cell = (ChatActionCell) view; + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == object.getId()) { + found = true; + break; + } + } + } + if (!found) { + showPagedownButton(true, true); + } } else { query = true; } @@ -2761,26 +2839,40 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (show) { - if (pagedownButton.getVisibility() == View.INVISIBLE) { + if (pagedownButton.getTag() == null) { + if (pagedownButtonAnimation != null) { + pagedownButtonAnimation.cancel(); + pagedownButtonAnimation = null; + } if (animated) { + if (ViewProxy.getTranslationY(pagedownButton) == 0) { + ViewProxy.setTranslationY(pagedownButton, AndroidUtilities.dp(100)); + } pagedownButton.setVisibility(View.VISIBLE); - ViewProxy.setAlpha(pagedownButton, 0); - ObjectAnimatorProxy.ofFloatProxy(pagedownButton, "alpha", 1.0f).setDuration(200).start(); + pagedownButton.setTag(1); + pagedownButtonAnimation = ObjectAnimatorProxy.ofFloatProxy(pagedownButton, "translationY", 0).setDuration(200).start(); } else { pagedownButton.setVisibility(View.VISIBLE); } } } else { returnToMessageId = 0; - if (pagedownButton.getVisibility() == View.VISIBLE) { + if (pagedownButton.getTag() != null) { + pagedownButton.setTag(null); + if (pagedownButtonAnimation != null) { + pagedownButtonAnimation.cancel(); + pagedownButtonAnimation = null; + } if (animated) { - ObjectAnimatorProxy.ofFloatProxy(pagedownButton, "alpha", 0.0f).setDuration(200).addListener(new AnimatorListenerAdapterProxy() { + pagedownButtonAnimation = ObjectAnimatorProxy.ofFloatProxy(pagedownButton, "translationY", AndroidUtilities.dp(100)).setDuration(200).addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { + pagedownButton.clearAnimation(); pagedownButton.setVisibility(View.INVISIBLE); } }).start(); } else { + pagedownButton.clearAnimation(); pagedownButton.setVisibility(View.INVISIBLE); } } @@ -2857,10 +2949,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private int updateOnlineCount() { + onlineCount = 0; if (!(info instanceof TLRPC.TL_chatFull)) { return 0; } - onlineCount = 0; int currentTime = ConnectionsManager.getInstance().getCurrentTime(); for (TLRPC.TL_chatParticipant participant : info.participants.participants) { TLRPC.User user = MessagesController.getInstance().getUser(participant.user_id); @@ -3022,15 +3114,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (actionBar.isActionModeShowed()) { if (selectedMessagesIds.isEmpty()) { actionBar.hideActionMode(); - } - actionBar.createActionMode().getItem(copy).setVisibility(selectedMessagesCanCopyIds.size() != 0 ? View.VISIBLE : View.GONE); - actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); - if (actionBar.createActionMode().getItem(reply) != null) { - boolean allowChatActions = true; - if (isBroadcast || currentChat != null && (ChatObject.isNotInChat(currentChat) || ChatObject.isChannel(currentChat) && (currentChat.flags & TLRPC.CHAT_FLAG_ADMIN) == 0 && (currentChat.flags & TLRPC.CHAT_FLAG_USER_IS_EDITOR) == 0)) { - allowChatActions = false; + } else { + actionBar.createActionMode().getItem(copy).setVisibility(selectedMessagesCanCopyIds.size() != 0 ? View.VISIBLE : View.GONE); + actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); + if (actionBar.createActionMode().getItem(reply) != null) { + boolean allowChatActions = true; + if (isBroadcast || currentChat != null && (ChatObject.isNotInChat(currentChat) || ChatObject.isChannel(currentChat) && (currentChat.flags & TLRPC.CHAT_FLAG_ADMIN) == 0 && (currentChat.flags & TLRPC.CHAT_FLAG_USER_IS_EDITOR) == 0)) { + allowChatActions = false; + } + actionBar.createActionMode().getItem(reply).setVisibility(allowChatActions && selectedMessagesIds.size() == 1 ? View.VISIBLE : View.GONE); } - actionBar.createActionMode().getItem(reply).setVisibility(allowChatActions && selectedMessagesIds.size() == 1 ? View.VISIBLE : View.GONE); } } } @@ -3058,7 +3151,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (!selectedMessagesIds.isEmpty()) { - selectedMessagesCountTextView.setText(String.format("%d", selectedMessagesIds.size())); + selectedMessagesCountTextView.setNumber(selectedMessagesIds.size(), true); } } @@ -3611,13 +3704,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Collections.reverse(messArr); } ReplyMessageQuery.loadReplyMessagesForMessages(messArr, dialog_id); - for (int a = 0; a < messArr.size(); a++) { MessageObject obj = messArr.get(a); if (messagesDict.containsKey(obj.getId())) { continue; } - if (obj.getId() > 0) { maxMessageId = Math.min(obj.getId(), maxMessageId); minMessageId = Math.max(obj.getId(), minMessageId); @@ -3747,11 +3838,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newRowsCount--; } if (newRowsCount != 0) { + int firstVisPos = chatLayoutManager.findLastVisibleItemPosition(); + int top = 0; + if (firstVisPos != chatLayoutManager.getItemCount() - 1) { + firstVisPos = RecyclerView.NO_POSITION; + } else { + View firstVisView = chatListView.getChildAt(chatListView.getChildCount() - 1); + top = ((firstVisView == null) ? 0 : firstVisView.getTop()) - chatListView.getPaddingTop(); + } chatAdapter.notifyItemRangeInserted(chatAdapter.getItemCount() - 1, newRowsCount); + if (firstVisPos != RecyclerView.NO_POSITION) { + chatLayoutManager.scrollToPositionWithOffset(firstVisPos, top); + } } loadingForward = false; } else { - if (messArr.size() < count) { + if (messArr.size() < count && load_type != 3) { if (isCache) { if (currentEncryptedChat != null || isBroadcast) { endReached = true; @@ -3802,7 +3904,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not View firstVisView = chatListView.getChildAt(chatListView.getChildCount() - 1); int top = ((firstVisView == null) ? 0 : firstVisView.getTop()) - chatListView.getPaddingTop(); if (newRowsCount - (endReached ? 1 : 0) > 0) { - chatAdapter.notifyItemRangeInserted((chatAdapter.isBot ? 2 : 1), newRowsCount - (endReached ? 1 : 0)); + chatAdapter.notifyItemRangeInserted((chatAdapter.isBot ? 2 : 1) + (endReached ? 0 : 1), newRowsCount - (endReached ? 1 : 0)); } chatLayoutManager.scrollToPositionWithOffset(firstVisPos + newRowsCount - (endReached ? 1 : 0), top); } else if (endReached) { @@ -3849,8 +3951,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateBottomOverlay(); } - if (progressView != null) { - progressView.setVisibility(View.INVISIBLE); + if (newRowsCount == 0 && currentEncryptedChat != null && !endReached) { + first = true; + chatListView.setEmptyView(null); + emptyViewContainer.setVisibility(View.INVISIBLE); + if (messagesByDays.size() != 0) { + MessagesController.getInstance().loadMessages(dialog_id, 50, maxMessageId, !cacheEndReached, minDate, classGuid, 0, 0, channelMessagesImportant); + } else { + MessagesController.getInstance().loadMessages(dialog_id, 50, 0, !cacheEndReached, minDate, classGuid, 0, 0, channelMessagesImportant); + } + loading = true; + } else { + if (progressView != null) { + progressView.setVisibility(View.INVISIBLE); + } } } } else if (id == NotificationCenter.emojiDidLoaded) { @@ -3944,7 +4058,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not timerDrawable.setTime(action.ttl_seconds); } if (obj.isOut() && obj.isSending()) { - scrollToLastMessage(); + scrollToLastMessage(false); return; } if (messagesDict.containsKey(obj.getId())) { @@ -4254,6 +4368,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject obj = messagesDict.get(msgId); if (obj != null) { Integer newMsgId = (Integer) args[1]; + if (!newMsgId.equals(msgId) && messagesDict.containsKey(newMsgId)) { + MessageObject removed = messagesDict.remove(msgId); + if (removed != null) { + int index = messages.indexOf(removed); + messages.remove(index); + ArrayList dayArr = messagesByDays.get(removed.dateKey); + dayArr.remove(obj); + if (dayArr.isEmpty()) { + messagesByDays.remove(obj.dateKey); + if (index >= 0 && index < messages.size()) { + messages.remove(index); + } + } + chatAdapter.notifyDataSetChanged(); + } + return; + } TLRPC.Message newMsgObj = (TLRPC.Message) args[2]; boolean mediaUpdated = false; try { @@ -4265,27 +4396,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not obj.messageOwner.media = newMsgObj.media; obj.generateThumbs(true); } - int oldCount = messagesDict.size(); - MessageObject removed = messagesDict.remove(msgId); + messagesDict.remove(msgId); messagesDict.put(newMsgId, obj); obj.messageOwner.id = newMsgId; obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; ArrayList messArr = new ArrayList<>(); messArr.add(obj); ReplyMessageQuery.loadReplyMessagesForMessages(messArr, dialog_id); - updateVisibleRows(); - if (oldCount != messagesDict.size()) { - int index = messages.indexOf(removed); - messages.remove(index); - ArrayList dayArr = messagesByDays.get(removed.dateKey); - dayArr.remove(obj); - if (dayArr.isEmpty()) { - messagesByDays.remove(obj.dateKey); - if (index >= 0 && index < messages.size()) { - messages.remove(index); - } - } - chatAdapter.notifyDataSetChanged(); + if (chatAdapter != null) { + chatAdapter.updateRowWithMessageObject(obj); } if (mediaUpdated && chatLayoutManager.findLastVisibleItemPosition() >= messages.size() - 1) { moveScrollToLastMessage(); @@ -4297,7 +4416,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject obj = messagesDict.get(msgId); if (obj != null) { obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - updateVisibleRows(); + if (chatAdapter != null) { + chatAdapter.updateRowWithMessageObject(obj); + } } } else if (id == NotificationCenter.messageSendError) { Integer msgId = (Integer) args[0]; @@ -4322,14 +4443,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not hasBotsCommands = false; botInfo.clear(); botsCount = 0; + URLSpanBotCommand.enabled = false; for (int a = 0; a < info.participants.participants.size(); a++) { TLRPC.TL_chatParticipant participant = info.participants.participants.get(a); TLRPC.User user = MessagesController.getInstance().getUser(participant.user_id); if (user != null && (user.flags & TLRPC.USER_FLAG_BOT) != 0) { + URLSpanBotCommand.enabled = true; botsCount++; BotQuery.loadBotInfo(user.id, true, classGuid); } } + if (chatListView != null) { + chatListView.invalidateViews(); + } } if (chatActivityEnterView != null) { chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands); @@ -4386,22 +4512,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); } } else if (id == NotificationCenter.audioDidReset || id == NotificationCenter.audioPlayStateChanged) { - Integer mid = (Integer) args[0]; if (chatListView != null) { int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); if (view instanceof ChatAudioCell) { ChatAudioCell cell = (ChatAudioCell) view; - if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { + if (cell.getMessageObject() != null) { cell.updateButtonState(false); - break; } } else if (view instanceof ChatMusicCell) { ChatMusicCell cell = (ChatMusicCell) view; - if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { + if (cell.getMessageObject() != null) { cell.updateButtonState(false); - break; } } } @@ -4537,15 +4660,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not View view = chatListView.getChildAt(a); if (view instanceof ChatAudioCell) { ChatAudioCell cell = (ChatAudioCell) view; - if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { + if (cell.getMessageObject() != null) { cell.updateButtonState(false); - break; } } else if (view instanceof ChatMusicCell) { ChatMusicCell cell = (ChatMusicCell) view; - if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { + if (cell.getMessageObject() != null) { cell.updateButtonState(false); - break; } } } @@ -4581,7 +4702,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - if (changed) { + if (changed && chatLayoutManager != null) { if (mediaUpdated && chatLayoutManager.findLastVisibleItemPosition() >= messages.size() - (chatAdapter.isBot ? 2 : 1)) { moveScrollToLastMessage(); } @@ -4732,26 +4853,30 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - protected void onOpenAnimationStart() { - NotificationCenter.getInstance().setAnimationInProgress(true); - openAnimationEnded = false; + public void onTransitionAnimationStart(boolean isOpen, boolean backward) { + if (isOpen) { + NotificationCenter.getInstance().setAnimationInProgress(true); + openAnimationEnded = false; + } } @Override - protected void onOpenAnimationEnd() { - NotificationCenter.getInstance().setAnimationInProgress(false); - openAnimationEnded = true; - int count = chatListView.getChildCount(); - for (int a = 0; a < count; a++) { - View view = chatListView.getChildAt(a); - if (view instanceof ChatMediaCell) { - ChatMediaCell cell = (ChatMediaCell) view; - cell.setAllowedToSetPhoto(true); + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen) { + NotificationCenter.getInstance().setAnimationInProgress(false); + openAnimationEnded = true; + int count = chatListView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = chatListView.getChildAt(a); + if (view instanceof ChatMediaCell) { + ChatMediaCell cell = (ChatMediaCell) view; + cell.setAllowedToSetPhoto(true); + } } - } - if (currentUser != null) { - MessagesController.getInstance().loadFullUser(MessagesController.getInstance().getUser(currentUser.id), classGuid); + if (currentUser != null) { + MessagesController.getInstance().loadFullUser(MessagesController.getInstance().getUser(currentUser.id), classGuid); + } } } @@ -4983,6 +5108,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (lastMessageText != null) { preferences.edit().remove("dialog_" + dialog_id).commit(); chatActivityEnterView.setFieldText(lastMessageText); + if (getArguments().getBoolean("hasUrl", false)) { + chatActivityEnterView.setSelection(lastMessageText.indexOf('\n') + 1); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (chatActivityEnterView != null) { + chatActivityEnterView.setFieldFocused(true); + chatActivityEnterView.openKeyboard(); + } + } + }, 700); + } } } else { preferences.edit().remove("dialog_" + dialog_id).commit(); @@ -5112,28 +5249,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { selectedMessagesCountTextView.setTextSize(20); } - if (AndroidUtilities.isTablet()) { - if (AndroidUtilities.isSmallTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { - actionBar.setBackButtonImage(R.drawable.ic_ab_back); - } else { - actionBar.setBackButtonImage(R.drawable.ic_close_white); - } - } + int padding = (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2; avatarContainer.setPadding(avatarContainer.getPaddingLeft(), padding, avatarContainer.getPaddingRight(), padding); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) avatarContainer.getLayoutParams(); layoutParams.topMargin = (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); avatarContainer.setLayoutParams(layoutParams); - if (!resume) { - int firstVisPos = chatLayoutManager.findLastVisibleItemPosition(); - if (firstVisPos == RecyclerView.NO_POSITION) { - firstVisPos = 0; + if (AndroidUtilities.isTablet()) { + if (AndroidUtilities.isSmallTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { + actionBar.setBackButtonDrawable(new BackDrawable(false)); + if (playerView != null && playerView.getParent() == null) { + ((ViewGroup) fragmentView).addView(playerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + } + } else { + actionBar.setBackButtonDrawable(new BackDrawable(true)); + if (playerView != null && playerView.getParent() != null) { + fragmentView.setPadding(0, 0, 0, 0); + ((ViewGroup) fragmentView).removeView(playerView); + } } - View firstVisView = chatListView.getChildAt(chatListView.getChildCount() - 1); - int top = ((firstVisView == null) ? 0 : firstVisView.getTop()) - chatListView.getPaddingTop(); - chatListView.setAdapter(null); - chatListView.setAdapter(chatAdapter); - chatLayoutManager.scrollToPositionWithOffset(firstVisPos, top); + return false; } return true; } @@ -5380,11 +5515,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int a = 0; a < actionModeViews.size(); a++) { View view = actionModeViews.get(a); AndroidUtilities.clearDrawableAnimation(view); - if (a < 1) { - animators.add(ObjectAnimatorProxy.ofFloat(view, "translationX", -AndroidUtilities.dp(56), 0)); - } else { - animators.add(ObjectAnimatorProxy.ofFloat(view, "scaleY", 0.1f, 1.0f)); - } + animators.add(ObjectAnimatorProxy.ofFloat(view, "scaleY", 0.1f, 1.0f)); } animatorSet.playTogether(animators); animatorSet.setDuration(250); @@ -5392,7 +5523,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } addToSelectedMessages(message); - updateActionModeTitle(); + selectedMessagesCountTextView.setNumber(1, false); updateVisibleRows(); } @@ -5460,10 +5591,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (path == null || path.length() == 0) { path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); } - if (selectedObject.type == 3) { - MediaController.saveFile(path, getParentActivity(), 1, null); - } else if (selectedObject.type == 1) { - MediaController.saveFile(path, getParentActivity(), 0, null); + if (selectedObject.type == 3 || selectedObject.type == 1) { + if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); + return; + } + MediaController.saveFile(path, getParentActivity(), selectedObject.type == 3 ? 1 : 0, null); } else if (selectedObject.type == 8 || selectedObject.type == 9 || selectedObject.type == 14) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(selectedObject.messageOwner.media.document.mime_type); @@ -5516,6 +5649,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path))); getParentActivity().startActivityForResult(Intent.createChooser(intent, LocaleController.getString("ShareFile", R.string.ShareFile)), 500); } else { + if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); + return; + } MediaController.saveFile(path, getParentActivity(), 0, null); } } @@ -5524,6 +5661,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (option == 9) { StickersQuery.loadStickers(this, selectedObject.getInputStickerSet()); } else if (option == 10) { + if (Build.VERSION.SDK_INT >= 23 && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); + return; + } String fileName = FileLoader.getDocumentFileName(selectedObject.messageOwner.media.document); if (fileName == null || fileName.length() == 0) { fileName = selectedObject.getFileName(); @@ -5777,7 +5918,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void cancelButtonPressed() { + public boolean cancelButtonPressed() { + return true; } @Override @@ -5890,7 +6032,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragment.setSearchString(url); presentFragment(fragment); } else if (url.startsWith("/")) { - chatActivityEnterView.setCommand(null, url); + chatActivityEnterView.setCommand(null, url, false); } } }); @@ -5899,6 +6041,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (view instanceof ChatBaseCell) { + if (currentEncryptedChat == null) { + ((ChatBaseCell) view).setAllowAssistant(true); + } ((ChatBaseCell) view).setDelegate(new ChatBaseCell.ChatBaseCellDelegate() { @Override public void didPressedChannelAvatar(ChatBaseCell cell, TLRPC.Chat chat) { @@ -5922,7 +6067,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (user != null && user.id != UserConfig.getClientUserId()) { Bundle args = new Bundle(); args.putInt("user_id", user.id); - presentFragment(new ProfileActivity(args)); + ProfileActivity fragment = new ProfileActivity(args); + fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == user.id); + presentFragment(fragment); } } @@ -5945,7 +6092,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void didPressUrl(MessageObject messageObject, final ClickableSpan url) { + public void didPressUrl(MessageObject messageObject, final ClickableSpan url, boolean longPress) { if (url instanceof URLSpanNoUnderline) { String str = ((URLSpanNoUnderline) url).getURL(); if (str.startsWith("@")) { @@ -5959,7 +6106,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not presentFragment(fragment); } } else if (str.startsWith("/")) { - chatActivityEnterView.setCommand(messageObject, str); + if (URLSpanBotCommand.enabled) { + chatActivityEnterView.setCommand(messageObject, str, longPress); + } } } else if (url instanceof URLSpanReplacement) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); @@ -6179,7 +6328,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (uid != UserConfig.getClientUserId()) { Bundle args = new Bundle(); args.putInt("user_id", uid); - presentFragment(new ProfileActivity(args)); + if (currentEncryptedChat != null && uid == currentUser.id) { + args.putLong("dialog_id", dialog_id); + } + ProfileActivity fragment = new ProfileActivity(args); + fragment.setPlayProfileAnimation(currentUser != null && currentUser.id == uid); + presentFragment(fragment); } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java index 8d50b48e3..a91770158 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -97,7 +97,7 @@ public class AlertsCreator { @Override public void onClick(DialogInterface dialogInterface, int i) { try { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://telegram.org/faq#can-39t-send-messages-to-non-contacts")); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(LocaleController.getString("NobodyLikesSpamUrl", R.string.NobodyLikesSpamUrl))); intent.putExtra(Browser.EXTRA_APPLICATION_ID, fragment.getParentActivity().getPackageName()); fragment.getParentActivity().startActivity(intent); } catch (Exception e) { @@ -107,6 +107,7 @@ public class AlertsCreator { }); break; case "USER_BLOCKED": + case "USER_BOT": case "USER_ID_INVALID": builder.setMessage(LocaleController.getString("ChannelUserCantAdd", R.string.ChannelUserCantAdd)); break; @@ -116,6 +117,9 @@ public class AlertsCreator { case "USER_NOT_MUTUAL_CONTACT": builder.setMessage(LocaleController.getString("ChannelUserLeftError", R.string.ChannelUserLeftError)); break; + case "ADMINS_TOO_MUCH": + builder.setMessage(LocaleController.getString("ChannelUserCantAdmin", R.string.ChannelUserCantAdmin)); + break; } builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); fragment.showDialog(builder.create(), true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java index 8e23920b6..89e754c65 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; @@ -11,6 +11,7 @@ package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; @@ -22,18 +23,15 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; -import org.telegram.messenger.UserConfig; import org.telegram.messenger.ApplicationLoader; -import java.util.Locale; - public class AvatarDrawable extends Drawable { private static Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private static TextPaint namePaint; private static TextPaint namePaintSmall; - private static int[] arrColors = {0xffe56555, 0xfff28c48, 0xffeec764, 0xff76c84d, 0xff5fbed5, 0xff549cdd, 0xff8e85ee, 0xfff2749a}; - private static int[] arrColorsProfiles = {0xffd86f65, 0xfff69d61, 0xfffabb3c, 0xff67b35d, 0xff56a2bb, 0xff5c98cd, 0xff8c79d2, 0xfff37fa6}; + private static int[] arrColors = {0xffe56555, 0xfff28c48, 0xff549cdd, 0xff76c84d, 0xff5fbed5, 0xff549cdd, 0xff8e85ee, 0xfff2749a}; + private static int[] arrColorsProfiles = {0xffd86f65, 0xfff69d61, 0xff8c79d2, 0xff67b35d, 0xff56a2bb, 0xff5c98cd, 0xff8c79d2, 0xfff37fa6}; private static int[] arrColorsProfilesBack = {0xffca6056, 0xfff18944, 0xff7d6ac4, 0xff56a14c, 0xff4492ac, 0xff4c84b6, 0xff7d6ac4, 0xff4c84b6}; private static int[] arrColorsProfilesText = {0xfff9cbc5, 0xfffdddc8, 0xffcdc4ed, 0xffc0edba, 0xffb8e2f0, 0xffb3d7f7, 0xffcdc4ed, 0xffb3d7f7}; private static int[] arrColorsNames = {0xffca5650, 0xffd87b29, 0xff4e92cc, 0xff50b232, 0xff42b1a8, 0xff4e92cc, 0xff4e92cc, 0xff4e92cc}; @@ -102,7 +100,7 @@ public class AvatarDrawable extends Drawable { if (id >= 0 && id < 8) { return id; } - try { + /*try { String str; if (id >= 0) { str = String.format(Locale.US, "%d%d", id, UserConfig.getClientUserId()); @@ -121,8 +119,8 @@ public class AvatarDrawable extends Drawable { return Math.abs(b) % arrColors.length; } catch (Exception e) { FileLog.e("tmessages", e); - } - return id % arrColors.length; + }*/ + return Math.abs(id % arrColors.length); } public static int getColorForId(int id) { @@ -276,7 +274,7 @@ public class AvatarDrawable extends Drawable { @Override public int getOpacity() { - return 0; + return PixelFormat.TRANSPARENT; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java index abda6c200..d740dfa5e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java @@ -1,18 +1,21 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; +import android.Manifest; import android.app.Activity; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.media.ExifInterface; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; @@ -73,6 +76,12 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg } public void openGallery() { + if (Build.VERSION.SDK_INT >= 23 && parentFragment != null && parentFragment.getParentActivity() != null) { + if (parentFragment.getParentActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + parentFragment.getParentActivity().requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 4); + return; + } + } PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(true, null); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override @@ -179,6 +188,7 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg } smallPhoto = ImageLoader.scaleAndSaveImage(bitmap, 100, 100, 80, false); bigPhoto = ImageLoader.scaleAndSaveImage(bitmap, 800, 800, 80, false, 320, 320); + bitmap.recycle(); if (bigPhoto != null && smallPhoto != null) { if (returnOnly) { if (delegate != null) { @@ -195,7 +205,7 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg } @Override - public void didFinishEdit(Bitmap bitmap, Bundle args) { + public void didFinishEdit(Bitmap bitmap) { processBitmap(bitmap); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index 4ff18a9bf..dc1e5f8a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java index bbbe04648..10d522db3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index a121a040d..3bf9cc229 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -1,17 +1,23 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; import android.media.AudioManager; +import android.os.Build; import android.os.PowerManager; import android.text.Editable; import android.text.TextWatcher; @@ -22,7 +28,8 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.FrameLayout; @@ -74,6 +81,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private ImageView audioSendButton; private FrameLayout recordPanel; private LinearLayout slideText; + private RecordDot recordDot; private SizeNotifierFrameLayout sizeNotifierLayout; private LinearLayout attachButton; private ImageView botButton; @@ -82,6 +90,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private PopupWindow botKeyboardPopup; private BotKeyboardView botKeyboardView; private ImageView asAdminButton; + private RecordCircle recordCircle; private int currentPopupContentType = -1; @@ -99,7 +108,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private PowerManager.WakeLock mWakeLock; private AnimatorSetProxy runningAnimation; private AnimatorSetProxy runningAnimation2; - private ObjectAnimatorProxy runningAnimationAudio; + private AnimatorSetProxy runningAnimationAudio; private int runningAnimationType; private int audioInterfaceState; @@ -149,6 +158,124 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } }; + private class RecordDot extends View { + + private Drawable dotDrawable; + private float alpha; + private long lastUpdateTime; + private boolean isIncr; + + public RecordDot(Context context) { + super(context); + + dotDrawable = getResources().getDrawable(R.drawable.rec); + } + + public void resetAlpha() { + alpha = 1.0f; + lastUpdateTime = System.currentTimeMillis(); + isIncr = false; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + dotDrawable.setBounds(0, 0, AndroidUtilities.dp(11), AndroidUtilities.dp(11)); + dotDrawable.setAlpha(185 + (int) (70 * alpha)); + long dt = (System.currentTimeMillis() - lastUpdateTime); + if (!isIncr) { + alpha -= dt / 200.0f; + if (alpha <= 0) { + alpha = 0; + isIncr = true; + } + } else { + alpha += dt / 200.0f; + if (alpha >= 1) { + alpha = 1; + isIncr = false; + } + } + lastUpdateTime = System.currentTimeMillis(); + dotDrawable.draw(canvas); + invalidate(); + } + } + + private class RecordCircle extends View { + + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint paintRecord = new Paint(Paint.ANTI_ALIAS_FLAG); + private Drawable micDrawable; + private float scale; + private float amplitude; + private float animateToAmplitude; + private float animateAmplitudeDiff; + private long lastUpdateTime; + + public RecordCircle(Context context) { + super(context); + paint.setColor(0xff5795cc); + paintRecord.setColor(0x0d000000); + micDrawable = getResources().getDrawable(R.drawable.mic_pressed); + } + + public void setAmplitude(double value) { + animateToAmplitude = (float) Math.min(100, value) / 100.0f; + animateAmplitudeDiff = (animateToAmplitude - amplitude) / 150.0f; + lastUpdateTime = System.currentTimeMillis(); + invalidate(); + } + + public float getScale() { + return scale; + } + + public void setScale(float value) { + scale = value; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + int cx = getMeasuredWidth() / 2; + int cy = getMeasuredHeight() / 2; + float sc; + float alpha; + if (scale <= 0.5f) { + alpha = sc = scale / 0.5f; + } else if (scale <= 0.75f) { + sc = 1.0f - (scale - 0.5f) / 0.25f * 0.1f; + alpha = 1; + } else { + sc = 0.9f + (scale - 0.75f) / 0.25f * 0.1f; + alpha = 1; + } + long dt = System.currentTimeMillis() - lastUpdateTime; + if (animateToAmplitude != amplitude) { + amplitude += animateAmplitudeDiff * dt; + if (animateAmplitudeDiff > 0) { + if (amplitude > animateToAmplitude) { + amplitude = animateToAmplitude; + } + } else { + if (amplitude < animateToAmplitude) { + amplitude = animateToAmplitude; + } + } + invalidate(); + } + lastUpdateTime = System.currentTimeMillis(); + if (amplitude != 0) { + canvas.drawCircle(getMeasuredWidth() / 2.0f, getMeasuredHeight() / 2.0f, (AndroidUtilities.dp(42) + AndroidUtilities.dp(20) * amplitude) * scale, paintRecord); + } + canvas.drawCircle(getMeasuredWidth() / 2.0f, getMeasuredHeight() / 2.0f, AndroidUtilities.dp(42) * sc, paint); + micDrawable.setBounds(cx - micDrawable.getIntrinsicWidth() / 2, cy - micDrawable.getIntrinsicHeight() / 2, cx + micDrawable.getIntrinsicWidth() / 2, cy + micDrawable.getIntrinsicHeight() / 2); + micDrawable.setAlpha((int) (255 * alpha)); + micDrawable.draw(canvas); + } + } + public ChatActivityEnterView(Activity context, SizeNotifierFrameLayout parent, BaseFragment fragment, boolean isChat) { super(context); setBackgroundResource(R.drawable.compose_panel); @@ -398,9 +525,8 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat linearLayout.setBackgroundColor(0xffffffff); recordPanel.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); - imageView = new ImageView(context); - imageView.setImageResource(R.drawable.rec); - linearLayout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 1, 0, 0)); + recordDot = new RecordDot(context); + linearLayout.addView(recordDot, LayoutHelper.createLinear(11, 11, Gravity.CENTER_VERTICAL, 0, 1, 0, 0)); recordTimeText = new TextView(context); recordTimeText.setText("00:00"); @@ -413,7 +539,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat audioSendButton = new ImageView(context); audioSendButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); - audioSendButton.setImageResource(R.drawable.mic_button_states); + audioSendButton.setImageResource(R.drawable.mic); audioSendButton.setBackgroundColor(0xffffffff); audioSendButton.setSoundEffectsEnabled(false); audioSendButton.setPadding(0, 0, AndroidUtilities.dp(4), 0); @@ -423,6 +549,13 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat public boolean onTouch(View view, MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { if (parentFragment != null) { + if (Build.VERSION.SDK_INT >= 23) { + if (parentActivity.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + parentActivity.requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 3); + return false; + } + } + String action; TLRPC.Chat currentChat; if ((int) dialog_id < 0) { @@ -460,6 +593,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) slideText.getLayoutParams(); if (startedDraggingX != -1) { float dist = (x - startedDraggingX); + ViewProxy.setTranslationX(recordCircle, dist); params.leftMargin = AndroidUtilities.dp(30) + (int) dist; slideText.setLayoutParams(params); float alpha = 1.0f + dist / distCanMove; @@ -483,6 +617,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } if (params.leftMargin > AndroidUtilities.dp(30)) { params.leftMargin = AndroidUtilities.dp(30); + ViewProxy.setTranslationX(recordCircle, 0); slideText.setLayoutParams(params); ViewProxy.setAlpha(slideText, 1); startedDraggingX = -1; @@ -493,6 +628,10 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } }); + recordCircle = new RecordCircle(context); + recordCircle.setVisibility(GONE); + sizeNotifierLayout.addView(recordCircle, LayoutHelper.createFrame(124, 124, Gravity.BOTTOM | Gravity.RIGHT, 0, 0, -36, -38)); + sendButton = new ImageView(context); sendButton.setVisibility(View.INVISIBLE); sendButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); @@ -572,7 +711,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat currentTopViewAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (animation == currentTopViewAnimation) { + if (currentTopViewAnimation != null && currentTopViewAnimation.equals(animation)) { setTopViewAnimation(1.0f); if (!forceShowSendButton) { openKeyboard(); @@ -617,7 +756,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat currentTopViewAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (animation == currentTopViewAnimation) { + if (currentTopViewAnimation != null && currentTopViewAnimation.equals(animation)) { topView.setVisibility(GONE); setTopViewAnimation(0.0f); currentTopViewAnimation = null; @@ -877,7 +1016,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat runningAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (runningAnimation.equals(animation)) { + if (runningAnimation != null && runningAnimation.equals(animation)) { sendButton.setVisibility(View.VISIBLE); audioSendButton.setVisibility(View.GONE); audioSendButton.clearAnimation(); @@ -952,7 +1091,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat runningAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (runningAnimation.equals(animation)) { + if (runningAnimation != null && runningAnimation.equals(animation)) { sendButton.setVisibility(View.GONE); sendButton.clearAnimation(); audioSendButton.setVisibility(View.VISIBLE); @@ -1023,8 +1162,11 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } AndroidUtilities.lockOrientation(parentActivity); - recordPanel.setVisibility(View.VISIBLE); + recordPanel.setVisibility(VISIBLE); + recordCircle.setVisibility(VISIBLE); + recordCircle.setAmplitude(0); recordTimeText.setText("00:00"); + recordDot.resetAlpha(); lastTimeString = null; FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) slideText.getLayoutParams(); @@ -1032,19 +1174,25 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat slideText.setLayoutParams(params); ViewProxy.setAlpha(slideText, 1); ViewProxy.setX(recordPanel, AndroidUtilities.displaySize.x); + ViewProxy.setTranslationX(recordCircle, 0); if (runningAnimationAudio != null) { runningAnimationAudio.cancel(); } - runningAnimationAudio = ObjectAnimatorProxy.ofFloatProxy(recordPanel, "translationX", 0).setDuration(300); + runningAnimationAudio = new AnimatorSetProxy(); + runningAnimationAudio.playTogether(ObjectAnimatorProxy.ofFloat(recordPanel, "translationX", 0), + ObjectAnimatorProxy.ofFloat(recordCircle, "scale", 1), + ObjectAnimatorProxy.ofFloat(audioSendButton, "alpha", 0)); + runningAnimationAudio.setDuration(300); runningAnimationAudio.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animator) { if (runningAnimationAudio != null && runningAnimationAudio.equals(animator)) { ViewProxy.setX(recordPanel, 0); + runningAnimationAudio = null; } } }); - runningAnimationAudio.setInterpolator(new AccelerateDecelerateInterpolator()); + runningAnimationAudio.setInterpolator(new DecelerateInterpolator()); runningAnimationAudio.start(); } else { if (mWakeLock != null) { @@ -1064,7 +1212,11 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat if (runningAnimationAudio != null) { runningAnimationAudio.cancel(); } - runningAnimationAudio = ObjectAnimatorProxy.ofFloatProxy(recordPanel, "translationX", AndroidUtilities.displaySize.x).setDuration(300); + runningAnimationAudio = new AnimatorSetProxy(); + runningAnimationAudio.playTogether(ObjectAnimatorProxy.ofFloat(recordPanel, "translationX", AndroidUtilities.displaySize.x), + ObjectAnimatorProxy.ofFloat(recordCircle, "scale", 0.0f), + ObjectAnimatorProxy.ofFloat(audioSendButton, "alpha", 1.0f)); + runningAnimationAudio.setDuration(300); runningAnimationAudio.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animator) { @@ -1074,10 +1226,12 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat slideText.setLayoutParams(params); ViewProxy.setAlpha(slideText, 1); recordPanel.setVisibility(View.GONE); + recordCircle.setVisibility(View.GONE); + runningAnimationAudio = null; } } }); - runningAnimationAudio.setInterpolator(new AccelerateDecelerateInterpolator()); + runningAnimationAudio.setInterpolator(new AccelerateInterpolator()); runningAnimationAudio.start(); } } @@ -1086,22 +1240,28 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat this.delegate = delegate; } - public void setCommand(MessageObject messageObject, String command) { + public void setCommand(MessageObject messageObject, String command, boolean longPress) { if (command == null || getVisibility() != VISIBLE) { return; } - TLRPC.User user = messageObject != null && (int) dialog_id < 0 ? MessagesController.getInstance().getUser(messageObject.messageOwner.from_id) : null; - if (botCount != 1 && user != null && (user.flags & TLRPC.USER_FLAG_BOT) != 0 && !command.contains("@")) { - SendMessagesHelper.getInstance().sendMessage(String.format(Locale.US, "%s@%s", command, user.username), dialog_id, null, null, false, asAdmin()); + if (longPress) { + String text = messageEditText.getText().toString(); + text = command + " " + text.replaceFirst("^/[a-zA-Z@\\d_]{1,255}(\\s|$)", ""); + ignoreTextChange = true; + messageEditText.setText(text); + messageEditText.setSelection(messageEditText.getText().length()); + ignoreTextChange = false; + if (!keyboardVisible && currentPopupContentType == -1) { + openKeyboard(); + } } else { - SendMessagesHelper.getInstance().sendMessage(command, dialog_id, null, null, false, asAdmin()); + TLRPC.User user = messageObject != null && (int) dialog_id < 0 ? MessagesController.getInstance().getUser(messageObject.messageOwner.from_id) : null; + if (botCount != 1 && user != null && (user.flags & TLRPC.USER_FLAG_BOT) != 0 && !command.contains("@")) { + SendMessagesHelper.getInstance().sendMessage(String.format(Locale.US, "%s@%s", command, user.username), dialog_id, null, null, false, asAdmin()); + } else { + SendMessagesHelper.getInstance().sendMessage(command, dialog_id, null, null, false, asAdmin()); + } } - /*String text = messageEditText.getText().toString(); - text = command + " " + text.replaceFirst("^/[a-zA-Z@\\d_]{1,255}(\\s|$)", ""); - ignoreTextChange = true; - messageEditText.setText(text); - messageEditText.setSelection(messageEditText.getText().length()); - ignoreTextChange = false;*/ } public void setFieldText(String text) { @@ -1117,6 +1277,13 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } } + public void setSelection(int start) { + if (messageEditText == null) { + return; + } + messageEditText.setSelection(start, messageEditText.length()); + } + public int getCursorPosition() { if (messageEditText == null) { return 0; @@ -1283,6 +1450,10 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat return view == botKeyboardView || view == emojiView; } + public boolean isRecordCircle(View view) { + return view == recordCircle; + } + private void showPopup(int show, int contentType) { if (show == 1) { if (contentType == 0 && emojiView == null) { @@ -1307,7 +1478,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } try { innerTextChange = 2; - CharSequence localCharSequence = Emoji.replaceEmoji(symbol/* + "\uFE0F"*/, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); + CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); messageEditText.setText(messageEditText.getText().insert(i, localCharSequence)); int j = i + localCharSequence.length(); messageEditText.setSelection(j, j); @@ -1378,6 +1549,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat if (emojiButton != null) { emojiButton.setImageResource(R.drawable.ic_msg_panel_smiles); } + currentPopupContentType = -1; if (emojiView != null) { emojiView.setVisibility(GONE); } @@ -1522,6 +1694,9 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat recordTimeText.setText(str); } } + if (recordCircle != null) { + recordCircle.setAmplitude((Double) args[1]); + } } else if (id == NotificationCenter.closeChats) { if (messageEditText != null && messageEditText.isFocused()) { AndroidUtilities.hideKeyboard(messageEditText); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java index 763d7bd04..448b02c3c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -8,12 +8,15 @@ package org.telegram.ui.Components; +import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.content.Context; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; @@ -27,19 +30,23 @@ import android.widget.ImageView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.Adapters.PhotoAttachAdapter; import org.telegram.ui.Cells.PhotoAttachPhotoCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.PhotoViewer; import java.util.ArrayList; import java.util.HashMap; -public class ChatAttachView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { +public class ChatAttachView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate, PhotoViewer.PhotoViewerProvider { public interface ChatAttachViewDelegate { void didPressedButton(int button); @@ -132,14 +139,30 @@ public class ChatAttachView extends FrameLayout implements NotificationCenter.No } }); attachPhotoRecyclerView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { + @SuppressWarnings("unchecked") @Override public void onItemClick(View view, int position) { - photoAttachAdapter.onItemClick((PhotoAttachPhotoCell) view); + if (baseFragment == null || baseFragment.getParentActivity() == null) { + return; + } + ArrayList arrayList = (ArrayList) MediaController.allPhotosAlbumEntry.photos; + if (position < 0 || position >= arrayList.size()) { + return; + } + PhotoViewer.getInstance().setParentActivity(baseFragment.getParentActivity()); + PhotoViewer.getInstance().openPhotoForSelect(arrayList, position, 0, ChatAttachView.this, baseFragment); + AndroidUtilities.hideKeyboard(baseFragment.getFragmentView().findFocus()); } }); views[9] = progressView = new EmptyTextProgressView(context); - progressView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos)); + if (Build.VERSION.SDK_INT >= 23 && getContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + progressView.setText(LocaleController.getString("PermissionStorage", R.string.PermissionStorage)); + progressView.setTextSize(16); + } else { + progressView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos)); + progressView.setTextSize(20); + } addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 80)); attachPhotoRecyclerView.setEmptyView(progressView); @@ -245,6 +268,14 @@ public class ChatAttachView extends FrameLayout implements NotificationCenter.No sendPhotosButton.imageView.setImageResource(R.drawable.attach_send2); sendPhotosButton.textView.setText(LocaleController.formatString("SendItems", R.string.SendItems, String.format("(%d)", count))); } + + if (Build.VERSION.SDK_INT >= 23 && getContext().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + progressView.setText(LocaleController.getString("PermissionStorage", R.string.PermissionStorage)); + progressView.setTextSize(16); + } else { + progressView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos)); + progressView.setTextSize(20); + } } public void setDelegate(ChatAttachViewDelegate chatAttachViewDelegate) { @@ -332,6 +363,14 @@ public class ChatAttachView extends FrameLayout implements NotificationCenter.No } public void init(ChatActivity parentFragment) { + if (MediaController.allPhotosAlbumEntry != null) { + for (int a = 0; a < Math.min(100, MediaController.allPhotosAlbumEntry.photos.size()); a++) { + MediaController.PhotoEntry photoEntry = MediaController.allPhotosAlbumEntry.photos.get(a); + photoEntry.caption = null; + photoEntry.imagePath = null; + photoEntry.thumbPath = null; + } + } attachPhotoLayoutManager.scrollToPositionWithOffset(0, 1000000); photoAttachAdapter.clearSelectedPhotos(); baseFragment = parentFragment; @@ -346,4 +385,142 @@ public class ChatAttachView extends FrameLayout implements NotificationCenter.No NotificationCenter.getInstance().removeObserver(this, NotificationCenter.albumsDidLoaded); baseFragment = null; } + + private PhotoAttachPhotoCell getCellForIndex(int index) { + int count = attachPhotoRecyclerView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = attachPhotoRecyclerView.getChildAt(a); + if (view instanceof PhotoAttachPhotoCell) { + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; + int num = (Integer) cell.getImageView().getTag(); + if (num < 0 || num >= MediaController.allPhotosAlbumEntry.photos.size()) { + continue; + } + if (num == index) { + return cell; + } + } + } + return null; + } + + @Override + public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { + PhotoAttachPhotoCell cell = getCellForIndex(index); + if (cell != null) { + int coords[] = new int[2]; + cell.getImageView().getLocationInWindow(coords); + PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); + object.viewX = coords[0]; + object.viewY = coords[1] - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); + object.parentView = attachPhotoRecyclerView; + object.imageReceiver = cell.getImageView().getImageReceiver(); + object.thumb = object.imageReceiver.getBitmap(); + object.scale = ViewProxy.getScaleX(cell.getImageView()); + object.clipBottomAddition = (Build.VERSION.SDK_INT >= 21 ? 0 : -AndroidUtilities.statusBarHeight); + cell.getCheckBox().setVisibility(View.GONE); + return object; + } + return null; + } + + @Override + public void updatePhotoAtIndex(int index) { + PhotoAttachPhotoCell cell = getCellForIndex(index); + if (cell != null) { + cell.getImageView().setOrientation(0, true); + MediaController.PhotoEntry photoEntry = MediaController.allPhotosAlbumEntry.photos.get(index); + if (photoEntry.thumbPath != null) { + cell.getImageView().setImage(photoEntry.thumbPath, null, cell.getContext().getResources().getDrawable(R.drawable.nophotos)); + } else if (photoEntry.path != null) { + cell.getImageView().setOrientation(photoEntry.orientation, true); + cell.getImageView().setImage("thumb://" + photoEntry.imageId + ":" + photoEntry.path, null, cell.getContext().getResources().getDrawable(R.drawable.nophotos)); + } else { + cell.getImageView().setImageResource(R.drawable.nophotos); + } + } + } + + @Override + public Bitmap getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { + PhotoAttachPhotoCell cell = getCellForIndex(index); + if (cell != null) { + return cell.getImageView().getImageReceiver().getBitmap(); + } + return null; + } + + @Override + public void willSwitchFromPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { + PhotoAttachPhotoCell cell = getCellForIndex(index); + if (cell != null) { + cell.getCheckBox().setVisibility(View.VISIBLE); + } + } + + @Override + public void willHidePhotoViewer() { + int count = attachPhotoRecyclerView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = attachPhotoRecyclerView.getChildAt(a); + if (view instanceof PhotoAttachPhotoCell) { + PhotoAttachPhotoCell cell = (PhotoAttachPhotoCell) view; + if (cell.getCheckBox().getVisibility() != VISIBLE) { + cell.getCheckBox().setVisibility(VISIBLE); + } + } + } + } + + @Override + public boolean isPhotoChecked(int index) { + return !(index < 0 || index >= MediaController.allPhotosAlbumEntry.photos.size()) && photoAttachAdapter.getSelectedPhotos().containsKey(MediaController.allPhotosAlbumEntry.photos.get(index).imageId); + } + + @Override + public void setPhotoChecked(int index) { + boolean add = true; + if (index < 0 || index >= MediaController.allPhotosAlbumEntry.photos.size()) { + return; + } + MediaController.PhotoEntry photoEntry = MediaController.allPhotosAlbumEntry.photos.get(index); + if (photoAttachAdapter.getSelectedPhotos().containsKey(photoEntry.imageId)) { + photoAttachAdapter.getSelectedPhotos().remove(photoEntry.imageId); + add = false; + } else { + photoAttachAdapter.getSelectedPhotos().put(photoEntry.imageId, photoEntry); + } + int count = attachPhotoRecyclerView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = attachPhotoRecyclerView.getChildAt(a); + int num = (Integer) view.getTag(); + if (num == index) { + ((PhotoAttachPhotoCell) view).setChecked(add, false); + break; + } + } + updatePhotosButton(); + } + + @Override + public boolean cancelButtonPressed() { + return false; + } + + @Override + public void sendButtonPressed(int index) { + if (photoAttachAdapter.getSelectedPhotos().isEmpty()) { + if (index < 0 || index >= MediaController.allPhotosAlbumEntry.photos.size()) { + return; + } + MediaController.PhotoEntry photoEntry = MediaController.allPhotosAlbumEntry.photos.get(index); + photoAttachAdapter.getSelectedPhotos().put(photoEntry.imageId, photoEntry); + } + delegate.didPressedButton(7); + } + + @Override + public int getSelectedCount() { + return photoAttachAdapter.getSelectedPhotos().size(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java index 6a0f06278..52af2a112 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChipSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChipSpan.java index c780bc7a6..c148376e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChipSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChipSpan.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java index 59ec72db5..a9ddcaacc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java deleted file mode 100644 index cabb49243..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 2.x.x. - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2015. - */ - -package org.telegram.ui.Components; - -import android.content.Context; -import android.text.TextUtils; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.MediaController; -import org.telegram.messenger.MessageObject; -import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.R; - -public class DrawerPlayerView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { - - private ImageView playButton; - private TextView titleTextView; - private ListView parentListView; - private MessageObject lastMessageObject; - - public DrawerPlayerView(Context context, ListView listView) { - super(context); - parentListView = listView; - - View shadow = new View(context); - shadow.setBackgroundResource(R.drawable.header_shadow_reverse); - addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3)); - - FrameLayout frameLayout = new FrameLayout(context); - frameLayout.setBackgroundColor(0xffffffff); - addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 3, 0, 0)); - - playButton = new ImageView(context); - playButton.setScaleType(ImageView.ScaleType.CENTER); - addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.TOP | Gravity.LEFT, 2, 3, 0, 0)); - playButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (MediaController.getInstance().isAudioPaused()) { - MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject()); - } else { - MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); - } - } - }); - - titleTextView = new TextView(context); - titleTextView.setTextColor(0xff15a5ed); - titleTextView.setMaxLines(1); - titleTextView.setLines(1); - titleTextView.setSingleLine(true); - titleTextView.setEllipsize(TextUtils.TruncateAt.END); - titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleTextView.setGravity(Gravity.CENTER_VERTICAL); - addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP, 72, 3, 8, 0)); - - checkPlayer(); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidStarted); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidStarted); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, AndroidUtilities.dp(51)); - } - - @Override - public void didReceivedNotification(int id, Object... args) { - if (id == NotificationCenter.audioDidStarted || id == NotificationCenter.audioPlayStateChanged || id == NotificationCenter.audioDidReset) { - checkPlayer(); - } - } - - private void checkPlayer() { - MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); - if (messageObject == null || !messageObject.isMusic()) { - lastMessageObject = null; - if (getVisibility() != GONE) { - setVisibility(GONE); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) parentListView.getLayoutParams(); - layoutParams.bottomMargin = 0; - parentListView.setLayoutParams(layoutParams); - } - } else { - if (getVisibility() != VISIBLE) { - setVisibility(VISIBLE); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) parentListView.getLayoutParams(); - layoutParams.bottomMargin = AndroidUtilities.dp(48); - parentListView.setLayoutParams(layoutParams); - } - if (MediaController.getInstance().isAudioPaused()) { - playButton.setImageResource(R.drawable.menu_play); - } else { - playButton.setImageResource(R.drawable.menu_pause); - } - if (lastMessageObject != messageObject) { - lastMessageObject = messageObject; - titleTextView.setText(String.format("%s - %s", messageObject.getMusicAuthor(), messageObject.getMusicTitle())); - } - } - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 0828ca98d..dc588c733 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; @@ -12,15 +12,22 @@ import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.WindowManager; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.BaseAdapter; @@ -28,11 +35,13 @@ import android.widget.FrameLayout; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.PopupWindow; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.Emoji; +import org.telegram.messenger.EmojiData; import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.query.StickersQuery; @@ -43,6 +52,7 @@ import org.telegram.ui.Cells.EmptyCell; import org.telegram.ui.Cells.StickerEmojiCell; import org.telegram.ui.StickerPreviewViewer; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -56,9 +66,415 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific void onStickerSelected(TLRPC.Document sticker); } + private static final Field superListenerField; + static { + Field f = null; + try { + f = PopupWindow.class.getDeclaredField("mOnScrollChangedListener"); + f.setAccessible(true); + } catch (NoSuchFieldException e) { + /* ignored */ + } + superListenerField = f; + } + private static final ViewTreeObserver.OnScrollChangedListener NOP = new ViewTreeObserver.OnScrollChangedListener() { + @Override + public void onScrollChanged() { + /* do nothing */ + } + }; + + private class ImageViewEmoji extends ImageView { + + private boolean touched; + private float lastX; + private float lastY; + private float touchedX; + private float touchedY; + + public ImageViewEmoji(Context context) { + super(context); + + setOnClickListener(new View.OnClickListener() { + public void onClick(View view) { + sendEmoji(null); + } + }); + setOnLongClickListener(new OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + String code = (String) view.getTag(); + if (EmojiData.emojiColoredMap.containsKey(code)) { + touched = true; + touchedX = lastX; + touchedY = lastY; + + String color = emojiColor.get(code); + if (color != null) { + switch (color) { + case "\uD83C\uDFFB": + pickerView.setSelection(1); + break; + case "\uD83C\uDFFC": + pickerView.setSelection(2); + break; + case "\uD83C\uDFFD": + pickerView.setSelection(3); + break; + case "\uD83C\uDFFE": + pickerView.setSelection(4); + break; + case "\uD83C\uDFFF": + pickerView.setSelection(5); + break; + } + } else { + pickerView.setSelection(0); + } + view.getLocationOnScreen(location); + int x = emojiSize * pickerView.getSelection() + AndroidUtilities.dp(4 * pickerView.getSelection() - (AndroidUtilities.isTablet() ? 5 : 1)); + if (location[0] - x < AndroidUtilities.dp(5)) { + x += (location[0] - x) - AndroidUtilities.dp(5); + } else if (location[0] - x + popupWidth > AndroidUtilities.displaySize.x - AndroidUtilities.dp(5)) { + x += (location[0] - x + popupWidth) - (AndroidUtilities.displaySize.x - AndroidUtilities.dp(5)); + } + int xOffset = -x; + int yOffset = view.getTop() < 0 ? view.getTop() : 0; + + pickerView.setEmoji(code, AndroidUtilities.dp(AndroidUtilities.isTablet() ? 30 : 22) - xOffset + (int) AndroidUtilities.dpf2(0.5f)); + + pickerViewPopup.setFocusable(true); + pickerViewPopup.showAsDropDown(view, xOffset, -view.getMeasuredHeight() - popupHeight + (view.getMeasuredHeight() - emojiSize) / 2 - yOffset); + view.getParent().requestDisallowInterceptTouchEvent(true); + return true; + } + return false; + } + }); + setBackgroundResource(R.drawable.list_selector); + setScaleType(ImageView.ScaleType.CENTER); + } + + private void sendEmoji(String override) { + String code = override != null ? override : (String) getTag(); + if (override == null) { + if (pager.getCurrentItem() != 0) { + String color = emojiColor.get(code); + if (color != null) { + code += color; + } + } + Integer count = emojiUseHistory.get(code); + if (count == null) { + count = 0; + } + if (count == 0 && emojiUseHistory.size() > 50) { + for (int a = recentEmoji.size() - 1; a >= 0; a--) { + String emoji = recentEmoji.get(a); + emojiUseHistory.remove(emoji); + recentEmoji.remove(a); + if (emojiUseHistory.size() <= 50) { + break; + } + } + } + emojiUseHistory.put(code, ++count); + if (pager.getCurrentItem() != 0) { + sortEmoji(); + } + saveRecentEmoji(); + adapters.get(0).notifyDataSetChanged(); + if (listener != null) { + listener.onEmojiSelected(Emoji.fixEmoji(code)); + } + } else { + if (listener != null) { + listener.onEmojiSelected(Emoji.fixEmoji(override)); + } + } + + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(View.MeasureSpec.getSize(widthMeasureSpec), View.MeasureSpec.getSize(widthMeasureSpec)); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (touched) { + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + if (pickerViewPopup != null && pickerViewPopup.isShowing()) { + pickerViewPopup.dismiss(); + + String color = null; + switch (pickerView.getSelection()) { + case 1: + color = "\uD83C\uDFFB"; + break; + case 2: + color = "\uD83C\uDFFC"; + break; + case 3: + color = "\uD83C\uDFFD"; + break; + case 4: + color = "\uD83C\uDFFE"; + break; + case 5: + color = "\uD83C\uDFFF"; + break; + } + String code = (String) getTag(); + if (pager.getCurrentItem() != 0) { + if (color != null) { + emojiColor.put(code, color); + code += color; + } else { + emojiColor.remove(code); + } + setImageDrawable(Emoji.getEmojiBigDrawable(code)); + sendEmoji(null); + saveEmojiColors(); + } else { + sendEmoji(code + (color != null ? color : "")); + } + } + touched = false; + touchedX = -10000; + touchedY = -10000; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + boolean ignore = false; + if (touchedX != -10000) { + if (Math.abs(touchedX - event.getX()) > AndroidUtilities.getPixelsInCM(0.2f, true) || Math.abs(touchedY - event.getY()) > AndroidUtilities.getPixelsInCM(0.2f, false)) { + touchedX = -10000; + touchedY = -10000; + } else { + ignore = true; + } + } + if (!ignore) { + getLocationOnScreen(location); + float x = location[0] + event.getX(); + pickerView.getLocationOnScreen(location); + x -= location[0] + AndroidUtilities.dp(3); + int position = (int) (x / (emojiSize + AndroidUtilities.dp(4))); + if (position < 0) { + position = 0; + } else if (position > 5) { + position = 5; + } + pickerView.setSelection(position); + } + } + } + lastX = event.getX(); + lastY = event.getY(); + return super.onTouchEvent(event); + } + } + + private class EmojiPopupWindow extends PopupWindow { + + private ViewTreeObserver.OnScrollChangedListener mSuperScrollListener; + private ViewTreeObserver mViewTreeObserver; + + public EmojiPopupWindow() { + super(); + init(); + } + + public EmojiPopupWindow(Context context) { + super(context); + init(); + } + + public EmojiPopupWindow(int width, int height) { + super(width, height); + init(); + } + + public EmojiPopupWindow(View contentView) { + super(contentView); + init(); + } + + public EmojiPopupWindow(View contentView, int width, int height, boolean focusable) { + super(contentView, width, height, focusable); + init(); + } + + public EmojiPopupWindow(View contentView, int width, int height) { + super(contentView, width, height); + init(); + } + + private void init() { + if (superListenerField != null) { + try { + mSuperScrollListener = (ViewTreeObserver.OnScrollChangedListener) superListenerField.get(this); + superListenerField.set(this, NOP); + } catch (Exception e) { + mSuperScrollListener = null; + } + } + } + + private void unregisterListener() { + if (mSuperScrollListener != null && mViewTreeObserver != null) { + if (mViewTreeObserver.isAlive()) { + mViewTreeObserver.removeOnScrollChangedListener(mSuperScrollListener); + } + mViewTreeObserver = null; + } + } + + private void registerListener(View anchor) { + if (mSuperScrollListener != null) { + ViewTreeObserver vto = (anchor.getWindowToken() != null) ? anchor.getViewTreeObserver() : null; + if (vto != mViewTreeObserver) { + if (mViewTreeObserver != null && mViewTreeObserver.isAlive()) { + mViewTreeObserver.removeOnScrollChangedListener(mSuperScrollListener); + } + if ((mViewTreeObserver = vto) != null) { + vto.addOnScrollChangedListener(mSuperScrollListener); + } + } + } + } + + @Override + public void showAsDropDown(View anchor, int xoff, int yoff) { + try { + super.showAsDropDown(anchor, xoff, yoff); + registerListener(anchor); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + + @Override + public void update(View anchor, int xoff, int yoff, int width, int height) { + super.update(anchor, xoff, yoff, width, height); + registerListener(anchor); + } + + @Override + public void update(View anchor, int width, int height) { + super.update(anchor, width, height); + registerListener(anchor); + } + + @Override + public void showAtLocation(View parent, int gravity, int x, int y) { + super.showAtLocation(parent, gravity, x, y); + unregisterListener(); + } + + @Override + public void dismiss() { + setFocusable(false); + try { + super.dismiss(); + } catch (Exception e) { + //don't promt + } + unregisterListener(); + } + } + + private class EmojiColorPickerView extends View { + + private Drawable backgroundDrawable; + private Drawable arrowDrawable; + private String currentEmoji; + private int arrowX; + private int selection; + private Paint rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private RectF rect = new RectF(); + + public void setEmoji(String emoji, int arrowPosition) { + currentEmoji = emoji; + arrowX = arrowPosition; + rectPaint.setColor(0x2f000000); + invalidate(); + } + + public String getEmoji() { + return currentEmoji; + } + + public void setSelection(int position) { + if (selection == position) { + return; + } + selection = position; + invalidate(); + } + + public int getSelection() { + return selection; + } + + public EmojiColorPickerView(Context context) { + super(context); + + backgroundDrawable = getResources().getDrawable(R.drawable.stickers_back_all); + arrowDrawable = getResources().getDrawable(R.drawable.stickers_back_arrow); + } + + @Override + protected void onDraw(Canvas canvas) { + backgroundDrawable.setBounds(0, 0, getMeasuredWidth(), AndroidUtilities.dp(AndroidUtilities.isTablet() ? 60 : 52)); + backgroundDrawable.draw(canvas); + + arrowDrawable.setBounds(arrowX - AndroidUtilities.dp(9), AndroidUtilities.dp(AndroidUtilities.isTablet() ? 55.5f : 47.5f), arrowX + AndroidUtilities.dp(9), AndroidUtilities.dp((AndroidUtilities.isTablet() ? 55.5f : 47.5f) + 8)); + arrowDrawable.draw(canvas); + + if (currentEmoji != null) { + String code; + for (int a = 0; a < 6; a++) { + int x = emojiSize * a + AndroidUtilities.dp(5 + 4 * a); + int y = AndroidUtilities.dp(9); + if (selection == a) { + rect.set(x, y - (int) AndroidUtilities.dpf2(3.5f), x + emojiSize, y + emojiSize + AndroidUtilities.dp(3)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), rectPaint); + } + code = currentEmoji; + if (a != 0) { + code += "\uD83C"; + switch (a) { + case 1: + code += "\uDFFB"; + break; + case 2: + code += "\uDFFC"; + break; + case 3: + code += "\uDFFD"; + break; + case 4: + code += "\uDFFE"; + break; + case 5: + code += "\uDFFF"; + break; + } + } + Drawable drawable = Emoji.getEmojiBigDrawable(code); + if (drawable != null) { + drawable.setBounds(x, y, x + emojiSize, y + emojiSize); + drawable.draw(canvas); + } + } + } + } + } + private ArrayList adapters = new ArrayList<>(); - private HashMap emojiUseHistory = new HashMap<>(); - private ArrayList recentEmoji = new ArrayList<>(); + private HashMap emojiUseHistory = new HashMap<>(); + private static HashMap emojiColor = new HashMap<>(); + private ArrayList recentEmoji = new ArrayList<>(); private HashMap stickersUseHistory = new HashMap<>(); private ArrayList recentStickers = new ArrayList<>(); private HashMap stickerSetsUseCount = new HashMap<>(); @@ -86,6 +502,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private AdapterView.OnItemClickListener stickersOnItemClickListener; private Runnable openStickerPreviewRunnable; private StickerEmojiCell currentStickerPreviewCell; + private EmojiColorPickerView pickerView; + private EmojiPopupWindow pickerViewPopup; + private int popupWidth; + private int popupHeight; + private int emojiSize; + private int location[] = new int[2]; private int startX; private int startY; @@ -102,7 +524,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific showStickers = needStickers; - for (int i = 0; i < Emoji.data.length + 1; i++) { + for (int i = 0; i < EmojiData.dataColored.length + 1; i++) { GridView gridView = new GridView(context); if (AndroidUtilities.isTablet()) { gridView.setColumnWidth(AndroidUtilities.dp(60)); @@ -508,11 +930,26 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific addView(pager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 48, 0, 0)); - loadRecents(); + emojiSize = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 40 : 32); + pickerView = new EmojiColorPickerView(context); + pickerViewPopup = new EmojiPopupWindow(pickerView, popupWidth = AndroidUtilities.dp((AndroidUtilities.isTablet() ? 40 : 32) * 6 + 10 + 4 * 5), popupHeight = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 64 : 56)); + pickerViewPopup.setOutsideTouchable(true); + pickerViewPopup.setClippingEnabled(true); + pickerViewPopup.setInputMethodMode(EmojiPopupWindow.INPUT_METHOD_NOT_NEEDED); + pickerViewPopup.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); + pickerViewPopup.getContentView().setFocusableInTouchMode(true); + pickerViewPopup.getContentView().setOnKeyListener(new OnKeyListener() { + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0 && event.getAction() == KeyEvent.ACTION_UP && pickerViewPopup != null && pickerViewPopup.isShowing()) { + pickerViewPopup.dismiss(); + return true; + } + return false; + } + }); - if (Emoji.data[0] == null || Emoji.data[0].length == 0) { - pager.setCurrentItem(1); - } + loadRecents(); } private void onPageScrolled(int position, int width, int positionOffsetPixels) { @@ -581,7 +1018,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private void saveRecentEmoji() { SharedPreferences preferences = getContext().getSharedPreferences("emoji", Activity.MODE_PRIVATE); StringBuilder stringBuilder = new StringBuilder(); - for (HashMap.Entry entry : emojiUseHistory.entrySet()) { + for (HashMap.Entry entry : emojiUseHistory.entrySet()) { if (stringBuilder.length() != 0) { stringBuilder.append(","); } @@ -589,7 +1026,21 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific stringBuilder.append("="); stringBuilder.append(entry.getValue()); } - preferences.edit().putString("emojis", stringBuilder.toString()).commit(); + preferences.edit().putString("emojis2", stringBuilder.toString()).commit(); + } + + private void saveEmojiColors() { + SharedPreferences preferences = getContext().getSharedPreferences("emoji", Activity.MODE_PRIVATE); + StringBuilder stringBuilder = new StringBuilder(); + for (HashMap.Entry entry : emojiColor.entrySet()) { + if (stringBuilder.length() != 0) { + stringBuilder.append(","); + } + stringBuilder.append(entry.getKey()); + stringBuilder.append("="); + stringBuilder.append(entry.getValue()); + } + preferences.edit().putString("color", stringBuilder.toString()).commit(); } private void saveRecentStickers() { @@ -636,12 +1087,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private void sortEmoji() { recentEmoji.clear(); - for (HashMap.Entry entry : emojiUseHistory.entrySet()) { + for (HashMap.Entry entry : emojiUseHistory.entrySet()) { recentEmoji.add(entry.getKey()); } - Collections.sort(recentEmoji, new Comparator() { + Collections.sort(recentEmoji, new Comparator() { @Override - public int compare(Long lhs, Long rhs) { + public int compare(String lhs, String rhs) { Integer count1 = emojiUseHistory.get(lhs); Integer count2 = emojiUseHistory.get(rhs); if (count1 == null) { @@ -749,50 +1200,71 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific String str; SharedPreferences preferences = getContext().getSharedPreferences("emoji", Activity.MODE_PRIVATE); - if (preferences.contains("recents")) { - try { - str = preferences.getString("recents", ""); - if (str != null && str.length() > 0) { - String[] args = str.split(","); - for (int i = 0; i < args.length; i++) { - emojiUseHistory.put(Long.parseLong(args[i]), args.length - i); - } - } - } catch (Exception e) { - FileLog.e("tmessages", e); - } - sortEmoji(); - preferences.edit().remove("recents").commit(); - saveRecentEmoji(); - adapters.get(0).notifyDataSetChanged(); - } else { - try { - emojiUseHistory.clear(); + try { + emojiUseHistory.clear(); + if (preferences.contains("emojis")) { str = preferences.getString("emojis", ""); if (str != null && str.length() > 0) { String[] args = str.split(","); for (String arg : args) { String[] args2 = arg.split("="); - emojiUseHistory.put(Long.parseLong(args2[0]), Integer.parseInt(args2[1])); + long value = Long.parseLong(args2[0]); + String string = ""; + for (int a = 0; a < 4; a++) { + char ch = (char) value; + string = String.valueOf(ch) + string; + value >>= 16; + if (value == 0) { + break; + } + } + if (string.length() > 0) { + emojiUseHistory.put(string, Integer.parseInt(args2[1])); + } } } - if (emojiUseHistory.isEmpty()) { - long[] newRecent = new long[]{0x00000000D83DDE02L, 0x00000000D83DDE18L, 0x0000000000002764L, 0x00000000D83DDE0DL, 0x00000000D83DDE0AL, 0x00000000D83DDE01L, - 0x00000000D83DDC4DL, 0x000000000000263AL, 0x00000000D83DDE14L, 0x00000000D83DDE04L, 0x00000000D83DDE2DL, 0x00000000D83DDC8BL, - 0x00000000D83DDE12L, 0x00000000D83DDE33L, 0x00000000D83DDE1CL, 0x00000000D83DDE48L, 0x00000000D83DDE09L, 0x00000000D83DDE03L, - 0x00000000D83DDE22L, 0x00000000D83DDE1DL, 0x00000000D83DDE31L, 0x00000000D83DDE21L, 0x00000000D83DDE0FL, 0x00000000D83DDE1EL, - 0x00000000D83DDE05L, 0x00000000D83DDE1AL, 0x00000000D83DDE4AL, 0x00000000D83DDE0CL, 0x00000000D83DDE00L, 0x00000000D83DDE0BL, - 0x00000000D83DDE06L, 0x00000000D83DDC4CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L}; - for (int i = 0; i < newRecent.length; i++) { - emojiUseHistory.put(newRecent[i], newRecent.length - i); + preferences.edit().remove("emojis").commit(); + saveRecentEmoji(); + } else { + str = preferences.getString("emojis2", ""); + if (str != null && str.length() > 0) { + String[] args = str.split(","); + for (String arg : args) { + String[] args2 = arg.split("="); + emojiUseHistory.put(args2[0], Integer.parseInt(args2[1])); } - saveRecentEmoji(); } - sortEmoji(); - adapters.get(0).notifyDataSetChanged(); - } catch (Exception e) { - FileLog.e("tmessages", e); } + if (emojiUseHistory.isEmpty()) { + String[] newRecent = new String[]{ + "\uD83D\uDE02", "\uD83D\uDE18", "\u2764", "\uD83D\uDE0D", "\uD83D\uDE0A", "\uD83D\uDE01", + "\uD83D\uDC4D", "\u263A", "\uD83D\uDE14", "\uD83D\uDE04", "\uD83D\uDE2D", "\uD83D\uDC8B", + "\uD83D\uDE12", "\uD83D\uDE33", "\uD83D\uDE1C", "\uD83D\uDE48", "\uD83D\uDE09", "\uD83D\uDE03", + "\uD83D\uDE22", "\uD83D\uDE1D", "\uD83D\uDE31", "\uD83D\uDE21", "\uD83D\uDE0F", "\uD83D\uDE1E", + "\uD83D\uDE05", "\uD83D\uDE1A", "\uD83D\uDE4A", "\uD83D\uDE0C", "\uD83D\uDE00", "\uD83D\uDE0B", + "\uD83D\uDE06", "\uD83D\uDC4C", "\uD83D\uDE10", "\uD83D\uDE15"}; + for (int i = 0; i < newRecent.length; i++) { + emojiUseHistory.put(newRecent[i], newRecent.length - i); + } + saveRecentEmoji(); + } + sortEmoji(); + adapters.get(0).notifyDataSetChanged(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + + try { + str = preferences.getString("color", ""); + if (str != null && str.length() > 0) { + String[] args = str.split(","); + for (String arg : args) { + String[] args2 = arg.split("="); + emojiColor.put(args2[0], args2[1]); + } + } + } catch (Exception e) { + FileLog.e("tmessages", e); } if (showStickers) { @@ -913,6 +1385,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (stickersGridAdapter != null) { NotificationCenter.getInstance().removeObserver(this, NotificationCenter.stickersDidLoaded); } + if (pickerViewPopup != null && pickerViewPopup.isShowing()) { + pickerViewPopup.dismiss(); + } } @Override @@ -1080,7 +1555,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (emojiPage == -1) { return recentEmoji.size(); } - return Emoji.data[emojiPage].length; + return EmojiData.dataColored[emojiPage].length; } public Object getItem(int i) { @@ -1093,51 +1568,22 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public View getView(int i, View view, ViewGroup paramViewGroup) { - ImageView imageView = (ImageView)view; + ImageViewEmoji imageView = (ImageViewEmoji) view; if (imageView == null) { - imageView = new ImageView(getContext()) { - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(View.MeasureSpec.getSize(widthMeasureSpec), View.MeasureSpec.getSize(widthMeasureSpec)); - } - }; - imageView.setOnClickListener(new View.OnClickListener() { - public void onClick(View view) { - Long code = (Long) view.getTag(); - Integer count = emojiUseHistory.get(code); - if (count == null) { - count = 0; - } - if (count == 0 && emojiUseHistory.size() > 50) { - for (int a = recentEmoji.size() - 1; a >= 0; a--) { - Long emoji = recentEmoji.get(a); - emojiUseHistory.remove(emoji); - recentEmoji.remove(a); - if (emojiUseHistory.size() <= 50) { - break; - } - } - } - emojiUseHistory.put(code, ++count); - if (pager.getCurrentItem() != 0) { - sortEmoji(); - } - saveRecentEmoji(); - adapters.get(0).notifyDataSetChanged(); - if (listener != null) { - listener.onEmojiSelected(convert((Long)view.getTag())); - } - } - }); - imageView.setBackgroundResource(R.drawable.list_selector); - imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView = new ImageViewEmoji(getContext()); } - long code; + String code; + String coloredCode; if (emojiPage == -1) { - code = recentEmoji.get(i); + coloredCode = code = recentEmoji.get(i); } else { - code = Emoji.data[emojiPage][i]; + coloredCode = code = EmojiData.dataColored[emojiPage][i]; + String color = emojiColor.get(code); + if (color != null) { + coloredCode += color; + } } - imageView.setImageDrawable(Emoji.getEmojiBigDrawable(code)); + imageView.setImageDrawable(Emoji.getEmojiBigDrawable(coloredCode)); imageView.setTag(code); return imageView; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java index 371ace6ad..124ae677d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -66,6 +66,10 @@ public class EmptyTextProgressView extends FrameLayout { textView.setText(text); } + public void setTextSize(int size) { + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, size); + } + public void setShowAtCenter(boolean value) { showAtCenter = value; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java index 26323f5e9..1db8f6328 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java index cd169b3f9..26f791a4f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java index 394b6af40..0d0e70d8b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java index c1a65b6cc..700d58277 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterDrawable.java index 4dcbfaa0d..aef713cce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterDrawable.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -11,6 +11,7 @@ package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.Layout; @@ -93,7 +94,7 @@ public class LetterDrawable extends Drawable { @Override public int getOpacity() { - return 0; + return PixelFormat.TRANSPARENT; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java index fbac8a24a..60a26421c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java index 9b7db2ce6..26e73d7b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java index c597ccafe..8d2edc3a6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MapPlaceholderDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MapPlaceholderDrawable.java index c522342d4..7c4ba414f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MapPlaceholderDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MapPlaceholderDrawable.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java new file mode 100644 index 000000000..505f3cc76 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java @@ -0,0 +1,167 @@ +/* + * This is the source code of Telegram for Android v. 3.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.view.View; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationCompat.AnimatorListenerAdapterProxy; +import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; + +import java.util.ArrayList; +import java.util.Locale; + +public class NumberTextView extends View { + + private ArrayList letters = new ArrayList<>(); + private ArrayList oldLetters = new ArrayList<>(); + private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private ObjectAnimatorProxy animator; + private float progress = 0.0f; + private int currentNumber = 1; + + public NumberTextView(Context context) { + super(context); + } + + public void setProgress(float value) { + if (progress == value) { + return; + } + progress = value; + invalidate(); + } + + public float getProgress() { + return progress; + } + + public void setNumber(int number, boolean animated) { + if (currentNumber == number && animated) { + return; + } + if (animator != null) { + animator.cancel(); + animator = null; + } + oldLetters.clear(); + oldLetters.addAll(letters); + letters.clear(); + String oldText = String.format(Locale.US, "%d", currentNumber); + String text = String.format(Locale.US, "%d", number); + boolean forwardAnimation = number > currentNumber; + currentNumber = number; + progress = 0; + for (int a = 0; a < text.length(); a++) { + String ch = text.substring(a, a + 1); + String oldCh = !oldLetters.isEmpty() && a < oldText.length() ? oldText.substring(a, a + 1) : null; + if (oldCh != null && oldCh.equals(ch)) { + letters.add(oldLetters.get(a)); + oldLetters.set(a, null); + } else { + StaticLayout layout = new StaticLayout(ch, textPaint, (int) Math.ceil(textPaint.measureText(ch)), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + letters.add(layout); + } + } + if (animated && !oldLetters.isEmpty()) { + animator = ObjectAnimatorProxy.ofFloatProxy(this, "progress", forwardAnimation ? -1 : 1, 0); + animator.setDuration(150); + animator.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + animator = null; + oldLetters.clear(); + } + }); + animator.start(); + } + invalidate(); + } + + public void setTextSize(int size) { + textPaint.setTextSize(AndroidUtilities.dp(size)); + oldLetters.clear(); + letters.clear(); + setNumber(currentNumber, false); + } + + public void setTextColor(int value) { + textPaint.setColor(value); + invalidate(); + } + + public void setTypeface(Typeface typeface) { + textPaint.setTypeface(typeface); + oldLetters.clear(); + letters.clear(); + setNumber(currentNumber, false); + } + + @Override + protected void onDraw(Canvas canvas) { + if (letters.isEmpty()) { + return; + } + float height = letters.get(0).getHeight(); + canvas.save(); + canvas.translate(getPaddingLeft(), (getMeasuredHeight() - height) / 2); + int count = Math.max(letters.size(), oldLetters.size()); + for (int a = 0; a < count; a++) { + canvas.save(); + StaticLayout old = a < oldLetters.size() ? oldLetters.get(a) : null; + StaticLayout layout = a < letters.size() ? letters.get(a) : null; + if (progress > 0) { + if (old != null) { + textPaint.setAlpha((int) (255 * progress)); + canvas.save(); + canvas.translate(0, (progress - 1.0f) * height); + old.draw(canvas); + canvas.restore(); + if (layout != null) { + textPaint.setAlpha((int) (255 * (1.0f - progress))); + canvas.translate(0, progress * height); + } + } else { + textPaint.setAlpha(255); + } + } else if (progress < 0) { + if (old != null) { + textPaint.setAlpha((int) (255 * -progress)); + canvas.save(); + canvas.translate(0, (1.0f + progress) * height); + old.draw(canvas); + canvas.restore(); + } + if (layout != null) { + if (a == count - 1 || old != null) { + textPaint.setAlpha((int) (255 * (1.0f + progress))); + canvas.translate(0, progress * height); + } else { + textPaint.setAlpha(255); + } + } + } else if (layout != null) { + textPaint.setAlpha(255); + } + if (layout != null) { + layout.draw(canvas); + } + canvas.restore(); + canvas.translate(layout != null ? layout.getLineWidth(0) : old.getLineWidth(0) + AndroidUtilities.dp(1), 0); + } + canvas.restore(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java index 5daf22f1e..b633bd1bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java index 3fa6f3754..584c4db4c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -9,7 +9,9 @@ package org.telegram.ui.Components; import android.app.Activity; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.Canvas; @@ -19,6 +21,8 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Vibrator; +import android.support.v4.hardware.fingerprint.FingerprintManagerCompat; +import android.support.v4.os.CancellationSignal; import android.text.Editable; import android.text.InputFilter; import android.text.InputType; @@ -38,6 +42,7 @@ import android.view.inputmethod.EditorInfo; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; @@ -185,7 +190,7 @@ public class PasscodeView extends FrameLayout { currentAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (animation.equals(currentAnimation)) { + if (currentAnimation != null && currentAnimation.equals(animation)) { currentAnimation = null; } } @@ -219,7 +224,7 @@ public class PasscodeView extends FrameLayout { currentAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (animation.equals(currentAnimation)) { + if (currentAnimation != null && currentAnimation.equals(animation)) { currentAnimation = null; } } @@ -296,7 +301,7 @@ public class PasscodeView extends FrameLayout { currentAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (animation.equals(currentAnimation)) { + if (currentAnimation != null && currentAnimation.equals(animation)) { currentAnimation = null; } } @@ -304,7 +309,7 @@ public class PasscodeView extends FrameLayout { currentAnimation.start(); } - private void eraseAllCharacters(boolean animated) { + private void eraseAllCharacters(final boolean animated) { if (stringBuilder.length() == 0) { return; } @@ -342,7 +347,7 @@ public class PasscodeView extends FrameLayout { currentAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (animation.equals(currentAnimation)) { + if (currentAnimation != null && currentAnimation.equals(animation)) { currentAnimation = null; } } @@ -409,10 +414,19 @@ public class PasscodeView extends FrameLayout { private ImageView checkImage; private int keyboardHeight = 0; + private CancellationSignal cancellationSignal; + private ImageView fingerprintImageView; + private TextView fingerprintStatusTextView; + private boolean selfCancelled; + private AlertDialog fingerprintDialog; + private Rect rect = new Rect(); private PasscodeViewDelegate delegate; + private final static int id_fingerprint_textview = 1000; + private final static int id_fingerprint_imageview = 1001; + public PasscodeView(final Context context) { super(context); @@ -497,7 +511,7 @@ public class PasscodeView extends FrameLayout { @Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { if (i == EditorInfo.IME_ACTION_DONE) { - processDone(); + processDone(false); return true; } return false; @@ -517,7 +531,7 @@ public class PasscodeView extends FrameLayout { @Override public void afterTextChanged(Editable s) { if (passwordEditText.length() == 4 && UserConfig.passcodeType == 0) { - processDone(); + processDone(false); } } }); @@ -561,7 +575,7 @@ public class PasscodeView extends FrameLayout { checkImage.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - processDone(); + processDone(false); } }); @@ -707,7 +721,7 @@ public class PasscodeView extends FrameLayout { break; } if (passwordEditText2.lenght() == 4) { - processDone(); + processDone(false); } } }); @@ -728,22 +742,24 @@ public class PasscodeView extends FrameLayout { this.delegate = delegate; } - private void processDone() { - String password = ""; - if (UserConfig.passcodeType == 0) { - password = passwordEditText2.getString(); - } else if (UserConfig.passcodeType == 1) { - password = passwordEditText.getText().toString(); - } - if (password.length() == 0) { - onPasscodeError(); - return; - } - if (!UserConfig.checkPasscode(password)) { - passwordEditText.setText(""); - passwordEditText2.eraseAllCharacters(true); - onPasscodeError(); - return; + private void processDone(boolean fingerprint) { + if (!fingerprint) { + String password = ""; + if (UserConfig.passcodeType == 0) { + password = passwordEditText2.getString(); + } else if (UserConfig.passcodeType == 1) { + password = passwordEditText.getText().toString(); + } + if (password.length() == 0) { + onPasscodeError(); + return; + } + if (!UserConfig.checkPasscode(password)) { + passwordEditText.setText(""); + passwordEditText2.eraseAllCharacters(true); + onPasscodeError(); + return; + } } passwordEditText.clearFocus(); AndroidUtilities.hideKeyboard(passwordEditText); @@ -816,16 +832,148 @@ public class PasscodeView extends FrameLayout { } }, 200); } + checkFingerprint(); + } + + public void onPause() { + if (fingerprintDialog != null) { + try { + if (fingerprintDialog.isShowing()) { + fingerprintDialog.dismiss(); + } + fingerprintDialog = null; + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + try { + if (Build.VERSION.SDK_INT >= 23 && cancellationSignal != null) { + cancellationSignal.cancel(); + cancellationSignal = null; + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + + private void checkFingerprint() { + Activity parentActivity = (Activity) getContext(); + if (Build.VERSION.SDK_INT >= 23 && parentActivity != null && UserConfig.useFingerprint && !ApplicationLoader.mainInterfacePaused) { + try { + if (fingerprintDialog != null && fingerprintDialog.isShowing()) { + return; + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + try { + FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(ApplicationLoader.applicationContext); + if (fingerprintManager.isHardwareDetected() && fingerprintManager.hasEnrolledFingerprints()) { + RelativeLayout relativeLayout = new RelativeLayout(getContext()); + relativeLayout.setPadding(AndroidUtilities.dp(24), AndroidUtilities.dp(16), AndroidUtilities.dp(24), AndroidUtilities.dp(8)); + + TextView fingerprintTextView = new TextView(getContext()); + fingerprintTextView.setTextColor(0xff939393); + fingerprintTextView.setId(id_fingerprint_textview); + fingerprintTextView.setTextAppearance(android.R.style.TextAppearance_Material_Subhead); + fingerprintTextView.setText(LocaleController.getString("FingerprintInfo", R.string.FingerprintInfo)); + relativeLayout.addView(fingerprintTextView); + RelativeLayout.LayoutParams layoutParams = LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP); + layoutParams.addRule(RelativeLayout.ALIGN_PARENT_START); + fingerprintTextView.setLayoutParams(layoutParams); + + fingerprintImageView = new ImageView(getContext()); + fingerprintImageView.setImageResource(R.drawable.ic_fp_40px); + fingerprintImageView.setId(id_fingerprint_imageview); + relativeLayout.addView(fingerprintImageView, LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 20, 0, 0, RelativeLayout.ALIGN_PARENT_START, RelativeLayout.BELOW, id_fingerprint_textview)); + + fingerprintStatusTextView = new TextView(getContext()); + fingerprintStatusTextView.setGravity(Gravity.CENTER_VERTICAL); + fingerprintStatusTextView.setText(LocaleController.getString("FingerprintHelp", R.string.FingerprintHelp)); + fingerprintStatusTextView.setTextAppearance(android.R.style.TextAppearance_Material_Body1); + fingerprintStatusTextView.setTextColor(0x42000000); + relativeLayout.addView(fingerprintStatusTextView); + layoutParams = LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT); + layoutParams.setMarginStart(AndroidUtilities.dp(16)); + layoutParams.addRule(RelativeLayout.ALIGN_BOTTOM, id_fingerprint_imageview); + layoutParams.addRule(RelativeLayout.ALIGN_TOP, id_fingerprint_imageview); + layoutParams.addRule(RelativeLayout.END_OF, id_fingerprint_imageview); + fingerprintStatusTextView.setLayoutParams(layoutParams); + + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setView(relativeLayout); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setOnDismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + if (cancellationSignal != null) { + selfCancelled = true; + cancellationSignal.cancel(); + cancellationSignal = null; + } + } + }); + if (fingerprintDialog != null) { + try { + if (fingerprintDialog.isShowing()) { + fingerprintDialog.dismiss(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + fingerprintDialog = builder.show(); + + cancellationSignal = new CancellationSignal(); + selfCancelled = false; + fingerprintManager.authenticate(null, 0, cancellationSignal, new FingerprintManagerCompat.AuthenticationCallback() { + @Override + public void onAuthenticationError(int errMsgId, CharSequence errString) { + if (!selfCancelled) { + showFingerprintError(errString); + } + } + + @Override + public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { + showFingerprintError(helpString); + } + + @Override + public void onAuthenticationFailed() { + showFingerprintError(LocaleController.getString("FingerprintNotRecognized", R.string.FingerprintNotRecognized)); + } + + @Override + public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) { + try { + if (fingerprintDialog.isShowing()) { + fingerprintDialog.dismiss(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + fingerprintDialog = null; + processDone(true); + } + }, null); + } + } catch (Throwable e) { + //ignore + } + } } public void onShow() { + Activity parentActivity = (Activity) getContext(); if (UserConfig.passcodeType == 1) { if (passwordEditText != null) { passwordEditText.requestFocus(); AndroidUtilities.showKeyboard(passwordEditText); } } else { - Activity parentActivity = (Activity) getContext(); if (parentActivity != null) { View currentFocus = parentActivity.getCurrentFocus(); if (currentFocus != null) { @@ -834,6 +982,7 @@ public class PasscodeView extends FrameLayout { } } } + checkFingerprint(); if (getVisibility() == View.VISIBLE) { return; } @@ -891,6 +1040,17 @@ public class PasscodeView extends FrameLayout { }); } + private void showFingerprintError(CharSequence error) { + fingerprintImageView.setImageResource(R.drawable.ic_fingerprint_error); + fingerprintStatusTextView.setText(error); + fingerprintStatusTextView.setTextColor(0xfff4511e); + Vibrator v = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); + if (v != null) { + v.vibrate(200); + } + AndroidUtilities.shakeView(fingerprintStatusTextView, 2, 0); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java index 6ea153f3b..f61de0265 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -348,8 +348,7 @@ public class PhotoCropView extends FrameLayout { private Bitmap createBitmap(int x, int y, int w, int h) { Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); - Paint paint = new Paint(); - paint.setFilterBitmap(true); + Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG); Matrix matrix = new Matrix(); matrix.setTranslate(-bitmapToEdit.getWidth() / 2, -bitmapToEdit.getHeight() / 2); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java index 5258a6512..a6bf84430 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java index d93099272..137ddc70a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java index 3007ddb32..0c14662f9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java index a50558113..9dc34b602 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java index a05d17618..ba566fc12 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayerView.java new file mode 100644 index 000000000..3e3823037 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PlayerView.java @@ -0,0 +1,257 @@ +/* + * This is the source code of Telegram for Android v. 3.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.os.Build; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationCompat.AnimatorListenerAdapterProxy; +import org.telegram.messenger.AnimationCompat.AnimatorSetProxy; +import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; +import org.telegram.messenger.AnimationCompat.ViewProxy; +import org.telegram.messenger.MediaController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.AudioPlayerActivity; + +public class PlayerView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + + private ImageView playButton; + private TextView titleTextView; + private MessageObject lastMessageObject; + private AnimatorSetProxy animatorSet; + private float yPosition; + private BaseFragment fragment; + private float topPadding; + private boolean visible; + + public PlayerView(Context context, BaseFragment parentFragment) { + super(context); + + fragment = parentFragment; + visible = true; + ((ViewGroup) fragment.getFragmentView()).setClipToPadding(false); + + setTag(1); + FrameLayout frameLayout = new FrameLayout(context); + frameLayout.setBackgroundColor(0xffffffff); + addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); + + View shadow = new View(context); + shadow.setBackgroundResource(R.drawable.header_shadow); + addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.LEFT | Gravity.TOP, 0, 36, 0, 0)); + + playButton = new ImageView(context); + playButton.setScaleType(ImageView.ScaleType.CENTER); + addView(playButton, LayoutHelper.createFrame(36, 36, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 0)); + playButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (MediaController.getInstance().isAudioPaused()) { + MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject()); + } else { + MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); + } + } + }); + + titleTextView = new TextView(context); + titleTextView.setTextColor(0xff212121); + titleTextView.setMaxLines(1); + titleTextView.setLines(1); + titleTextView.setSingleLine(true); + titleTextView.setEllipsize(TextUtils.TruncateAt.END); + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + titleTextView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); + addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP, 35, 0, 36, 0)); + + ImageView closeButton = new ImageView(context); + closeButton.setImageResource(R.drawable.miniplayer_close); + closeButton.setScaleType(ImageView.ScaleType.CENTER); + addView(closeButton, LayoutHelper.createFrame(36, 36, Gravity.RIGHT | Gravity.TOP)); + closeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + MediaController.getInstance().cleanupPlayer(true, true); + } + }); + + setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (fragment != null) { + fragment.presentFragment(new AudioPlayerActivity()); + } + } + }); + } + + public float getTopPadding() { + return topPadding; + } + + public void setTopPadding(float value) { + topPadding = value; + if (fragment != null) { + View view = fragment.getFragmentView(); + if (view != null) { + view.setPadding(0, (int) topPadding, 0, 0); + } + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + topPadding = 0; + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidStarted); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidStarted); + checkPlayer(true); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, AndroidUtilities.dp(39)); + } + + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.audioDidStarted || id == NotificationCenter.audioPlayStateChanged || id == NotificationCenter.audioDidReset) { + checkPlayer(false); + } + } + + private void checkPlayer(boolean create) { + MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + View fragmentView = fragment.getFragmentView(); + if (!create && fragmentView != null) { + if (fragmentView.getParent() == null || ((View) fragmentView.getParent()).getVisibility() != VISIBLE) { + create = true; + } + } + if (messageObject == null || !messageObject.isMusic()) { + lastMessageObject = null; + if (visible) { + visible = false; + if (create && topPadding != 0) { + clearAnimation(); + setVisibility(GONE); + setTopPadding(0); + } else { + if (animatorSet != null) { + animatorSet.cancel(); + animatorSet = null; + } + animatorSet = new AnimatorSetProxy(); + animatorSet.playTogether(ObjectAnimatorProxy.ofFloat(this, "translationY", -AndroidUtilities.dp(36)), + ObjectAnimatorProxy.ofFloat(this, "topPadding", 0)); + animatorSet.setDuration(200); + animatorSet.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (animatorSet != null && animatorSet.equals(animation)) { + clearAnimation(); + setVisibility(GONE); + animatorSet = null; + } + } + }); + animatorSet.start(); + } + } + } else { + if (create && topPadding == 0) { + setTopPadding(AndroidUtilities.dp(36)); + ViewProxy.setTranslationY(this, 0); + yPosition = 0; + } + if (!visible) { + if (!create) { + if (animatorSet != null) { + animatorSet.cancel(); + animatorSet = null; + } + animatorSet = new AnimatorSetProxy(); + animatorSet.playTogether(ObjectAnimatorProxy.ofFloat(this, "translationY", -AndroidUtilities.dp(36), 0), + ObjectAnimatorProxy.ofFloat(this, "topPadding", AndroidUtilities.dp(36))); + animatorSet.setDuration(200); + animatorSet.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (animatorSet != null && animatorSet.equals(animation)) { + animatorSet = null; + } + } + }); + animatorSet.start(); + } + visible = true; + setVisibility(VISIBLE); + } + if (MediaController.getInstance().isAudioPaused()) { + playButton.setImageResource(R.drawable.miniplayer_play); + } else { + playButton.setImageResource(R.drawable.miniplayer_pause); + } + if (lastMessageObject != messageObject) { + lastMessageObject = messageObject; + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(String.format("%s - %s", messageObject.getMusicAuthor(), messageObject.getMusicTitle())); + TypefaceSpan span = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + stringBuilder.setSpan(span, 0, messageObject.getMusicAuthor().length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + titleTextView.setText(stringBuilder); + } + } + } + + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + yPosition = translationY; + invalidate(); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + int restoreToCount = 0; + if (Build.VERSION.SDK_INT >= 11) { + restoreToCount = canvas.save(); + if (yPosition < 0) { + canvas.clipRect(0, (int) -yPosition, child.getMeasuredWidth(), AndroidUtilities.dp(39)); + } + } + final boolean result = super.drawChild(canvas, child, drawingTime); + if (Build.VERSION.SDK_INT >= 11) { + canvas.restoreToCount(restoreToCount); + } + return result; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java index f22dde478..7e6fb2ba9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java index be0123392..71908c83a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java index 58b52ad5c..d5e7f3773 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java index f9dca6b1c..ae01fcf1e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadioButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadioButton.java index adb752df8..8a3a581b2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadioButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadioButton.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -9,8 +9,12 @@ package org.telegram.ui.Components; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.view.View; import org.telegram.messenger.AndroidUtilities; @@ -18,7 +22,10 @@ import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; public class RadioButton extends View { + private Bitmap bitmap; + private Canvas bitmapCanvas; private static Paint paint; + private static Paint eraser; private static Paint checkedPaint; private int checkedColor = 0xffd7e8f7; @@ -26,14 +33,11 @@ public class RadioButton extends View { private float progress; private ObjectAnimatorProxy checkAnimator; - private boolean isCheckAnimation = true; private boolean attachedToWindow; private boolean isChecked; private int size = AndroidUtilities.dp(16); - private final static float progressBounceDiff = 0.2f; - public RadioButton(Context context) { super(context); if (paint == null) { @@ -41,7 +45,13 @@ public class RadioButton extends View { paint.setStrokeWidth(AndroidUtilities.dp(2)); paint.setStyle(Paint.Style.STROKE); checkedPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + eraser = new Paint(Paint.ANTI_ALIAS_FLAG); + eraser.setColor(0); + eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } + + bitmap = Bitmap.createBitmap(AndroidUtilities.dp(size), AndroidUtilities.dp(size), Bitmap.Config.ARGB_4444); + bitmapCanvas = new Canvas(bitmap); } public void setProgress(float value) { @@ -57,6 +67,9 @@ public class RadioButton extends View { } public void setSize(int value) { + if (size == value) { + return; + } size = value; } @@ -72,7 +85,6 @@ public class RadioButton extends View { } private void animateToCheckedState(boolean newCheckedState) { - isCheckAnimation = newCheckedState; checkAnimator = ObjectAnimatorProxy.ofFloatProxy(this, "progress", newCheckedState ? 1 : 0); checkAnimator.setDuration(300); checkAnimator.start(); @@ -110,14 +122,41 @@ public class RadioButton extends View { @Override protected void onDraw(Canvas canvas) { - if (getVisibility() != VISIBLE) { - return; + if (bitmap == null || bitmap.getWidth() != getMeasuredWidth()) { + if (bitmap != null) { + bitmap.recycle(); + } + bitmap = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); + bitmapCanvas = new Canvas(bitmap); } - paint.setColor(isChecked ? checkedColor : color); - checkedPaint.setColor(checkedColor); - canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, size / 2 - AndroidUtilities.dp(1), paint); - if (isChecked) { - canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, size / 4, checkedPaint); + float circleProgress; + float innerRad; + if (progress <= 0.5f) { + paint.setColor(color); + checkedPaint.setColor(color); + circleProgress = progress / 0.5f; + } else { + circleProgress = 2.0f - progress / 0.5f; + int r1 = Color.red(color); + int rD = (int) ((Color.red(checkedColor) - r1) * (1.0f - circleProgress)); + int g1 = Color.green(color); + int gD = (int) ((Color.green(checkedColor) - g1) * (1.0f - circleProgress)); + int b1 = Color.blue(color); + int bD = (int) ((Color.blue(checkedColor) - b1) * (1.0f - circleProgress)); + int c = Color.rgb(r1 + rD, g1 + gD, b1 + bD); + paint.setColor(c); + checkedPaint.setColor(c); } + bitmap.eraseColor(0); + float rad = size / 2 - (1 + circleProgress) * AndroidUtilities.density; + bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, rad, paint); + if (progress <= 0.5f) { + bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, (rad - AndroidUtilities.dp(1)), checkedPaint); + bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, (rad - AndroidUtilities.dp(1)) * (1.0f - circleProgress), eraser); + } else { + bitmapCanvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, size / 4 + (rad - AndroidUtilities.dp(1) - size / 4) * circleProgress, checkedPaint); + } + + canvas.drawBitmap(bitmap, 0, 0, null); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java index a0ea38ac6..d8e9a39f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecordStatusDrawable.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java index 9dde354b9..ef88d877b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index dc0c32a29..7d29cd0cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -49,7 +49,7 @@ public class RecyclerListView extends RecyclerView { } public interface OnItemLongClickListener { - void onItemClick(View view, int position); + boolean onItemClick(View view, int position); } public interface OnInterceptTouchListener { @@ -97,8 +97,9 @@ public class RecyclerListView extends RecyclerView { @Override public void onLongPress(MotionEvent e) { if (currentChildView != null && onItemLongClickListener != null) { - currentChildView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - onItemLongClickListener.onItemClick(currentChildView, currentChildPosition); + if (onItemLongClickListener.onItemClick(currentChildView, currentChildPosition)) { + currentChildView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } } } }); @@ -164,7 +165,15 @@ public class RecyclerListView extends RecyclerView { @Override public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { - + if (selectChildRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(selectChildRunnable); + selectChildRunnable = null; + } + if (currentChildView != null) { + currentChildView.setPressed(false); + currentChildView = null; + } + interceptedByChild = false; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ResourceLoader.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ResourceLoader.java index 687a77d2c..49f470030 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ResourceLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ResourceLoader.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -125,6 +125,15 @@ public class ResourceLoader { geoInDrawable = context.getResources().getDrawable(R.drawable.location_b); geoOutDrawable = context.getResources().getDrawable(R.drawable.location_g); + + context.getResources().getDrawable(R.drawable.attach_camera_states); + context.getResources().getDrawable(R.drawable.attach_gallery_states); + context.getResources().getDrawable(R.drawable.attach_video_states); + context.getResources().getDrawable(R.drawable.attach_audio_states); + context.getResources().getDrawable(R.drawable.attach_file_states); + context.getResources().getDrawable(R.drawable.attach_contact_states); + context.getResources().getDrawable(R.drawable.attach_location_states); + context.getResources().getDrawable(R.drawable.attach_hide_states); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java index 40027e80e..30a0f5209 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Scroller.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Scroller.java index 56890bfb2..a42617994 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Scroller.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Scroller.java @@ -369,7 +369,7 @@ public class Scroller { float dx = (float) (mFinalX - mStartX); float dy = (float) (mFinalY - mStartY); - float hyp = FloatMath.sqrt(dx * dx + dy * dy); + float hyp = (float) Math.sqrt(dx * dx + dy * dy); float ndx = dx / hyp; float ndy = dy / hyp; @@ -386,7 +386,7 @@ public class Scroller { mMode = FLING_MODE; mFinished = false; - float velocity = FloatMath.sqrt(velocityX * velocityX + velocityY * velocityY); + float velocity = (float) Math.sqrt(velocityX * velocityX + velocityY * velocityY); mVelocity = velocity; float ALPHA = 800; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java index 441938c38..b10564746 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java index 447644072..9b315e9e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java @@ -3,7 +3,7 @@ * 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. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java index cd4d6364a..8ad190ad0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileDrawable.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileEx2Drawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileEx2Drawable.java index 30aa88809..f6a46363c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileEx2Drawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileEx2Drawable.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileExDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileExDrawable.java index f524a459e..563a8962e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileExDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SendingFileExDrawable.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleTextView.java index 2a1a0a8a3..eaf03eaf6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleTextView.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java index 986c40703..a793a2053 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java index a77d0f36a..899c13d18 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayoutPhoto.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayoutPhoto.java index b6a806bb2..0b7e8de7f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayoutPhoto.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayoutPhoto.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java index a1ae84c65..cc27b2e6a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java index 8e30cc027..859ee42b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java index c64b07616..224d37233 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java index f918c1b3c..cd464f6be 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StaticLayoutEx.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java index 1e0ed7ec5..ecfe7a6db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java index ea98120d6..6f363f28a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java index 9f86fe3b7..c0a4e6504 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java index 5ece5436d..48e801864 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanBotCommand.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanBotCommand.java new file mode 100644 index 000000000..8310d65be --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanBotCommand.java @@ -0,0 +1,27 @@ +/* + * This is the source code of Telegram for Android v. 3.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.text.TextPaint; + +public class URLSpanBotCommand extends URLSpanNoUnderline { + + public static boolean enabled = true; + + public URLSpanBotCommand(String url) { + super(url); + } + + @Override + public void updateDrawState(TextPaint ds) { + super.updateDrawState(ds); + ds.setColor(enabled ? 0xff316f9f : 0xff000000); + ds.setUnderlineText(false); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java index 8debb5211..b2ff88819 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderlineBold.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderlineBold.java index 7c1b06bc8..e1be75925 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderlineBold.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderlineBold.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanReplacement.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanReplacement.java index 3f38b1a48..764d0be23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanReplacement.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanReplacement.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java index d7ac826c2..14c87235a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java index b4cca99d4..3f9ba71cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui.Components; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java index deeca0aaa..b50536103 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -137,6 +137,7 @@ public class WebFrameLayout extends FrameLayout { webView = new WebView(context); webView.getSettings().setJavaScriptEnabled(true); webView.getSettings().setDomStorageEnabled(true); + String userAgent = webView.getSettings().getUserAgentString(); if (userAgent != null) { userAgent = userAgent.replace("Android", ""); @@ -232,9 +233,14 @@ public class WebFrameLayout extends FrameLayout { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - webView.stopLoading(); - webView.loadUrl("about:blank"); - webView.destroy(); + try { + removeView(webView); + webView.stopLoading(); + webView.loadUrl("about:blank"); + webView.destroy(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index 1aafe718a..86c6f7810 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -297,8 +297,10 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent } @Override - public void onOpenAnimationEnd() { - firstNameField.requestFocus(); - AndroidUtilities.showKeyboard(firstNameField); + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen) { + firstNameField.requestFocus(); + AndroidUtilities.showKeyboard(firstNameField); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index 14e342994..eea68ad19 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java index b57c3cbe0..e34a29daf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 601555b9a..8329725d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -1,19 +1,24 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; +import android.Manifest; import android.animation.ObjectAnimator; import android.animation.StateListAnimator; import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.Activity; import android.app.AlertDialog; +import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Outline; import android.os.Build; @@ -35,13 +40,13 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ImageLoader; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.UserObject; import org.telegram.messenger.support.widget.LinearLayoutManager; import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.messenger.FileLog; -import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; import org.telegram.messenger.MessagesController; @@ -62,6 +67,7 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.MenuDrawable; +import org.telegram.ui.Components.PlayerView; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; @@ -81,12 +87,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private ActionBarMenuItem passcodeItem; private ImageView floatingButton; + private AlertDialog permissionDialog; + private int prevPosition; private int prevTop; private boolean scrollUpdated; private boolean floatingHidden; private final AccelerateDecelerateInterpolator floatingInterpolator = new AccelerateDecelerateInterpolator(); + private boolean checkPermission = true; + private String selectAlertString; private String selectAlertStringGroup; private String addToGroupAlertString; @@ -140,7 +150,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (!dialogsLoaded) { - MessagesController.getInstance().loadDialogs(0, 0, 100, true); + MessagesController.getInstance().loadDialogs(0, 0, 0, 100, true); ContactsController.getInstance().checkInviteText(); dialogsLoaded = true; } @@ -411,7 +421,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. }); listView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() { @Override - public void onItemClick(View view, int position) { + public boolean onItemClick(View view, int position) { if (onlySelect || searching && searchWas || getParentActivity() == null) { if (searchWas && searching || dialogsSearchAdapter.isRecentSearchDisplayed()) { RecyclerView.Adapter adapter = listView.getAdapter(); @@ -433,16 +443,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); - return; + return true; } } } - return; + return false; } TLRPC.Dialog dialog; ArrayList dialogs = getDialogsArray(); if (position < 0 || position >= dialogs.size()) { - return; + return false; } dialog = dialogs.get(position); selectedDialog = dialog.id; @@ -453,15 +463,12 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (dialog instanceof TLRPC.TL_dialogChannel) { final TLRPC.Chat chat = MessagesController.getInstance().getChat(-lower_id); - if (chat == null) { - return; - } - builder.setItems(new CharSequence[]{(chat.flags & TLRPC.CHAT_FLAG_ADMIN) == 0 ? LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu) : LocaleController.getString("ChannelDeleteMenu", R.string.ChannelDeleteMenu)}, new DialogInterface.OnClickListener() { + builder.setItems(new CharSequence[]{chat == null || (chat.flags & TLRPC.CHAT_FLAG_ADMIN) == 0 ? LocaleController.getString("LeaveChannelMenu", R.string.LeaveChannelMenu) : LocaleController.getString("ChannelDeleteMenu", R.string.ChannelDeleteMenu)}, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, final int which) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - if ((chat.flags & TLRPC.CHAT_FLAG_ADMIN) == 0) { + if (chat == null || (chat.flags & TLRPC.CHAT_FLAG_ADMIN) == 0) { builder.setMessage(LocaleController.getString("ChannelLeaveAlert", R.string.ChannelLeaveAlert)); } else { builder.setMessage(LocaleController.getString("ChannelDeleteAlert", R.string.ChannelDeleteAlert)); @@ -524,7 +531,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. }); showDialog(builder.create()); } - + return true; } }); @@ -620,7 +627,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } if (visibleItemCount > 0) { if (layoutManager.findLastVisibleItemPosition() == getDialogsArray().size()) { - MessagesController.getInstance().loadDialogs(MessagesController.getInstance().dialogs.size(), MessagesController.getInstance().currentDialogsCount, 100, true); + MessagesController.getInstance().loadDialogs(MessagesController.getInstance().dialogs.size(), MessagesController.getInstance().currentDialogsCount, -1, 100, true); } } @@ -689,6 +696,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. actionBar.openSearchField(searchString); } + if (!onlySelect && dialogsType == 0) { + frameLayout.addView(new PlayerView(context, this), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + } + return fragmentView; } @@ -701,6 +712,57 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (dialogsSearchAdapter != null) { dialogsSearchAdapter.notifyDataSetChanged(); } + if (checkPermission && !onlySelect && Build.VERSION.SDK_INT >= 23) { + Activity activity = getParentActivity(); + if (activity != null) { + checkPermission = false; + if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED || activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + if (activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) { + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("PermissionContacts", R.string.PermissionContacts)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + showDialog(permissionDialog = builder.create()); + } else if (activity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("PermissionStorage", R.string.PermissionStorage)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + showDialog(permissionDialog = builder.create()); + } else { + askForPermissons(); + } + } + } + } + } + + @TargetApi(Build.VERSION_CODES.M) + private void askForPermissons() { + Activity activity = getParentActivity(); + if (activity == null) { + return; + } + ArrayList permissons = new ArrayList<>(); + if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { + permissons.add(Manifest.permission.READ_CONTACTS); + permissons.add(Manifest.permission.WRITE_CONTACTS); + permissons.add(Manifest.permission.GET_ACCOUNTS); + } + if (activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + permissons.add(Manifest.permission.READ_EXTERNAL_STORAGE); + permissons.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + } + String[] items = permissons.toArray(new String[permissons.size()]); + activity.requestPermissions(items, 1); + } + + @Override + protected void onDialogDismiss(Dialog dialog) { + super.onDialogDismiss(dialog); + if (permissionDialog != null && dialog == permissionDialog && getParentActivity() != null) { + askForPermissons(); + } } @Override @@ -724,6 +786,25 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } + @Override + public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { + if (requestCode == 1) { + for (int a = 0; a < permissions.length; a++) { + if (grantResults[a] != PackageManager.PERMISSION_GRANTED) { + continue; + } + switch (permissions[a]) { + case Manifest.permission.READ_CONTACTS: + ContactsController.getInstance().readContacts(); + break; + case Manifest.permission.WRITE_EXTERNAL_STORAGE: + ImageLoader.getInstance().createMediaPaths(); + break; + } + } + } + } + @Override @SuppressWarnings("unchecked") public void didReceivedNotification(int id, Object... args) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java index a3ddf0d07..307908f52 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -14,17 +14,16 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Configuration; import android.os.Build; import android.os.Environment; import android.os.StatFs; -import android.text.TextUtils; -import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.widget.AbsListView; import android.widget.AdapterView; -import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; @@ -33,6 +32,7 @@ import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -41,6 +41,7 @@ import org.telegram.messenger.AnimationCompat.ObjectAnimatorProxy; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Cells.SharedDocumentCell; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.NumberTextView; import java.io.BufferedReader; import java.io.File; @@ -61,7 +62,7 @@ public class DocumentSelectActivity extends BaseFragment { private ListView listView; private ListAdapter listAdapter; - private TextView selectedMessagesCountTextView; + private NumberTextView selectedMessagesCountTextView; private TextView emptyView; private File currentDir; @@ -145,18 +146,20 @@ public class DocumentSelectActivity extends BaseFragment { ApplicationLoader.applicationContext.registerReceiver(receiver, filter); } - actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setBackButtonDrawable(new BackDrawable(false)); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("SelectFile", R.string.SelectFile)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(int id) { if (id == -1) { - finishFragment(); - } else if (id == -2) { - selectedFiles.clear(); - actionBar.hideActionMode(); - listView.invalidateViews(); + if (actionBar.isActionModeShowed()) { + selectedFiles.clear(); + actionBar.hideActionMode(); + listView.invalidateViews(); + } else { + finishFragment(); + } } else if (id == done) { if (delegate != null) { ArrayList files = new ArrayList<>(); @@ -170,29 +173,18 @@ public class DocumentSelectActivity extends BaseFragment { actionModeViews.clear(); final ActionBarMenu actionMode = actionBar.createActionMode(); - actionModeViews.add(actionMode.addItem(-2, R.drawable.ic_ab_back_grey, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); - selectedMessagesCountTextView = new TextView(actionMode.getContext()); + selectedMessagesCountTextView = new NumberTextView(actionMode.getContext()); selectedMessagesCountTextView.setTextSize(18); selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); selectedMessagesCountTextView.setTextColor(0xff737373); - selectedMessagesCountTextView.setSingleLine(true); - selectedMessagesCountTextView.setLines(1); - selectedMessagesCountTextView.setEllipsize(TextUtils.TruncateAt.END); - selectedMessagesCountTextView.setPadding(AndroidUtilities.dp(11), 0, 0, AndroidUtilities.dp(2)); - selectedMessagesCountTextView.setGravity(Gravity.CENTER_VERTICAL); selectedMessagesCountTextView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); - actionMode.addView(selectedMessagesCountTextView); - LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) selectedMessagesCountTextView.getLayoutParams(); - layoutParams.weight = 1; - layoutParams.width = 0; - layoutParams.height = LayoutHelper.MATCH_PARENT; - selectedMessagesCountTextView.setLayoutParams(layoutParams); + actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); actionModeViews.add(actionMode.addItem(done, R.drawable.ic_ab_done_gray, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); @@ -244,18 +236,14 @@ public class DocumentSelectActivity extends BaseFragment { return false; } selectedFiles.put(file.toString(), item); - selectedMessagesCountTextView.setText(String.format("%d", selectedFiles.size())); + selectedMessagesCountTextView.setNumber(1, false); if (Build.VERSION.SDK_INT >= 11) { AnimatorSetProxy animatorSet = new AnimatorSetProxy(); ArrayList animators = new ArrayList<>(); for (int a = 0; a < actionModeViews.size(); a++) { View view2 = actionModeViews.get(a); AndroidUtilities.clearDrawableAnimation(view2); - if (a < 1) { - animators.add(ObjectAnimatorProxy.ofFloat(view2, "translationX", -AndroidUtilities.dp(56), 0)); - } else { - animators.add(ObjectAnimatorProxy.ofFloat(view2, "scaleY", 0.1f, 1.0f)); - } + animators.add(ObjectAnimatorProxy.ofFloat(view2, "scaleY", 0.1f, 1.0f)); } animatorSet.playTogether(animators); animatorSet.setDuration(250); @@ -331,7 +319,7 @@ public class DocumentSelectActivity extends BaseFragment { if (selectedFiles.isEmpty()) { actionBar.hideActionMode(); } else { - selectedMessagesCountTextView.setText(String.format("%d", selectedFiles.size())); + selectedMessagesCountTextView.setNumber(selectedFiles.size(), true); } scrolling = false; if (view instanceof SharedDocumentCell) { @@ -359,6 +347,34 @@ public class DocumentSelectActivity extends BaseFragment { if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } + fixLayoutInternal(); + } + + @Override + public void onConfigurationChanged(android.content.res.Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (listView != null) { + ViewTreeObserver obs = listView.getViewTreeObserver(); + obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + listView.getViewTreeObserver().removeOnPreDrawListener(this); + fixLayoutInternal(); + return true; + } + }); + } + } + + private void fixLayoutInternal() { + if (selectedMessagesCountTextView == null) { + return; + } + if (!AndroidUtilities.isTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + selectedMessagesCountTextView.setTextSize(18); + } else { + selectedMessagesCountTextView.setTextSize(20); + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 276323c46..df04f1b57 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index e9d157b18..67f086d08 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -375,9 +375,11 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati } @Override - public void onOpenAnimationEnd() { - nameTextView.requestFocus(); - AndroidUtilities.showKeyboard(nameTextView); + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen) { + nameTextView.requestFocus(); + AndroidUtilities.showKeyboard(nameTextView); + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java index 65af539ea..389cb18ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java index f695fda44..61b620d0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java index dd43638e3..6570deb9e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index e98fb5f09..b6c0a4f6c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java index 319e0a410..33dc5a6ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -43,6 +43,7 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.LastSeenRadioCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.LayoutHelper; @@ -57,6 +58,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter private int currentType = 0; private ArrayList currentPlus; private ArrayList currentMinus; + private int lastCheckedType = -1; private int lastSeenSectionRow; private int everybodyRow; @@ -175,6 +177,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter return; } doneButton.setVisibility(View.VISIBLE); + lastCheckedType = currentType; currentType = newType; updateRows(); } else if (i == neverShareRow || i == alwaysShareRow) { @@ -203,6 +206,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter } } doneButton.setVisibility(View.VISIBLE); + lastCheckedType = -1; listAdapter.notifyDataSetChanged(); } }); @@ -387,6 +391,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter @Override public void onResume() { super.onResume(); + lastCheckedType = -1; if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } @@ -438,13 +443,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter view.setBackgroundColor(0xffffffff); } TextSettingsCell textCell = (TextSettingsCell) view; - if (i == everybodyRow) { - textCell.setTextAndIcon(LocaleController.getString("LastSeenEverybody", R.string.LastSeenEverybody), currentType == 0 ? R.drawable.check_blue : 0, true); - } else if (i == myContactsRow) { - textCell.setTextAndIcon(LocaleController.getString("LastSeenContacts", R.string.LastSeenContacts), currentType == 2 ? R.drawable.check_blue : 0, true); - } else if (i == nobodyRow) { - textCell.setTextAndIcon(LocaleController.getString("LastSeenNobody", R.string.LastSeenNobody), currentType == 1 ? R.drawable.check_blue : 0, false); - } else if (i == alwaysShareRow) { + if (i == alwaysShareRow) { String value; if (currentPlus.size() != 0) { value = LocaleController.formatPluralString("Users", currentPlus.size()); @@ -483,25 +482,49 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter } else if (i == shareSectionRow) { ((HeaderCell) view).setText(LocaleController.getString("AddExceptions", R.string.AddExceptions)); } + } else if (type == 3) { + if (view == null) { + view = new LastSeenRadioCell(mContext); + view.setBackgroundColor(0xffffffff); + } + LastSeenRadioCell textCell = (LastSeenRadioCell) view; + int checkedType = 0; + if (i == everybodyRow) { + textCell.setText(LocaleController.getString("LastSeenEverybody", R.string.LastSeenEverybody), lastCheckedType == 0, true); + checkedType = 0; + } else if (i == myContactsRow) { + textCell.setText(LocaleController.getString("LastSeenContacts", R.string.LastSeenContacts), lastCheckedType == 2, true); + checkedType = 2; + } else if (i == nobodyRow) { + textCell.setText(LocaleController.getString("LastSeenNobody", R.string.LastSeenNobody), lastCheckedType == 1, false); + checkedType = 1; + } + if (lastCheckedType == checkedType) { + textCell.setChecked(false, true); + } else if (currentType == checkedType) { + textCell.setChecked(true, true); + } } return view; } @Override public int getItemViewType(int i) { - if (i == alwaysShareRow || i == neverShareRow || i == everybodyRow || i == myContactsRow || i == nobodyRow) { + if (i == alwaysShareRow || i == neverShareRow) { return 0; } else if (i == shareDetailRow || i == lastSeenDetailRow) { return 1; } else if (i == lastSeenSectionRow || i == shareSectionRow) { return 2; + } else if (i == everybodyRow || i == myContactsRow || i == nobodyRow) { + return 3; } return 0; } @Override public int getViewTypeCount() { - return 3; + return 4; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java index 7dfb0d442..c7365924a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 312ada984..52c8664ed 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -1,13 +1,14 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; +import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.ProgressDialog; @@ -15,6 +16,7 @@ import android.content.ContentResolver; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Point; @@ -26,7 +28,6 @@ import android.provider.Browser; import android.provider.ContactsContract; import android.support.annotation.NonNull; import android.view.ActionMode; -import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -46,6 +47,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NativeCrashManager; @@ -66,7 +68,6 @@ import org.telegram.ui.Adapters.DrawerLayoutAdapter; import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.DrawerLayoutContainer; -import org.telegram.ui.Components.DrawerPlayerView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PasscodeView; @@ -260,22 +261,24 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa drawerLayoutContainer.addView(actionBarLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } - FrameLayout listViewContainer = new FrameLayout(this); - listViewContainer.setBackgroundColor(0xffffffff); - drawerLayoutContainer.setDrawerLayout(listViewContainer); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listViewContainer.getLayoutParams(); - Point screenSize = AndroidUtilities.getRealScreenSize(); - layoutParams.width = AndroidUtilities.isTablet() ? AndroidUtilities.dp(320) : Math.min(screenSize.x, screenSize.y) - AndroidUtilities.dp(56); - layoutParams.height = LayoutHelper.MATCH_PARENT; - listViewContainer.setLayoutParams(layoutParams); - - ListView listView = new ListView(this); + ListView listView = new ListView(this) { + @Override + public boolean hasOverlappingRendering() { + return false; + } + }; + listView.setBackgroundColor(0xffffffff); listView.setAdapter(drawerLayoutAdapter = new DrawerLayoutAdapter(this)); listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); listView.setDivider(null); listView.setDividerHeight(0); listView.setVerticalScrollBarEnabled(false); - listViewContainer.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + drawerLayoutContainer.setDrawerLayout(listView); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); + Point screenSize = AndroidUtilities.getRealScreenSize(); + layoutParams.width = AndroidUtilities.isTablet() ? AndroidUtilities.dp(320) : Math.min(screenSize.x, screenSize.y) - AndroidUtilities.dp(56); + layoutParams.height = LayoutHelper.MATCH_PARENT; + listView.setLayoutParams(layoutParams); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -335,16 +338,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } }); - DrawerPlayerView drawerPlayerView = new DrawerPlayerView(this, listView); - listViewContainer.addView(drawerPlayerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.LEFT | Gravity.BOTTOM)); - drawerPlayerView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - actionBarLayout.presentFragment(new AudioPlayerActivity()); - drawerLayoutContainer.closeDrawer(false); - } - }); - drawerLayoutContainer.setParentActionBarLayout(actionBarLayout); actionBarLayout.setDrawerLayoutContainer(drawerLayoutContainer); actionBarLayout.init(mainFragmentsStack); @@ -458,10 +451,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa drawerLayoutContainer.setAllowOpenDrawer(allowOpen, false); } - /*if (BuildVars.DEBUG_VERSION) { - ViewServer.get(this).addWindow(this); - }*/ - handleIntent(getIntent(), false, savedInstanceState != null, false); needLayout(); } @@ -510,6 +499,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa Integer push_chat_id = 0; Integer push_enc_id = 0; Integer open_settings = 0; + long dialogId = intent != null && intent.getExtras() != null ? intent.getExtras().getLong("dialogId", 0) : 0; boolean showDialogsList = false; boolean showPlayer = false; @@ -731,6 +721,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa String botUser = null; String botChat = null; String message = null; + boolean hasUrl = false; String scheme = data.getScheme(); if (scheme != null) { if ((scheme.equals("http") || scheme.equals("https"))) { @@ -744,8 +735,17 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } else if (path.startsWith("addstickers/")) { sticker = path.replace("addstickers/", ""); } else if (path.startsWith("msg/")) { - message = data.getQueryParameter("text"); - message += " " + data.getQueryParameter("url"); + message = data.getQueryParameter("url"); + if (message == null) { + message = ""; + } + if (data.getQueryParameter("text") != null) { + if (message.length() > 0) { + hasUrl = true; + message += "\n"; + } + message += data.getQueryParameter("text"); + } } else if (path.length() >= 5) { username = data.getLastPathSegment(); botUser = data.getQueryParameter("start"); @@ -772,13 +772,22 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } else if (url.startsWith("tg:msg") || url.startsWith("tg://msg")) { url = url.replace("tg:msg", "tg://telegram.org").replace("tg://msg", "tg://telegram.org"); data = Uri.parse(url); - message = data.getQueryParameter("text"); - message += " " + data.getQueryParameter("url"); + message = data.getQueryParameter("url"); + if (message == null) { + message = ""; + } + if (data.getQueryParameter("text") != null) { + if (message.length() > 0) { + hasUrl = true; + message += "\n"; + } + message += data.getQueryParameter("text"); + } } } } if (username != null || group != null || sticker != null || message != null) { - runLinkRequest(username, group, sticker, botUser, botChat, message, 0); + runLinkRequest(username, group, sticker, botUser, botChat, message, hasUrl, 0); } else { try { Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null); @@ -882,30 +891,34 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (!AndroidUtilities.isTablet()) { NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); } - Bundle args = new Bundle(); - args.putBoolean("onlySelect", true); - args.putString("selectAlertString", LocaleController.getString("SendMessagesTo", R.string.SendMessagesTo)); - args.putString("selectAlertStringGroup", LocaleController.getString("SendMessagesToGroup", R.string.SendMessagesToGroup)); - DialogsActivity fragment = new DialogsActivity(args); - fragment.setDelegate(this); - boolean removeLast; - if (AndroidUtilities.isTablet()) { - removeLast = layersActionBarLayout.fragmentsStack.size() > 0 && layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1) instanceof DialogsActivity; - } else { - removeLast = actionBarLayout.fragmentsStack.size() > 1 && actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1) instanceof DialogsActivity; - } - actionBarLayout.presentFragment(fragment, removeLast, true, true); - pushOpened = true; - if (PhotoViewer.getInstance().isVisible()) { - PhotoViewer.getInstance().closePhoto(false, true); - } + if (dialogId == 0) { + Bundle args = new Bundle(); + args.putBoolean("onlySelect", true); + args.putString("selectAlertString", LocaleController.getString("SendMessagesTo", R.string.SendMessagesTo)); + args.putString("selectAlertStringGroup", LocaleController.getString("SendMessagesToGroup", R.string.SendMessagesToGroup)); + DialogsActivity fragment = new DialogsActivity(args); + fragment.setDelegate(this); + boolean removeLast; + if (AndroidUtilities.isTablet()) { + removeLast = layersActionBarLayout.fragmentsStack.size() > 0 && layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1) instanceof DialogsActivity; + } else { + removeLast = actionBarLayout.fragmentsStack.size() > 1 && actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1) instanceof DialogsActivity; + } + actionBarLayout.presentFragment(fragment, removeLast, true, true); + pushOpened = true; + if (PhotoViewer.getInstance().isVisible()) { + PhotoViewer.getInstance().closePhoto(false, true); + } - drawerLayoutContainer.setAllowOpenDrawer(false, false); - if (AndroidUtilities.isTablet()) { - actionBarLayout.showLastFragment(); - rightActionBarLayout.showLastFragment(); + drawerLayoutContainer.setAllowOpenDrawer(false, false); + if (AndroidUtilities.isTablet()) { + actionBarLayout.showLastFragment(); + rightActionBarLayout.showLastFragment(); + } else { + drawerLayoutContainer.setAllowOpenDrawer(true, false); + } } else { - drawerLayoutContainer.setAllowOpenDrawer(true, false); + didSelectDialog(null, dialogId, false); } } else if (open_settings != 0) { actionBarLayout.presentFragment(new SettingsActivity(), false, true, true); @@ -956,7 +969,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa return false; } - private void runLinkRequest(final String username, final String group, final String sticker, final String botUser, final String botChat, final String message, final int state) { + private void runLinkRequest(final String username, final String group, final String sticker, final String botUser, final String botChat, final String message, final boolean hasUrl, final int state) { final ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); progressDialog.setCanceledOnTouchOutside(false); @@ -1076,7 +1089,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - runLinkRequest(username, group, sticker, botUser, botChat, message, 1); + runLinkRequest(username, group, sticker, botUser, botChat, message, hasUrl, 1); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -1166,6 +1179,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa editor.commit(); Bundle args = new Bundle(); args.putBoolean("scrollToTopOnResume", true); + args.putBoolean("hasUrl", hasUrl); int lower_part = (int) did; int high_id = (int) (did >> 32); if (lower_part != 0) { @@ -1184,7 +1198,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa actionBarLayout.presentFragment(new ChatActivity(args), true, false, true); } }); - presentFragment(fragment); + presentFragment(fragment, false, true); } if (requestId != 0) { @@ -1236,7 +1250,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } @Override - public void didSelectDialog(DialogsActivity messageFragment, long dialog_id, boolean param) { + public void didSelectDialog(DialogsActivity dialogsFragment, long dialog_id, boolean param) { if (dialog_id != 0) { int lower_part = (int)dialog_id; int high_id = (int)(dialog_id >> 32); @@ -1265,24 +1279,21 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if(android.os.Build.VERSION.SDK_INT >= 16) { if (AndroidUtilities.isTablet()) { actionBarLayout.presentFragment(fragment, false, true, true); - } - - if (!AndroidUtilities.isTablet()) { + } else { actionBarLayout.addFragmentToStack(fragment, actionBarLayout.fragmentsStack.size() - 1); } - if (!fragment.openVideoEditor(videoPath, true, false)) { + if (!fragment.openVideoEditor(videoPath, dialogsFragment != null, false) && dialogsFragment != null) { if (!AndroidUtilities.isTablet()) { - messageFragment.finishFragment(true); + dialogsFragment.finishFragment(true); } } } else { - actionBarLayout.presentFragment(fragment, true); + actionBarLayout.presentFragment(fragment, dialogsFragment != null, dialogsFragment == null, true); SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id, null, true); } } else { - - actionBarLayout.presentFragment(fragment, true); + actionBarLayout.presentFragment(fragment, dialogsFragment != null, dialogsFragment == null, true); if (sendingText != null) { SendMessagesHelper.prepareSendingText(sendingText, dialog_id, true); @@ -1339,13 +1350,13 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa public void needLayout() { if (AndroidUtilities.isTablet()) { - RelativeLayout.LayoutParams relativeLayoutParams = (RelativeLayout.LayoutParams)layersActionBarLayout.getLayoutParams(); relativeLayoutParams.leftMargin = (AndroidUtilities.displaySize.x - relativeLayoutParams.width) / 2; int y = (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); relativeLayoutParams.topMargin = y + (AndroidUtilities.displaySize.y - relativeLayoutParams.height - y) / 2; layersActionBarLayout.setLayoutParams(relativeLayoutParams); + if (!AndroidUtilities.isSmallTablet() || getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { tabletFullSize = false; int leftWidth = AndroidUtilities.displaySize.x / 100 * 35; @@ -1398,7 +1409,8 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa BaseFragment chatFragment = rightActionBarLayout.fragmentsStack.get(0); chatFragment.onPause(); rightActionBarLayout.fragmentsStack.remove(0); - actionBarLayout.addFragmentToStack(chatFragment); + actionBarLayout.fragmentsStack.add(chatFragment); + //actionBarLayout.addFragmentToStack(chatFragment); if (passcodeView.getVisibility() != View.VISIBLE) { actionBarLayout.showLastFragment(); } @@ -1408,24 +1420,25 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } public void fixLayout() { - if (AndroidUtilities.isTablet()) { - if (actionBarLayout == null) { - return; - } - actionBarLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - needLayout(); - if (actionBarLayout != null) { - if (Build.VERSION.SDK_INT < 16) { - actionBarLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); - } else { - actionBarLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } + if (!AndroidUtilities.isTablet()) { + return; + } + if (actionBarLayout == null) { + return; + } + actionBarLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + needLayout(); + if (actionBarLayout != null) { + if (Build.VERSION.SDK_INT < 16) { + actionBarLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); + } else { + actionBarLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this); } } - }); - } + } + }); } @Override @@ -1451,16 +1464,73 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == 3 || requestCode == 4 || requestCode == 5) { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (requestCode == 4) { + ImageLoader.getInstance().createMediaPaths(); + } else if (requestCode == 5) { + ContactsController.getInstance().readContacts(); + } + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + if (requestCode == 3) { + builder.setMessage(LocaleController.getString("PermissionNoAudio", R.string.PermissionNoAudio)); + } else if (requestCode == 4) { + builder.setMessage(LocaleController.getString("PermissionStorage", R.string.PermissionStorage)); + } else if (requestCode == 5) { + builder.setMessage(LocaleController.getString("PermissionContacts", R.string.PermissionContacts)); + } + builder.setNegativeButton(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), new DialogInterface.OnClickListener() { + @TargetApi(Build.VERSION_CODES.GINGERBREAD) + @Override + public void onClick(DialogInterface dialog, int which) { + try { + Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + ApplicationLoader.applicationContext.getPackageName())); + startActivity(intent); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.show(); + return; + } + if (actionBarLayout.fragmentsStack.size() != 0) { + BaseFragment fragment = actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1); + fragment.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); + } + if (AndroidUtilities.isTablet()) { + if (rightActionBarLayout.fragmentsStack.size() != 0) { + BaseFragment fragment = rightActionBarLayout.fragmentsStack.get(rightActionBarLayout.fragmentsStack.size() - 1); + fragment.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); + } + if (layersActionBarLayout.fragmentsStack.size() != 0) { + BaseFragment fragment = layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1); + fragment.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); + } + } + } + @Override protected void onPause() { super.onPause(); + ApplicationLoader.mainInterfacePaused = true; onPasscodePause(); actionBarLayout.onPause(); if (AndroidUtilities.isTablet()) { rightActionBarLayout.onPause(); layersActionBarLayout.onPause(); } - ApplicationLoader.mainInterfacePaused = true; + if (passcodeView != null) { + passcodeView.onPause(); + } ConnectionsManager.getInstance().setAppPaused(true, false); AndroidUtilities.unregisterUpdates(); } @@ -1485,6 +1555,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override protected void onResume() { super.onResume(); + ApplicationLoader.mainInterfacePaused = false; onPasscodeResume(); if (passcodeView.getVisibility() != View.VISIBLE) { actionBarLayout.onResume(); @@ -1497,7 +1568,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } AndroidUtilities.checkForCrashes(this); AndroidUtilities.checkForUpdates(this); - ApplicationLoader.mainInterfacePaused = false; ConnectionsManager.getInstance().setAppPaused(false, false); updateCurrentConnectionState(); if (PhotoViewer.getInstance().isVisible()) { @@ -1568,7 +1638,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override public void onClick(DialogInterface dialogInterface, int i) { try { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://telegram.org/faq#can-39t-send-messages-to-non-contacts")); + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(LocaleController.getString("NobodyLikesSpamUrl", R.string.NobodyLikesSpamUrl))); intent.putExtra(Browser.EXTRA_APPLICATION_ID, getPackageName()); startActivity(intent); } catch (Exception e) { @@ -1734,6 +1804,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override public void onActionModeStarted(ActionMode mode) { super.onActionModeStarted(mode); + if (Build.VERSION.SDK_INT >= 23 && mode.getType() == ActionMode.TYPE_FLOATING) { + return; + } actionBarLayout.onActionModeStarted(mode); if (AndroidUtilities.isTablet()) { rightActionBarLayout.onActionModeStarted(mode); @@ -1744,6 +1817,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override public void onActionModeFinished(ActionMode mode) { super.onActionModeFinished(mode); + if (Build.VERSION.SDK_INT >= 23 && mode.getType() == ActionMode.TYPE_FLOATING) { + return; + } actionBarLayout.onActionModeFinished(mode); if (AndroidUtilities.isTablet()) { rightActionBarLayout.onActionModeFinished(mode); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index c8a8efc75..d3cb22789 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -1,18 +1,24 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; +import android.Manifest; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.StateListAnimator; +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Outline; import android.location.Location; import android.location.LocationManager; @@ -90,6 +96,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private AnimatorSet animatorSet; + private boolean checkPermission = true; + private boolean searching; private boolean searchWas; @@ -117,11 +125,6 @@ public class LocationActivity extends BaseFragment implements NotificationCenter void didSelectLocation(TLRPC.MessageMedia location); } - @Override - public boolean needAddActionBar() { - return messageObject != null; - } - @Override public boolean onFragmentCreate() { super.onFragmentCreate(); @@ -156,6 +159,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (AndroidUtilities.isTablet()) { actionBar.setOccupyStatusBar(false); } + actionBar.setAddToContainer(messageObject != null); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -293,7 +297,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (userLocation != null) { LatLng latLng = new LatLng(userLocation.getLatitude(), userLocation.getLongitude()); if (googleMap != null) { - CameraUpdate position = CameraUpdateFactory.newLatLngZoom(latLng, googleMap.getMaxZoomLevel() - 8); + CameraUpdate position = CameraUpdateFactory.newLatLngZoom(latLng, googleMap.getMaxZoomLevel() - 4); googleMap.animateCamera(position); } } @@ -333,7 +337,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } catch (Exception e) { FileLog.e("tmessages", e); } - CameraUpdate position = CameraUpdateFactory.newLatLngZoom(latLng, googleMap.getMaxZoomLevel() - 8); + CameraUpdate position = CameraUpdateFactory.newLatLngZoom(latLng, googleMap.getMaxZoomLevel() - 4); googleMap.moveCamera(position); } @@ -372,8 +376,17 @@ public class LocationActivity extends BaseFragment implements NotificationCenter locationButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (Build.VERSION.SDK_INT >= 23) { + Activity activity = getParentActivity(); + if (activity != null) { + if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + showPermissionAlert(); + return; + } + } + } if (myLocation != null && googleMap != null) { - googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(myLocation.getLatitude(), myLocation.getLongitude()), googleMap.getMaxZoomLevel() - 8)); + googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(myLocation.getLatitude(), myLocation.getLongitude()), googleMap.getMaxZoomLevel() - 4)); } } }); @@ -516,6 +529,15 @@ public class LocationActivity extends BaseFragment implements NotificationCenter locationButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { + if (Build.VERSION.SDK_INT >= 23) { + Activity activity = getParentActivity(); + if (activity != null) { + if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + showPermissionAlert(); + return; + } + } + } if (myLocation != null && googleMap != null) { if (Build.VERSION.SDK_INT >= 11) { AnimatorSet animatorSet = new AnimatorSet(); @@ -614,21 +636,50 @@ public class LocationActivity extends BaseFragment implements NotificationCenter return fragmentView; } - @Override - public void onOpenAnimationEnd() { - try { - if (mapView.getParent() instanceof ViewGroup) { - ViewGroup viewGroup = (ViewGroup) mapView.getParent(); - viewGroup.removeView(mapView); - } - } catch (Exception e) { - FileLog.e("tmessages", e); + private void showPermissionAlert() { + if (getParentActivity() == null) { + return; } - if (mapViewClip != null) { - mapViewClip.addView(mapView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + AndroidUtilities.dp(10), Gravity.TOP | Gravity.LEFT)); - updateClipView(listView.getFirstVisiblePosition()); - } else { - ((FrameLayout) fragmentView).addView(mapView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("PermissionNoLocation", R.string.PermissionNoLocation)); + builder.setNegativeButton(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), new DialogInterface.OnClickListener() { + @TargetApi(Build.VERSION_CODES.GINGERBREAD) + @Override + public void onClick(DialogInterface dialog, int which) { + if (getParentActivity() == null) { + return; + } + try { + Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + ApplicationLoader.applicationContext.getPackageName())); + getParentActivity().startActivity(intent); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + showDialog(builder.create()); + } + + @Override + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen) { + try { + if (mapView.getParent() instanceof ViewGroup) { + ViewGroup viewGroup = (ViewGroup) mapView.getParent(); + viewGroup.removeView(mapView); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + if (mapViewClip != null) { + mapViewClip.addView(mapView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, overScrollHeight + AndroidUtilities.dp(10), Gravity.TOP | Gravity.LEFT)); + updateClipView(listView.getFirstVisiblePosition()); + } else { + ((FrameLayout) fragmentView).addView(mapView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + } } } @@ -820,7 +871,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter googleMap.animateCamera(position); } else { firstWas = true; - CameraUpdate position = CameraUpdateFactory.newLatLngZoom(latLng, googleMap.getMaxZoomLevel() - 8); + CameraUpdate position = CameraUpdateFactory.newLatLngZoom(latLng, googleMap.getMaxZoomLevel() - 4); googleMap.moveCamera(position); } } @@ -864,6 +915,15 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } updateUserData(); fixLayoutInternal(true); + if (checkPermission && Build.VERSION.SDK_INT >= 23) { + Activity activity = getParentActivity(); + if (activity != null) { + checkPermission = false; + if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + activity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 2); + } + } + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index e66f29f5b..d8134c068 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -765,6 +765,7 @@ public class LoginActivity extends BaseFragment { needShowAlert(LocaleController.getString("AppName", R.string.AppName), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); return; } + ConnectionsManager.getInstance().cleanUp(); TLRPC.TL_auth_sendCode req = new TLRPC.TL_auth_sendCode(); String phone = PhoneFormat.stripExceptNumbers("" + codeField.getText() + phoneField.getText()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index d821ece68..ef51ac9bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -59,6 +59,7 @@ import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.Adapters.BaseSectionsAdapter; @@ -73,6 +74,8 @@ import org.telegram.ui.Cells.SharedPhotoVideoCell; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.NumberTextView; +import org.telegram.ui.Components.PlayerView; import org.telegram.ui.Components.SectionsListView; import org.telegram.ui.Components.WebFrameLayout; @@ -88,7 +91,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No private SharedPhotoVideoAdapter photoVideoAdapter; private SharedLinksAdapter linksAdapter; private SharedDocumentsAdapter documentsAdapter; + private SharedDocumentsAdapter audioAdapter; private MediaSearchAdapter documentsSearchAdapter; + private MediaSearchAdapter audioSearchAdapter; private MediaSearchAdapter linksSearchAdapter; private SectionsListView listView; private LinearLayout progressView; @@ -98,7 +103,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No private TextView dropDown; private ActionBarMenuItem dropDownContainer; private ActionBarMenuItem searchItem; - private TextView selectedMessagesCountTextView; + private NumberTextView selectedMessagesCountTextView; private ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout; private ArrayList cellCache = new ArrayList<>(6); @@ -186,11 +191,12 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } } - private SharedMediaData sharedMediaData[] = new SharedMediaData[4]; + private SharedMediaData sharedMediaData[] = new SharedMediaData[5]; private final static int shared_media_item = 1; private final static int files_item = 2; private final static int links_item = 5; + private final static int music_item = 6; private final static int forward = 3; private final static int delete = 4; @@ -226,26 +232,29 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No @Override public View createView(Context context) { - actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setBackButtonDrawable(new BackDrawable(false)); actionBar.setTitle(""); actionBar.setAllowOverlayTitle(false); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(int id) { if (id == -1) { - if (Build.VERSION.SDK_INT < 11 && listView != null) { - listView.setAdapter(null); - listView = null; - photoVideoAdapter = null; - documentsAdapter = null; - linksAdapter = null; + if (actionBar.isActionModeShowed()) { + selectedFiles.clear(); + cantDeleteMessagesCount = 0; + actionBar.hideActionMode(); + listView.invalidateViews(); + } else { + if (Build.VERSION.SDK_INT < 11 && listView != null) { + listView.setAdapter(null); + listView = null; + photoVideoAdapter = null; + documentsAdapter = null; + audioAdapter = null; + linksAdapter = null; + } + finishFragment(); } - finishFragment(); - } else if (id == -2) { - selectedFiles.clear(); - cantDeleteMessagesCount = 0; - actionBar.hideActionMode(); - listView.invalidateViews(); } else if (id == shared_media_item) { if (selectedMode == 0) { return; @@ -264,6 +273,12 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } selectedMode = 3; switchToCurrentSelectedMode(); + } else if (id == music_item) { + if (selectedMode == 4) { + return; + } + selectedMode = 4; + switchToCurrentSelectedMode(); } else if (id == delete) { if (getParentActivity() == null) { return; @@ -372,6 +387,8 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No documentsSearchAdapter.search(null); } else if (selectedMode == 3) { linksSearchAdapter.search(null); + } else if (selectedMode == 4) { + audioSearchAdapter.search(null); } searching = false; searchWas = false; @@ -395,6 +412,11 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No return; } linksSearchAdapter.search(text); + } else if (selectedMode == 4) { + if (audioSearchAdapter == null) { + return; + } + audioSearchAdapter.search(text); } } }); @@ -407,8 +429,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No dropDownContainer.addSubItem(files_item, LocaleController.getString("DocumentsTitle", R.string.DocumentsTitle), 0); if ((int) dialog_id != 0) { dropDownContainer.addSubItem(links_item, LocaleController.getString("LinksTitle", R.string.LinksTitle), 0); + dropDownContainer.addSubItem(music_item, LocaleController.getString("AudioTitle", R.string.AudioTitle), 0); } - actionBar.addView(dropDownContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, AndroidUtilities.isTablet() ? 64 : 56, 0, 40, 0)); + actionBar.addView(dropDownContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, AndroidUtilities.isTablet() ? 64 : 56, 0, 40, 0)); dropDownContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -430,24 +453,18 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No dropDownContainer.addView(dropDown, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 16, 0, 0, 0)); final ActionBarMenu actionMode = actionBar.createActionMode(); - actionModeViews.add(actionMode.addItem(-2, R.drawable.ic_ab_back_grey, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); - selectedMessagesCountTextView = new TextView(actionMode.getContext()); + selectedMessagesCountTextView = new NumberTextView(actionMode.getContext()); selectedMessagesCountTextView.setTextSize(18); selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); selectedMessagesCountTextView.setTextColor(0xff737373); - selectedMessagesCountTextView.setSingleLine(true); - selectedMessagesCountTextView.setLines(1); - selectedMessagesCountTextView.setEllipsize(TextUtils.TruncateAt.END); - selectedMessagesCountTextView.setPadding(AndroidUtilities.dp(11), 0, 0, AndroidUtilities.dp(2)); - selectedMessagesCountTextView.setGravity(Gravity.CENTER_VERTICAL); selectedMessagesCountTextView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return true; } }); - actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f)); + actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 65, 0, 0, 0)); if ((int) dialog_id != 0) { actionModeViews.add(actionMode.addItem(forward, R.drawable.ic_ab_fwd_forward, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); @@ -455,8 +472,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No actionModeViews.add(actionMode.addItem(delete, R.drawable.ic_ab_fwd_delete, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); photoVideoAdapter = new SharedPhotoVideoAdapter(context); - documentsAdapter = new SharedDocumentsAdapter(context); + documentsAdapter = new SharedDocumentsAdapter(context, 1); + audioAdapter = new SharedDocumentsAdapter(context, 4); documentsSearchAdapter = new MediaSearchAdapter(context, 1); + audioSearchAdapter = new MediaSearchAdapter(context, 4); linksSearchAdapter = new MediaSearchAdapter(context, 3); linksAdapter = new SharedLinksAdapter(context); @@ -472,7 +491,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, final int i, long l) { - if (selectedMode == 1 && view instanceof SharedDocumentCell) { + if ((selectedMode == 1 || selectedMode == 4) && view instanceof SharedDocumentCell) { MediaActivity.this.onItemClick(i, view, ((SharedDocumentCell) view).getDocument(), 0); } else if (selectedMode == 3 && view instanceof SharedLinkCell) { MediaActivity.this.onItemClick(i, view, ((SharedLinkCell) view).getMessage(), 0); @@ -502,6 +521,8 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No type = SharedMediaQuery.MEDIA_FILE; } else if (selectedMode == 2) { type = SharedMediaQuery.MEDIA_AUDIO; + } else if (selectedMode == 4) { + type = SharedMediaQuery.MEDIA_MUSIC; } else { type = SharedMediaQuery.MEDIA_URL; } @@ -512,7 +533,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView parent, View view, int i, long id) { - if (selectedMode == 1 && view instanceof SharedDocumentCell) { + if ((selectedMode == 1 || selectedMode == 4) && view instanceof SharedDocumentCell) { SharedDocumentCell cell = (SharedDocumentCell) view; MessageObject message = cell.getDocument(); return MediaActivity.this.onItemLongClick(message, view, 0); @@ -564,6 +585,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No switchToCurrentSelectedMode(); + if (!AndroidUtilities.isTablet()) { + frameLayout.addView(new PlayerView(context, this), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 39, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + } + return fragmentView; } @@ -600,12 +625,16 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (documentsAdapter != null) { documentsAdapter.notifyDataSetChanged(); } - } else if (selectedMode == 3 && type == 3) { + } else if (selectedMode == 3 && type == 3) { if (linksAdapter != null) { linksAdapter.notifyDataSetChanged(); } + } else if (selectedMode == 4 && type == 4) { + if (audioAdapter != null) { + audioAdapter.notifyDataSetChanged(); + } } - if (selectedMode == 1 || selectedMode == 3) { + if (selectedMode == 1 || selectedMode == 3 || selectedMode == 4) { searchItem.setVisibility(!sharedMediaData[selectedMode].messages.isEmpty() && !searching ? View.VISIBLE : View.GONE); } } @@ -642,7 +671,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (linksAdapter != null) { linksAdapter.notifyDataSetChanged(); } - if (selectedMode == 1 || selectedMode == 3) { + if (audioAdapter != null) { + audioAdapter.notifyDataSetChanged(); + } + if (selectedMode == 1 || selectedMode == 3 || selectedMode == 4) { searchItem.setVisibility(!sharedMediaData[selectedMode].messages.isEmpty() && !searching ? View.VISIBLE : View.GONE); } } @@ -675,7 +707,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (linksAdapter != null) { linksAdapter.notifyDataSetChanged(); } - if (selectedMode == 1 || selectedMode == 3) { + if (audioAdapter != null) { + audioAdapter.notifyDataSetChanged(); + } + if (selectedMode == 1 || selectedMode == 3 || selectedMode == 4) { searchItem.setVisibility(!sharedMediaData[selectedMode].messages.isEmpty() && !searching ? View.VISIBLE : View.GONE); } } @@ -786,7 +821,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No public void setPhotoChecked(int index) { } @Override - public void cancelButtonPressed() { } + public boolean cancelButtonPressed() { return true; } @Override public void sendButtonPressed(int index) { } @@ -803,6 +838,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } else if (selectedMode == 3) { listView.setAdapter(linksSearchAdapter); linksSearchAdapter.notifyDataSetChanged(); + } else if (selectedMode == 4) { + listView.setAdapter(audioSearchAdapter); + audioSearchAdapter.notifyDataSetChanged(); } } if (emptyTextView != null) { @@ -829,15 +867,22 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } listView.setVisibility(View.VISIBLE); listView.setPadding(0, 0, 0, AndroidUtilities.dp(4)); - } else if (selectedMode == 1) { - listView.setAdapter(documentsAdapter); - dropDown.setText(LocaleController.getString("DocumentsTitle", R.string.DocumentsTitle)); - emptyImageView.setImageResource(R.drawable.tip2); - emptyTextView.setText(LocaleController.getString("NoSharedFiles", R.string.NoSharedFiles)); + } else if (selectedMode == 1 || selectedMode == 4) { + if (selectedMode == 1) { + listView.setAdapter(documentsAdapter); + dropDown.setText(LocaleController.getString("DocumentsTitle", R.string.DocumentsTitle)); + emptyImageView.setImageResource(R.drawable.tip2); + emptyTextView.setText(LocaleController.getString("NoSharedFiles", R.string.NoSharedFiles)); + } else if (selectedMode == 4) { + listView.setAdapter(audioAdapter); + dropDown.setText(LocaleController.getString("AudioTitle", R.string.AudioTitle)); + emptyImageView.setImageResource(R.drawable.tip4); + emptyTextView.setText(LocaleController.getString("NoSharedAudio", R.string.NoSharedAudio)); + } searchItem.setVisibility(!sharedMediaData[selectedMode].messages.isEmpty() ? View.VISIBLE : View.GONE); if (!sharedMediaData[selectedMode].loading && !sharedMediaData[selectedMode].endReached && sharedMediaData[selectedMode].messages.isEmpty()) { sharedMediaData[selectedMode].loading = true; - SharedMediaQuery.loadMedia(dialog_id, 0, 50, 0, SharedMediaQuery.MEDIA_FILE, true, classGuid); + SharedMediaQuery.loadMedia(dialog_id, 0, 50, 0, selectedMode == 1 ? SharedMediaQuery.MEDIA_FILE : SharedMediaQuery.MEDIA_MUSIC, true, classGuid); } listView.setVisibility(View.VISIBLE); if (sharedMediaData[selectedMode].loading && sharedMediaData[selectedMode].messages.isEmpty()) { @@ -882,18 +927,14 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No cantDeleteMessagesCount++; } actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); - selectedMessagesCountTextView.setText(String.format("%d", selectedFiles.size())); + selectedMessagesCountTextView.setNumber(1, false); if (Build.VERSION.SDK_INT >= 11) { AnimatorSetProxy animatorSet = new AnimatorSetProxy(); ArrayList animators = new ArrayList<>(); for (int i = 0; i < actionModeViews.size(); i++) { View view2 = actionModeViews.get(i); AndroidUtilities.clearDrawableAnimation(view2); - if (i < 1) { - animators.add(ObjectAnimatorProxy.ofFloat(view2, "translationX", -AndroidUtilities.dp(56), 0)); - } else { - animators.add(ObjectAnimatorProxy.ofFloat(view2, "scaleY", 0.1f, 1.0f)); - } + animators.add(ObjectAnimatorProxy.ofFloat(view2, "scaleY", 0.1f, 1.0f)); } animatorSet.playTogether(animators); animatorSet.setDuration(250); @@ -930,7 +971,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (selectedFiles.isEmpty()) { actionBar.hideActionMode(); } else { - selectedMessagesCountTextView.setText(String.format("%d", selectedFiles.size())); + selectedMessagesCountTextView.setNumber(selectedFiles.size(), true); } actionBar.createActionMode().getItem(delete).setVisibility(cantDeleteMessagesCount == 0 ? View.VISIBLE : View.GONE); scrolling = false; @@ -945,12 +986,12 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (selectedMode == 0) { PhotoViewer.getInstance().setParentActivity(getParentActivity()); PhotoViewer.getInstance().openPhoto(sharedMediaData[selectedMode].messages, index, this); - } else if (selectedMode == 1) { + } else if (selectedMode == 1 || selectedMode == 4) { if (view instanceof SharedDocumentCell) { SharedDocumentCell cell = (SharedDocumentCell) view; if (cell.isLoaded()) { if (message.isMusic()) { - if (MediaController.getInstance().setPlaylist(sharedMediaData[1].messages, message)) { + if (MediaController.getInstance().setPlaylist(sharedMediaData[selectedMode].messages, message)) { return; } } @@ -1056,6 +1097,12 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); int rotation = manager.getDefaultDisplay().getRotation(); + if (!AndroidUtilities.isTablet() && ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + selectedMessagesCountTextView.setTextSize(18); + } else { + selectedMessagesCountTextView.setTextSize(20); + } + if (AndroidUtilities.isTablet()) { columnsCount = 4; emptyTextView.setPadding(AndroidUtilities.dp(40), 0, AndroidUtilities.dp(40), AndroidUtilities.dp(128)); @@ -1191,10 +1238,13 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } private class SharedDocumentsAdapter extends BaseSectionsAdapter { - private Context mContext; - public SharedDocumentsAdapter(Context context) { + private Context mContext; + private int currentType; + + public SharedDocumentsAdapter(Context context, int type) { mContext = context; + currentType = type; } @Override @@ -1209,13 +1259,13 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No @Override public int getSectionCount() { - return sharedMediaData[1].sections.size() + (sharedMediaData[1].sections.isEmpty() || sharedMediaData[1].endReached ? 0 : 1); + return sharedMediaData[currentType].sections.size() + (sharedMediaData[currentType].sections.isEmpty() || sharedMediaData[currentType].endReached ? 0 : 1); } @Override public int getCountForSection(int section) { - if (section < sharedMediaData[1].sections.size()) { - return sharedMediaData[1].sectionArrays.get(sharedMediaData[1].sections.get(section)).size() + 1; + if (section < sharedMediaData[currentType].sections.size()) { + return sharedMediaData[currentType].sectionArrays.get(sharedMediaData[currentType].sections.get(section)).size() + 1; } return 1; } @@ -1225,9 +1275,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (convertView == null) { convertView = new GreySectionCell(mContext); } - if (section < sharedMediaData[1].sections.size()) { - String name = sharedMediaData[1].sections.get(section); - ArrayList messageObjects = sharedMediaData[1].sectionArrays.get(name); + if (section < sharedMediaData[currentType].sections.size()) { + String name = sharedMediaData[currentType].sections.get(section); + ArrayList messageObjects = sharedMediaData[currentType].sectionArrays.get(name); MessageObject messageObject = messageObjects.get(0); ((GreySectionCell) convertView).setText(LocaleController.formatterMonthYear.format((long) messageObject.messageOwner.date * 1000).toUpperCase()); } @@ -1236,9 +1286,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No @Override public View getItemView(int section, int position, View convertView, ViewGroup parent) { - if (section < sharedMediaData[1].sections.size()) { - String name = sharedMediaData[1].sections.get(section); - ArrayList messageObjects = sharedMediaData[1].sectionArrays.get(name); + if (section < sharedMediaData[currentType].sections.size()) { + String name = sharedMediaData[currentType].sections.get(section); + ArrayList messageObjects = sharedMediaData[currentType].sectionArrays.get(name); if (position == 0) { if (convertView == null) { convertView = new GreySectionCell(mContext); @@ -1251,7 +1301,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } SharedDocumentCell sharedDocumentCell = (SharedDocumentCell) convertView; MessageObject messageObject = messageObjects.get(position - 1); - sharedDocumentCell.setDocument(messageObject, position != messageObjects.size() || section == sharedMediaData[1].sections.size() - 1 && sharedMediaData[1].loading); + sharedDocumentCell.setDocument(messageObject, position != messageObjects.size() || section == sharedMediaData[currentType].sections.size() - 1 && sharedMediaData[currentType].loading); if (actionBar.isActionModeShowed()) { sharedDocumentCell.setChecked(selectedFiles.containsKey(messageObject.getId()), !scrolling); } else { @@ -1268,7 +1318,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No @Override public int getItemViewType(int section, int position) { - if (section < sharedMediaData[1].sections.size()) { + if (section < sharedMediaData[currentType].sections.size()) { if (position == 0) { return 0; } else { @@ -1446,6 +1496,8 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No req.filter = new TLRPC.TL_inputMessagesFilterDocument(); } else if (currentType == 3) { req.filter = new TLRPC.TL_inputMessagesFilterUrl(); + } else if (currentType == 4) { + req.filter = new TLRPC.TL_inputMessagesFilterAudioDocuments(); } req.q = query; req.peer = MessagesController.getInputPeer(uid); @@ -1511,16 +1563,16 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No @Override public void run() { if (!sharedMediaData[currentType].messages.isEmpty()) { - if (currentType == 1) { + if (currentType == 1 || currentType == 4) { MessageObject messageObject = sharedMediaData[currentType].messages.get(sharedMediaData[currentType].messages.size() - 1); queryServerSearch(query, messageObject.getId()); } else if (currentType == 3) { queryServerSearch(query, 0); } } - if (currentType == 1) { + if (currentType == 1 || currentType == 4) { final ArrayList copy = new ArrayList<>(); - copy.addAll(sharedMediaData[1].messages); + copy.addAll(sharedMediaData[currentType].messages); Utilities.searchQueue.postRunnable(new Runnable() { @Override public void run() { @@ -1536,7 +1588,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No String search[] = new String[1 + (search2 != null ? 1 : 0)]; search[0] = search1; if (search2 != null) { - search[1] = search2; + search[currentType] = search2; } ArrayList resultArray = new ArrayList<>(); @@ -1625,7 +1677,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No @Override public View getView(int i, View view, ViewGroup viewGroup) { - if (currentType == 1) { + if (currentType == 1 || currentType == 4) { if (view == null) { view = new SharedDocumentCell(mContext); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index 57d4d1e76..c170ba744 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -52,6 +52,7 @@ import org.telegram.ui.Components.ColorPickerView; import org.telegram.ui.Components.LayoutHelper; public class NotificationsSettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + private ListView listView; private boolean reseting = false; @@ -186,7 +187,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif listView.setAdapter(new ListAdapter(context)); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override - public void onItemClick(AdapterView adapterView, View view, final int i, long l) { + public void onItemClick(AdapterView adapterView, final View view, final int i, long l) { boolean enabled = false; if (i == messageAlertRow || i == groupAlertRow) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); @@ -356,7 +357,12 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif listView.invalidateViews(); } }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ((TextCheckCell) view).setChecked(true); + } + }); showDialog(builder.create()); } } else if (i == messageLedRow || i == groupLedRow) { @@ -384,13 +390,15 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif public void onClick(DialogInterface dialogInterface, int which) { final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); + TextColorCell textCell = (TextColorCell) view; if (i == messageLedRow) { editor.putInt("MessagesLed", colorPickerView.getColor()); + textCell.setTextAndColor(LocaleController.getString("LedColor", R.string.LedColor), colorPickerView.getColor(), true); } else if (i == groupLedRow) { editor.putInt("GroupLed", colorPickerView.getColor()); + textCell.setTextAndColor(LocaleController.getString("LedColor", R.string.LedColor), colorPickerView.getColor(), true); } editor.commit(); - listView.invalidateViews(); } }); builder.setNeutralButton(LocaleController.getString("LedDisabled", R.string.LedDisabled), new DialogInterface.OnClickListener() { @@ -398,10 +406,13 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif public void onClick(DialogInterface dialog, int which) { final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); + TextColorCell textCell = (TextColorCell) view; if (i == messageLedRow) { editor.putInt("MessagesLed", 0); + textCell.setTextAndColor(LocaleController.getString("LedColor", R.string.LedColor), 0, true); } else if (i == groupLedRow) { editor.putInt("GroupLed", 0); + textCell.setTextAndColor(LocaleController.getString("LedColor", R.string.LedColor), 0, true); } editor.commit(); listView.invalidateViews(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java index a6abe8cd4..a308df84c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -15,6 +15,7 @@ import android.content.res.Configuration; import android.graphics.Typeface; import android.os.Build; import android.os.Vibrator; +import android.support.v4.hardware.fingerprint.FingerprintManagerCompat; import android.text.Editable; import android.text.InputFilter; import android.text.InputType; @@ -76,6 +77,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter private int passcodeRow; private int changePasscodeRow; private int passcodeDetailRow; + private int fingerprintRow; private int autoLockRow; private int autoLockDetailRow; private int rowCount; @@ -394,6 +396,10 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter } }); showDialog(builder.create()); + } else if (i == fingerprintRow) { + UserConfig.useFingerprint = !UserConfig.useFingerprint; + UserConfig.saveConfig(false); + ((TextCheckCell) view).setChecked(UserConfig.useFingerprint); } } }); @@ -440,9 +446,20 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter changePasscodeRow = rowCount++; passcodeDetailRow = rowCount++; if (UserConfig.passcodeHash.length() > 0) { + try { + if (Build.VERSION.SDK_INT >= 23) { + FingerprintManagerCompat fingerprintManager = FingerprintManagerCompat.from(ApplicationLoader.applicationContext); + if (fingerprintManager.isHardwareDetected()) { + fingerprintRow = rowCount++; + } + } + } catch (Throwable e) { + FileLog.e("tmessages", e); + } autoLockRow = rowCount++; autoLockDetailRow = rowCount++; } else { + fingerprintRow = -1; autoLockRow = -1; autoLockDetailRow = -1; } @@ -465,9 +482,8 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter } @Override - public void onOpenAnimationEnd() { - super.onOpenAnimationEnd(); - if (type != 0) { + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen && type != 0) { AndroidUtilities.showKeyboard(passwordEditText); } } @@ -599,7 +615,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter @Override public boolean isEnabled(int i) { - return i == passcodeRow || i == autoLockRow || UserConfig.passcodeHash.length() != 0 && i == changePasscodeRow; + return i == passcodeRow || i == fingerprintRow || i == autoLockRow || UserConfig.passcodeHash.length() != 0 && i == changePasscodeRow; } @Override @@ -634,6 +650,8 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter if (i == passcodeRow) { textCell.setTextAndCheck(LocaleController.getString("Passcode", R.string.Passcode), UserConfig.passcodeHash.length() > 0, true); + } else if (i == fingerprintRow) { + textCell.setTextAndCheck(LocaleController.getString("UnlockFingerprint", R.string.UnlockFingerprint), UserConfig.useFingerprint, true); } } else if (viewType == 1) { if (view == null) { @@ -679,7 +697,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter @Override public int getItemViewType(int i) { - if (i == passcodeRow) { + if (i == passcodeRow || i == fingerprintRow) { return 0; } else if (i == changePasscodeRow || i == autoLockRow) { return 1; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index aad3f361b..309949c36 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -3,7 +3,7 @@ * 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-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java index 34f2b0b97..b4cc7b0cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java @@ -3,7 +3,7 @@ * 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. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -21,6 +21,7 @@ import android.view.View; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Bitmaps; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; @@ -35,7 +36,7 @@ import java.io.File; public class PhotoCropActivity extends BaseFragment { public interface PhotoEditActivityDelegate { - void didFinishEdit(Bitmap bitmap, Bundle args); + void didFinishEdit(Bitmap bitmap); } private class PhotoCropView extends FrameLayout { @@ -315,12 +316,12 @@ public class PhotoCropActivity extends BaseFragment { sizeY = imageToCrop.getHeight() - y; } try { - return Bitmap.createBitmap(imageToCrop, x, y, sizeX, sizeY); + return Bitmaps.createBitmap(imageToCrop, x, y, sizeX, sizeY); } catch (Throwable e) { FileLog.e("tmessags", e); System.gc(); try { - return Bitmap.createBitmap(imageToCrop, x, y, sizeX, sizeY); + return Bitmaps.createBitmap(imageToCrop, x, y, sizeX, sizeY); } catch (Throwable e2) { FileLog.e("tmessages", e2); } @@ -331,8 +332,12 @@ public class PhotoCropActivity extends BaseFragment { @Override protected void onDraw(Canvas canvas) { if (drawable != null) { - drawable.setBounds(bitmapX, bitmapY, bitmapX + bitmapWidth, bitmapY + bitmapHeight); - drawable.draw(canvas); + try { + drawable.setBounds(bitmapX, bitmapY, bitmapX + bitmapWidth, bitmapY + bitmapHeight); + drawable.draw(canvas); + } catch (Throwable e) { + FileLog.e("tmessages", e); + } } canvas.drawRect(bitmapX, bitmapY, bitmapX + bitmapWidth, rectY, halfPaint); canvas.drawRect(bitmapX, rectY, rectX, rectY + rectSizeY, halfPaint); @@ -375,15 +380,6 @@ public class PhotoCropActivity extends BaseFragment { super(args); } - public PhotoCropActivity(Bundle args, Bitmap bitmap, String key) { - super(args); - imageToCrop = bitmap; - bitmapKey = key; - if (imageToCrop != null && key != null) { - ImageLoader.getInstance().incrementUseCount(key); - } - } - @Override public boolean onFragmentCreate() { swipeBackEnabled = false; @@ -418,7 +414,6 @@ public class PhotoCropActivity extends BaseFragment { @Override public void onFragmentDestroy() { super.onFragmentDestroy(); - drawable = null; if (bitmapKey != null) { if (ImageLoader.getInstance().decrementUseCount(bitmapKey) && !ImageLoader.getInstance().isInCache(bitmapKey)) { bitmapKey = null; @@ -428,6 +423,7 @@ public class PhotoCropActivity extends BaseFragment { imageToCrop.recycle(); imageToCrop = null; } + drawable = null; } @Override @@ -448,7 +444,7 @@ public class PhotoCropActivity extends BaseFragment { if (bitmap == imageToCrop) { sameBitmap = true; } - delegate.didFinishEdit(bitmap, getArguments()); + delegate.didFinishEdit(bitmap); doneButtonPressed = true; } finishFragment(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index 984b77f84..3961e1bd6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -34,6 +34,7 @@ import android.widget.TextView; import org.json.JSONArray; import org.json.JSONObject; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessagesStorage; @@ -294,6 +295,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (i < 0 || i >= arrayList.size()) { return; } + if (searchItem != null) { + AndroidUtilities.hideKeyboard(searchItem.getSearchField()); + } PhotoViewer.getInstance().setParentActivity(getParentActivity()); PhotoViewer.getInstance().openPhotoForSelect(arrayList, i, singlePhoto ? 1 : 0, PhotoPickerActivity.this, chatActivity); } @@ -498,9 +502,18 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; object.viewY = coords[1] - AndroidUtilities.statusBarHeight; + if (Build.VERSION.SDK_INT < 11) { + float scale = ViewProxy.getScaleX(cell.photoImage); + if (scale != 1) { + int width = cell.photoImage.getMeasuredWidth(); + object.viewX += (width - width * scale) / 2; + object.viewY += (width - width * scale) / 2; + } + } object.parentView = listView; object.imageReceiver = cell.photoImage.getImageReceiver(); object.thumb = object.imageReceiver.getBitmap(); + object.scale = ViewProxy.getScaleX(cell.photoImage); cell.checkBox.setVisibility(View.GONE); return object; } @@ -646,7 +659,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen View view = listView.getChildAt(a); int num = (Integer) view.getTag(); if (num == index) { - ((PhotoPickerPhotoCell) view).checkBox.setChecked(add, false); + ((PhotoPickerPhotoCell) view).setChecked(add, false); break; } } @@ -655,9 +668,10 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } @Override - public void cancelButtonPressed() { + public boolean cancelButtonPressed() { delegate.actionButtonPressed(true); finishFragment(); + return true; } @Override @@ -692,9 +706,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } @Override - public void onOpenAnimationEnd() { - super.onOpenAnimationEnd(); - if (searchItem != null) { + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen && searchItem != null) { AndroidUtilities.showKeyboard(searchItem.getSearchField()); } } @@ -1016,7 +1029,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } else { selectedPhotos.put(photoEntry.imageId, photoEntry); } - ((PhotoPickerPhotoCell) v.getParent()).checkBox.setChecked(selectedPhotos.containsKey(photoEntry.imageId), true); + ((PhotoPickerPhotoCell) v.getParent()).setChecked(selectedPhotos.containsKey(photoEntry.imageId), true); } else { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); MediaController.SearchImage photoEntry; @@ -1033,7 +1046,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } else { selectedWebPhotos.put(photoEntry.id, photoEntry); } - ((PhotoPickerPhotoCell) v.getParent()).checkBox.setChecked(selectedWebPhotos.containsKey(photoEntry.id), true); + ((PhotoPickerPhotoCell) v.getParent()).setChecked(selectedWebPhotos.containsKey(photoEntry.id), true); } pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); delegate.selectedPhotosChanged(); @@ -1062,7 +1075,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } else { imageView.setImageResource(R.drawable.nophotos); } - cell.checkBox.setChecked(selectedPhotos.containsKey(photoEntry.imageId), false); + cell.setChecked(selectedPhotos.containsKey(photoEntry.imageId), false); showing = PhotoViewer.getInstance().isShowingImage(photoEntry.path); } else { MediaController.SearchImage photoEntry; @@ -1078,7 +1091,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } else { imageView.setImageResource(R.drawable.nophotos); } - cell.checkBox.setChecked(selectedWebPhotos.containsKey(photoEntry.id), false); + cell.setChecked(selectedWebPhotos.containsKey(photoEntry.id), false); showing = PhotoViewer.getInstance().isShowingImage(photoEntry.thumbUrl); } imageView.getImageReceiver().setVisible(!showing, true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index f484f9f42..c2f3e89a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -1,19 +1,21 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; +import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; @@ -406,6 +408,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public int index; public int size; public int radius; + public int clipBottomAddition; + public float scale = 1.0f; } public static class EmptyPhotoViewerProvider implements PhotoViewerProvider { @@ -440,8 +444,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } @Override - public void cancelButtonPressed() { - + public boolean cancelButtonPressed() { + return true; } @Override @@ -473,7 +477,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat void setPhotoChecked(int index); - void cancelButtonPressed(); + boolean cancelButtonPressed(); void sendButtonPressed(int index); @@ -733,7 +737,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (needSearchImageInArr && isFirstLoading) { isFirstLoading = false; loadingMoreImages = true; - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, 0, SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 80, 0, SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); } else if (!imagesArr.isEmpty()) { if (opennedFromMedia) { actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, currentIndex + 1, totalImagesCount)); @@ -798,9 +802,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (!endReached || !arr.isEmpty() && added != 0) { loadingMoreImages = true; if (opennedFromMedia) { - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, imagesArrTemp.get(imagesArrTemp.size() - 1).getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 80, imagesArrTemp.get(imagesArrTemp.size() - 1).getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); } else { - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, imagesArrTemp.get(0).getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 80, imagesArrTemp.get(0).getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); } } } @@ -856,6 +860,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat scroller = new Scroller(activity); windowView = new FrameLayoutTouchListener(activity) { + @Override public boolean dispatchKeyEventPreIme(KeyEvent event) { if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { @@ -906,6 +911,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } closePhoto(true, false); } else if (id == gallery_menu_save) { + if (Build.VERSION.SDK_INT >= 23 && parentActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); + return; + } + File f = null; if (currentMessageObject != null) { f = FileLoader.getPathToMessage(currentMessageObject.messageOwner); @@ -1218,8 +1228,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override public void onClick(View view) { if (placeProvider != null) { - placeProvider.cancelButtonPressed(); - closePhoto(false, false); + closePhoto(!placeProvider.cancelButtonPressed(), false); } } }); @@ -1968,7 +1977,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat currentActionBarAnimation.addListener(new AnimatorListenerAdapterProxy() { @Override public void onAnimationEnd(Object animation) { - if (currentActionBarAnimation.equals(animation)) { + if (currentActionBarAnimation != null && currentActionBarAnimation.equals(animation)) { actionBar.setVisibility(View.GONE); if (canShowBottom) { bottomLayout.clearAnimation(); @@ -2382,14 +2391,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (opennedFromMedia) { if (imagesArr.size() < totalImagesCount && !loadingMoreImages && currentIndex > imagesArr.size() - 5) { MessageObject lastMessage = imagesArr.get(imagesArr.size() - 1); - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, lastMessage.getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 80, lastMessage.getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); loadingMoreImages = true; } actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, currentIndex + 1, totalImagesCount)); } else { if (imagesArr.size() < totalImagesCount && !loadingMoreImages && currentIndex < 5) { MessageObject lastMessage = imagesArr.get(0); - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, lastMessage.getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 80, lastMessage.getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); loadingMoreImages = true; } actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, (totalImagesCount - imagesArr.size()) + currentIndex + 1, totalImagesCount)); @@ -2803,19 +2812,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } try { - if (photos != null) { - windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; - windowLayoutParams.flags = 0; - windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; - windowView.setFocusable(true); - containerView.setFocusable(true); - } else { - windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; - windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; - windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED; - windowView.setFocusable(false); - containerView.setFocusable(false); - } + windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED; + windowView.setFocusable(false); + containerView.setFocusable(false); wm.addView(windowView, windowLayoutParams); } catch (Exception e) { FileLog.e("tmessages", e); @@ -2859,13 +2860,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ViewProxy.setAlpha(animatingImageView, 1.0f); ViewProxy.setPivotX(animatingImageView, 0.0f); ViewProxy.setPivotY(animatingImageView, 0.0f); - ViewProxy.setScaleX(animatingImageView, 1.0f); - ViewProxy.setScaleY(animatingImageView, 1.0f); - ViewProxy.setTranslationX(animatingImageView, object.viewX + drawRegion.left); - ViewProxy.setTranslationY(animatingImageView, object.viewY + drawRegion.top); + ViewProxy.setScaleX(animatingImageView, object.scale); + ViewProxy.setScaleY(animatingImageView, object.scale); + ViewProxy.setTranslationX(animatingImageView, object.viewX + drawRegion.left * object.scale); + ViewProxy.setTranslationY(animatingImageView, object.viewY + drawRegion.top * object.scale); final ViewGroup.LayoutParams layoutParams = animatingImageView.getLayoutParams(); - layoutParams.width = drawRegion.right - drawRegion.left; - layoutParams.height = drawRegion.bottom - drawRegion.top; + layoutParams.width = (drawRegion.right - drawRegion.left); + layoutParams.height = (drawRegion.bottom - drawRegion.top); animatingImageView.setLayoutParams(layoutParams); float scaleX = (float) AndroidUtilities.displaySize.x / layoutParams.width; @@ -2884,7 +2885,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (clipTop < 0) { clipTop = 0; } - int clipBottom = (object.viewY + drawRegion.top + layoutParams.height) - (coords2[1] + object.parentView.getHeight() - AndroidUtilities.statusBarHeight); + int clipBottom = (object.viewY + drawRegion.top + layoutParams.height) - (coords2[1] + object.parentView.getHeight() - AndroidUtilities.statusBarHeight) + object.clipBottomAddition; if (clipBottom < 0) { clipBottom = 0; } @@ -2895,9 +2896,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animationValues[0][1] = ViewProxy.getScaleY(animatingImageView); animationValues[0][2] = ViewProxy.getTranslationX(animatingImageView); animationValues[0][3] = ViewProxy.getTranslationY(animatingImageView); - animationValues[0][4] = clipHorizontal; - animationValues[0][5] = clipTop; - animationValues[0][6] = clipBottom; + animationValues[0][4] = clipHorizontal * object.scale; + animationValues[0][5] = clipTop * object.scale; + animationValues[0][6] = clipBottom * object.scale; animationValues[0][7] = animatingImageView.getRadius(); animationValues[1][0] = scale; @@ -2940,6 +2941,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (hideAfterAnimation != null) { hideAfterAnimation.imageReceiver.setVisible(false, true); } + if (photos != null) { + windowLayoutParams.flags = 0; + windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; + WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); + wm.updateViewLayout(windowView, windowLayoutParams); + windowView.setFocusable(true); + containerView.setFocusable(true); + } } }; @@ -2983,6 +2992,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } }; } else { + if (photos != null) { + windowLayoutParams.flags = 0; + windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; + wm.updateViewLayout(windowView, windowLayoutParams); + windowView.setFocusable(true); + containerView.setFocusable(true); + } + backgroundDrawable.setAlpha(255); ViewProxy.setAlpha(containerView, 1.0f); onPhotoShow(messageObject, fileLocation, messages, photos, index, object); @@ -3090,7 +3107,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (clipTop < 0) { clipTop = 0; } - int clipBottom = (object.viewY + drawRegion.top + (drawRegion.bottom - drawRegion.top)) - (coords2[1] + object.parentView.getHeight() - AndroidUtilities.statusBarHeight); + int clipBottom = (object.viewY + drawRegion.top + (drawRegion.bottom - drawRegion.top)) - (coords2[1] + object.parentView.getHeight() - AndroidUtilities.statusBarHeight) + object.clipBottomAddition; if (clipBottom < 0) { clipBottom = 0; } @@ -3107,13 +3124,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animationValues[0][6] = 0; animationValues[0][7] = 0; - animationValues[1][0] = 1; - animationValues[1][1] = 1; - animationValues[1][2] = object.viewX + drawRegion.left; - animationValues[1][3] = object.viewY + drawRegion.top; - animationValues[1][4] = clipHorizontal; - animationValues[1][5] = clipTop; - animationValues[1][6] = clipBottom; + animationValues[1][0] = object.scale; + animationValues[1][1] = object.scale; + animationValues[1][2] = object.viewX + drawRegion.left * object.scale; + animationValues[1][3] = object.viewY + drawRegion.top * object.scale; + animationValues[1][4] = clipHorizontal * object.scale; + animationValues[1][5] = clipTop * object.scale; + animationValues[1][6] = clipBottom * object.scale; animationValues[1][7] = object.radius; animatorSet.playTogether( diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index 9c0927b07..9b5fc2f50 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -1,19 +1,25 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; +import android.annotation.TargetApi; import android.app.Activity; +import android.app.AlertDialog; import android.app.KeyguardManager; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.PowerManager; import android.text.TextUtils; @@ -76,6 +82,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC private ViewGroup centerView; private ViewGroup leftView; private ViewGroup rightView; + private RelativeLayout popupContainer; private ArrayList textViews = new ArrayList<>(); private ArrayList imageViews = new ArrayList<>(); private ArrayList audioViews = new ArrayList<>(); @@ -195,6 +202,8 @@ public class PopupNotificationActivity extends Activity implements NotificationC } if (chatActivityEnterView.isPopupView(child)) { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getLayoutParams().height, MeasureSpec.EXACTLY)); + } else if (chatActivityEnterView.isRecordCircle(child)) { + measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); } else { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), heightSize + AndroidUtilities.dp(2)), MeasureSpec.EXACTLY)); } @@ -255,6 +264,9 @@ public class PopupNotificationActivity extends Activity implements NotificationC } if (chatActivityEnterView.isPopupView(child)) { childTop = paddingBottom != 0 ? getMeasuredHeight() - paddingBottom : getMeasuredHeight(); + } else if (chatActivityEnterView.isRecordCircle(child)) { + childTop = popupContainer.getTop() + popupContainer.getMeasuredHeight() - child.getMeasuredHeight() - lp.bottomMargin; + childLeft = popupContainer.getLeft() + popupContainer.getMeasuredWidth() - child.getMeasuredWidth() - lp.rightMargin; } child.layout(childLeft, childTop, childLeft + width, childTop + height); } @@ -268,7 +280,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC RelativeLayout relativeLayout = new RelativeLayout(this); contentView.addView(relativeLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - RelativeLayout popupContainer = new RelativeLayout(this); + popupContainer = new RelativeLayout(this); popupContainer.setBackgroundColor(0xffffffff); relativeLayout.addView(popupContainer, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, 240, 12, 0, 12, 0, RelativeLayout.CENTER_IN_PARENT)); @@ -426,6 +438,34 @@ public class PopupNotificationActivity extends Activity implements NotificationC handleIntent(intent); } + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == 3) { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("PermissionNoAudio", R.string.PermissionNoAudio)); + builder.setNegativeButton(LocaleController.getString("PermissionOpenSettings", R.string.PermissionOpenSettings), new DialogInterface.OnClickListener() { + @TargetApi(Build.VERSION_CODES.GINGERBREAD) + @Override + public void onClick(DialogInterface dialog, int which) { + try { + Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + ApplicationLoader.applicationContext.getPackageName())); + startActivity(intent); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.show(); + } + } + private void switchToNextMessage() { if (NotificationsController.getInstance().popupMessages.size() > 1) { if (currentMessageNum < NotificationsController.getInstance().popupMessages.size() - 1) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 57ad7f2db..958ea0020 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index ab7f48277..ffe035bda 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -18,26 +18,23 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; -import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Outline; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; -import android.widget.AbsListView; -import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; @@ -54,6 +51,8 @@ import org.telegram.messenger.UserObject; import org.telegram.messenger.query.BotQuery; import org.telegram.messenger.query.SharedMediaQuery; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.support.widget.LinearLayoutManager; +import org.telegram.messenger.support.widget.RecyclerView; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.messenger.ContactsController; @@ -64,7 +63,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.MessageObject; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.ui.Adapters.BaseFragmentAdapter; +import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.messenger.AnimationCompat.ViewProxy; import org.telegram.ui.Cells.AddMemberCell; import org.telegram.ui.Cells.DividerCell; @@ -82,6 +81,7 @@ import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Components.IdenticonDrawable; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.Collections; @@ -91,19 +91,28 @@ import java.util.concurrent.Semaphore; public class ProfileActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.MessagesActivityDelegate, PhotoViewer.PhotoViewerProvider { - private ListView listView; + private RecyclerListView listView; + private LinearLayoutManager layoutManager; private ListAdapter listAdapter; private BackupImageView avatarImage; private TextView nameTextView; private TextView onlineTextView; private ImageView writeButton; private AnimatorSetProxy writeButtonAnimation; + private View extraHeightView; + private View shadowView; private int user_id; private int chat_id; private long dialog_id; private boolean creatingChat; private boolean userBlocked; + private boolean openAnimationInProgress; + private boolean playProfileAnimation; + private int extraHeight; + private int initialAnimationExtraHeight; + private float animationProgress; + private AvatarUpdater avatarUpdater; private TLRPC.ChatFull info; private TLRPC.TL_chatParticipant selectedUser; @@ -175,6 +184,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatUpdated); NotificationCenter.getInstance().addObserver(this, NotificationCenter.blockedUsersDidLoaded); NotificationCenter.getInstance().addObserver(this, NotificationCenter.botInfoDidLoaded); + if (currentEncryptedChat != null) { + NotificationCenter.getInstance().addObserver(this, NotificationCenter.didReceivedNewMessages); + } userBlocked = MessagesController.getInstance().blockedUsers.contains(user_id); if ((user.flags & TLRPC.USER_FLAG_BOT) != 0) { BotQuery.loadBotInfo(user.id, true, classGuid); @@ -246,6 +258,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. NotificationCenter.getInstance().removeObserver(this, NotificationCenter.blockedUsersDidLoaded); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.botInfoDidLoaded); MessagesController.getInstance().cancelLoadFullUser(user_id); + if (currentEncryptedChat != null) { + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didReceivedNewMessages); + } } else if (chat_id != 0) { NotificationCenter.getInstance().removeObserver(this, NotificationCenter.chatInfoDidLoaded); avatarUpdater.clear(); @@ -256,8 +271,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public View createView(Context context) { actionBar.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id)); actionBar.setItemsBackground(AvatarDrawable.getButtonColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id)); - actionBar.setBackButtonImage(R.drawable.ic_ab_back); - actionBar.setExtraHeight(AndroidUtilities.dp(88), false); + actionBar.setBackButtonDrawable(new BackDrawable(false)); + actionBar.setCastShadows(false); + actionBar.setAddToContainer(false); + hasOwnBackground = true; + extraHeight = 88; if (AndroidUtilities.isTablet()) { actionBar.setOccupyStatusBar(false); } @@ -307,11 +325,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. TLRPC.User user = MessagesController.getInstance().getUser(user_id); Bundle args = new Bundle(); args.putInt("user_id", user.id); + args.putBoolean("addContact", true); presentFragment(new ContactAddActivity(args)); } else if (id == share_contact) { Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", 1); + args.putString("selectAlertString", LocaleController.getString("SendMessagesTo", R.string.SendMessagesTo)); + args.putString("selectAlertStringGroup", LocaleController.getString("SendMessagesToGroup", R.string.SendMessagesToGroup)); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ProfileActivity.this); presentFragment(fragment); @@ -414,123 +435,38 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. listAdapter = new ListAdapter(context); - fragmentView = new FrameLayout(context) { - @Override - protected boolean drawChild(@NonNull Canvas canvas, @NonNull View child, long drawingTime) { - if (child == listView) { - boolean result = super.drawChild(canvas, child, drawingTime); - if (parentLayout != null) { - int actionBarHeight = 0; - int childCount = getChildCount(); - for (int a = 0; a < childCount; a++) { - View view = getChildAt(a); - if (view == child) { - continue; - } - if (view instanceof ActionBar && view.getVisibility() == VISIBLE) { - if (((ActionBar) view).getCastShadows()) { - actionBarHeight = view.getMeasuredHeight(); - } - break; - } - } - parentLayout.drawHeaderShadow(canvas, actionBarHeight); - } - return result; - } else { - return super.drawChild(canvas, child, drawingTime); - } - } - }; + fragmentView = new FrameLayout(context); FrameLayout frameLayout = (FrameLayout) fragmentView; - avatarImage = new BackupImageView(context); - avatarImage.setRoundRadius(AndroidUtilities.dp(30)); - actionBar.addView(avatarImage); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) avatarImage.getLayoutParams(); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM; - layoutParams.width = AndroidUtilities.dp(60); - layoutParams.height = AndroidUtilities.dp(60); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(17); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(17) : 0; - layoutParams.bottomMargin = AndroidUtilities.dp(22); - avatarImage.setLayoutParams(layoutParams); - avatarImage.setOnClickListener(new View.OnClickListener() { + listView = new RecyclerListView(context) { @Override - public void onClick(View v) { - if (user_id != 0) { - TLRPC.User user = MessagesController.getInstance().getUser(user_id); - if (user.photo != null && user.photo.photo_big != null) { - PhotoViewer.getInstance().setParentActivity(getParentActivity()); - PhotoViewer.getInstance().openPhoto(user.photo.photo_big, ProfileActivity.this); - } - } else if (chat_id != 0) { - TLRPC.Chat chat = MessagesController.getInstance().getChat(chat_id); - if (chat.photo != null && chat.photo.photo_big != null) { - PhotoViewer.getInstance().setParentActivity(getParentActivity()); - PhotoViewer.getInstance().openPhoto(chat.photo.photo_big, ProfileActivity.this); - } - } + public boolean hasOverlappingRendering() { + return false; } - }); - - nameTextView = new TextView(context); - nameTextView.setTextColor(0xffffffff); - nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - nameTextView.setLines(1); - nameTextView.setMaxLines(1); - nameTextView.setSingleLine(true); - nameTextView.setEllipsize(TextUtils.TruncateAt.END); - nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - actionBar.addView(nameTextView); - layoutParams = (FrameLayout.LayoutParams) nameTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 97); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 97 : 16); - layoutParams.bottomMargin = AndroidUtilities.dp(51); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM; - nameTextView.setLayoutParams(layoutParams); - - onlineTextView = new TextView(context); - onlineTextView.setTextColor(AvatarDrawable.getProfileTextColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id)); - onlineTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - onlineTextView.setLines(1); - onlineTextView.setMaxLines(1); - onlineTextView.setSingleLine(true); - onlineTextView.setEllipsize(TextUtils.TruncateAt.END); - onlineTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - actionBar.addView(onlineTextView); - layoutParams = (FrameLayout.LayoutParams) onlineTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 97); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 97 : 16); - layoutParams.bottomMargin = AndroidUtilities.dp(30); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM; - onlineTextView.setLayoutParams(layoutParams); - - listView = new ListView(context); - listView.setDivider(null); - listView.setDividerHeight(0); + }; + listView.setBackgroundColor(0xffffffff); listView.setVerticalScrollBarEnabled(false); - AndroidUtilities.setListViewEdgeEffectColor(listView, AvatarDrawable.getProfileBackColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id)); - frameLayout.addView(listView); - layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.gravity = Gravity.TOP; - listView.setLayoutParams(layoutParams); + listView.setItemAnimator(null); + listView.setLayoutAnimation(null); + layoutManager = new LinearLayoutManager(context) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + }; + layoutManager.setOrientation(LinearLayoutManager.VERTICAL); + listView.setLayoutManager(layoutManager); + listView.setGlowColor(AvatarDrawable.getProfileBackColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id)); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); listView.setAdapter(listAdapter); - listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { @Override - public void onItemClick(AdapterView adapterView, View view, final int i, long l) { + public void onItemClick(View view, final int position) { if (getParentActivity() == null) { return; } - if (i == sharedMediaRow) { + if (position == sharedMediaRow) { Bundle args = new Bundle(); if (user_id != 0) { args.putLong("dialog_id", dialog_id != 0 ? dialog_id : user_id); @@ -538,13 +474,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. args.putLong("dialog_id", -chat_id); } presentFragment(new MediaActivity(args)); - } else if (i == settingsKeyRow) { + } else if (position == settingsKeyRow) { Bundle args = new Bundle(); args.putInt("chat_id", (int) (dialog_id >> 32)); presentFragment(new IdenticonActivity(args)); - } else if (i == settingsTimerRow) { + } else if (position == settingsTimerRow) { showDialog(AndroidUtilities.buildTTLAlert(getParentActivity(), currentEncryptedChat).create()); - } else if (i == settingsNotificationsRow) { + } else if (position == settingsNotificationsRow) { Bundle args = new Bundle(); if (user_id != 0) { args.putLong("dialog_id", dialog_id == 0 ? user_id : dialog_id); @@ -552,7 +488,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. args.putLong("dialog_id", -chat_id); } presentFragment(new ProfileNotificationsActivity(args)); - } else if (i == startSecretChatRow) { + } else if (position == startSecretChatRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setMessage(LocaleController.getString("AreYouSureSecretChat", R.string.AreYouSureSecretChat)); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); @@ -565,7 +501,33 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); - } else if (i == phoneRow) { + } else if (position == usernameRow) { + final TLRPC.User user = MessagesController.getInstance().getUser(user_id); + if (user == null || user.username == null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setItems(new CharSequence[]{LocaleController.getString("Copy", R.string.Copy)}, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (i == 0) { + try { + if (Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { + android.text.ClipboardManager clipboard = (android.text.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + clipboard.setText("@" + user.username); + } else { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText("label", "@" + user.username); + clipboard.setPrimaryClip(clip); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } + }); + showDialog(builder.create()); + } else if (position == phoneRow) { final TLRPC.User user = MessagesController.getInstance().getUser(user_id); if (user == null || user.phone == null || user.phone.length() == 0 || getParentActivity() == null) { return; @@ -600,17 +562,17 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); showDialog(builder.create()); - } else if (i > emptyRowChat2 && i < membersEndRow) { - int user_id = info.participants.participants.get(sortedUsers.get(i - emptyRowChat2 - 1)).user_id; + } else if (position > emptyRowChat2 && position < membersEndRow) { + int user_id = info.participants.participants.get(sortedUsers.get(position - emptyRowChat2 - 1)).user_id; if (user_id == UserConfig.getClientUserId()) { return; } Bundle args = new Bundle(); args.putInt("user_id", user_id); presentFragment(new ProfileActivity(args)); - } else if (i == addMemberRow) { + } else if (position == addMemberRow) { openAddMember(); - } else if (i == channelNameRow) { + } else if (position == channelNameRow) { try { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); @@ -619,7 +581,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } catch (Exception e) { FileLog.e("tmessages", e); } - } else if (i == leaveChannelRow) { + } else if (position == leaveChannelRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setMessage(ChatObject.isChannel(chat_id) ? LocaleController.getString("ChannelLeaveAlert", R.string.ChannelLeaveAlert) : LocaleController.getString("AreYouSureDeleteAndExit", R.string.AreYouSureDeleteAndExit)); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); @@ -631,18 +593,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); - } else if (i == membersRow || i == blockedUsersRow || i == managementRow) { + } else if (position == membersRow || position == blockedUsersRow || position == managementRow) { Bundle args = new Bundle(); args.putInt("chat_id", chat_id); - if (i == blockedUsersRow) { + if (position == blockedUsersRow) { args.putInt("type", 0); - } else if (i == managementRow) { + } else if (position == managementRow) { args.putInt("type", 1); - } else if (i == membersRow) { + } else if (position == membersRow) { args.putInt("type", 2); } presentFragment(new ChannelUsersActivity(args)); - } else if (i == channelInfoRow) { + } else if (position == channelInfoRow) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setItems(new CharSequence[]{LocaleController.getString("Copy", R.string.Copy)}, new DialogInterface.OnClickListener() { @Override @@ -665,16 +627,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } }); + if (chat_id != 0) { - listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + listView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListener() { @Override - public boolean onItemLongClick(AdapterView adapterView, View view, int i, long l) { - if (i > emptyRowChat2 && i < membersEndRow) { + public boolean onItemClick(View view, int position) { + if (position > emptyRowChat2 && position < membersEndRow) { if (getParentActivity() == null) { return false; } - - TLRPC.TL_chatParticipant user = info.participants.participants.get(sortedUsers.get(i - emptyRowChat2 - 1)); + TLRPC.TL_chatParticipant user = info.participants.participants.get(sortedUsers.get(position - emptyRowChat2 - 1)); if (user.user_id == UserConfig.getClientUserId()) { return false; } @@ -695,7 +657,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); showDialog(builder.create()); - return true; } return false; @@ -710,6 +671,63 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. frameLayout.addView(actionBar); + extraHeightView = new View(context); + ViewProxy.setPivotY(extraHeightView, 0); + extraHeightView.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id)); + frameLayout.addView(extraHeightView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 88)); + + shadowView = new View(context); + shadowView.setBackgroundResource(R.drawable.header_shadow); + frameLayout.addView(shadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3)); + + avatarImage = new BackupImageView(context); + avatarImage.setRoundRadius(AndroidUtilities.dp(21)); + ViewProxy.setPivotX(avatarImage, 0); + ViewProxy.setPivotY(avatarImage, 0); + frameLayout.addView(avatarImage, LayoutHelper.createFrame(42, 42, Gravity.TOP | Gravity.LEFT, 64, 0, 0, 0)); + avatarImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (user_id != 0) { + TLRPC.User user = MessagesController.getInstance().getUser(user_id); + if (user.photo != null && user.photo.photo_big != null) { + PhotoViewer.getInstance().setParentActivity(getParentActivity()); + PhotoViewer.getInstance().openPhoto(user.photo.photo_big, ProfileActivity.this); + } + } else if (chat_id != 0) { + TLRPC.Chat chat = MessagesController.getInstance().getChat(chat_id); + if (chat.photo != null && chat.photo.photo_big != null) { + PhotoViewer.getInstance().setParentActivity(getParentActivity()); + PhotoViewer.getInstance().openPhoto(chat.photo.photo_big, ProfileActivity.this); + } + } + } + }); + + nameTextView = new TextView(context); + nameTextView.setTextColor(0xffffffff); + nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + nameTextView.setLines(1); + nameTextView.setMaxLines(1); + nameTextView.setSingleLine(true); + nameTextView.setEllipsize(TextUtils.TruncateAt.END); + nameTextView.setGravity(Gravity.LEFT); + nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + nameTextView.setCompoundDrawablePadding(AndroidUtilities.dp(4)); + ViewProxy.setPivotX(nameTextView, 0); + ViewProxy.setPivotY(nameTextView, 0); + frameLayout.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 48, 0)); + + onlineTextView = new TextView(context); + onlineTextView.setTextColor(AvatarDrawable.getProfileTextColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id)); + onlineTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + onlineTextView.setLines(1); + onlineTextView.setMaxLines(1); + onlineTextView.setSingleLine(true); + onlineTextView.setEllipsize(TextUtils.TruncateAt.END); + onlineTextView.setGravity(Gravity.LEFT); + frameLayout.addView(onlineTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 48, 0)); + if (user_id != 0 || chat_id >= 0 && !ChatObject.isLeftFromChat(currentChat)) { writeButton = new ImageView(context); writeButton.setBackgroundResource(R.drawable.floating_user_states); @@ -724,7 +742,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. writeButton.setImageResource(R.drawable.floating_camera); } } - frameLayout.addView(writeButton); + frameLayout.addView(writeButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.TOP, 0, 0, 16, 0)); if (Build.VERSION.SDK_INT >= 21) { StateListAnimator animator = new StateListAnimator(); animator.addState(new int[]{android.R.attr.state_pressed}, ObjectAnimator.ofFloat(writeButton, "translationZ", AndroidUtilities.dp(2), AndroidUtilities.dp(4)).setDuration(200)); @@ -738,13 +756,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); } - layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? 16 : 0); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? 0 : 16); - layoutParams.gravity = (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT); - writeButton.setLayoutParams(layoutParams); writeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -752,15 +763,19 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return; } if (user_id != 0) { - TLRPC.User user = MessagesController.getInstance().getUser(user_id); - if (user == null || user instanceof TLRPC.TL_userEmpty) { - return; + if (playProfileAnimation && parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2) instanceof ChatActivity) { + finishFragment(); + } else { + TLRPC.User user = MessagesController.getInstance().getUser(user_id); + if (user == null || user instanceof TLRPC.TL_userEmpty) { + return; + } + NotificationCenter.getInstance().removeObserver(ProfileActivity.this, NotificationCenter.closeChats); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); + Bundle args = new Bundle(); + args.putInt("user_id", user_id); + presentFragment(new ChatActivity(args), true); } - NotificationCenter.getInstance().removeObserver(ProfileActivity.this, NotificationCenter.closeChats); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); - Bundle args = new Bundle(); - args.putInt("user_id", user_id); - presentFragment(new ChatActivity(args), true); } else if (chat_id != 0) { if (ChatObject.isChannel(currentChat) && (currentChat.flags & TLRPC.CHAT_FLAG_ADMIN) == 0) { NotificationCenter.getInstance().removeObserver(ProfileActivity.this, NotificationCenter.closeChats); @@ -796,15 +811,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); } + needLayout(); - listView.setOnScrollListener(new AbsListView.OnScrollListener() { + listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); } @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { checkListViewScroll(); } }); @@ -868,17 +884,17 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } private void checkListViewScroll() { - if (listView.getChildCount() == 0) { + if (listView.getChildCount() == 0 || openAnimationInProgress) { return; } int height = 0; View child = listView.getChildAt(0); if (child != null) { - if (listView.getFirstVisiblePosition() == 0) { + if (layoutManager.findFirstVisibleItemPosition() == 0) { height = AndroidUtilities.dp(88) + (child.getTop() < 0 ? child.getTop() : 0); } - if (actionBar.getExtraHeight() != height) { - actionBar.setExtraHeight(height, true); + if (extraHeight != height) { + extraHeight = height; needLayout(); } } @@ -886,103 +902,102 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private void needLayout() { FrameLayout.LayoutParams layoutParams; - if (listView != null) { + int newTop = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight(); + if (listView != null && !openAnimationInProgress) { layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight(); - listView.setLayoutParams(layoutParams); + if (layoutParams.topMargin != newTop) { + layoutParams.topMargin = newTop; + listView.setLayoutParams(layoutParams); + ViewProxy.setTranslationY(extraHeightView, newTop); + } } if (avatarImage != null) { - float diff = actionBar.getExtraHeight() / (float)AndroidUtilities.dp(88); - float diffm = 1.0f - diff; - - int avatarSize = 42 + (int)(18 * diff); - int avatarX = 17 + (int)(47 * diffm); - int avatarY = AndroidUtilities.dp(22) - (int)((AndroidUtilities.dp(22) - (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff)); - int nameX = 97 + (int)(21 * diffm); - int nameEndX = 16 + (int)(32 * diffm); - int nameY = avatarY + AndroidUtilities.dp(29 - 10 * diffm); - int statusY = avatarY + AndroidUtilities.dp(8 - 7 * diffm); - float scale = 1.0f - 0.12f * diffm; + float diff = extraHeight / (float) AndroidUtilities.dp(88); + ViewProxy.setScaleY(extraHeightView, diff); + ViewProxy.setTranslationY(shadowView, newTop + extraHeight); + listView.setTopGlowOffset(extraHeight); if (writeButton != null) { - layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams(); - layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f); - writeButton.setLayoutParams(layoutParams); - /*ViewProxy.setAlpha(writeButton, diff); - writeButton.setVisibility(diff <= 0.02 ? View.GONE : View.VISIBLE); - if (writeButton.getVisibility() == View.GONE) { - writeButton.clearAnimation(); - }*/ - final boolean setVisible = diff > 0.2f; - boolean currentVisible = writeButton.getTag() == null; - if (setVisible != currentVisible) { - if (setVisible) { - writeButton.setTag(null); - writeButton.setVisibility(View.VISIBLE); - } else { - writeButton.setTag(0); - } - if (writeButtonAnimation != null) { - AnimatorSetProxy old = writeButtonAnimation; - writeButtonAnimation = null; - old.cancel(); - } - writeButtonAnimation = new AnimatorSetProxy(); - if (setVisible) { - writeButtonAnimation.setInterpolator(new DecelerateInterpolator()); - writeButtonAnimation.playTogether( - ObjectAnimatorProxy.ofFloat(writeButton, "scaleX", 1.0f), - ObjectAnimatorProxy.ofFloat(writeButton, "scaleY", 1.0f), - ObjectAnimatorProxy.ofFloat(writeButton, "alpha", 1.0f) - ); - } else { - writeButtonAnimation.setInterpolator(new AccelerateInterpolator()); - writeButtonAnimation.playTogether( - ObjectAnimatorProxy.ofFloat(writeButton, "scaleX", 0.2f), - ObjectAnimatorProxy.ofFloat(writeButton, "scaleY", 0.2f), - ObjectAnimatorProxy.ofFloat(writeButton, "alpha", 0.0f) - ); - } - writeButtonAnimation.setDuration(150); - writeButtonAnimation.addListener(new AnimatorListenerAdapterProxy() { - @Override - public void onAnimationEnd(Object animation) { - if (writeButtonAnimation != null && writeButtonAnimation.equals(animation)) { - writeButton.clearAnimation(); - writeButton.setVisibility(setVisible ? View.VISIBLE : View.GONE); - writeButtonAnimation = null; + if (Build.VERSION.SDK_INT < 11) { + layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams(); + layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + extraHeight - AndroidUtilities.dp(29.5f); + writeButton.setLayoutParams(layoutParams); + } else { + ViewProxy.setTranslationY(writeButton, (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + extraHeight - AndroidUtilities.dp(29.5f)); + } + + if (!openAnimationInProgress) { + final boolean setVisible = diff > 0.2f; + boolean currentVisible = writeButton.getTag() == null; + if (setVisible != currentVisible) { + if (setVisible) { + writeButton.setTag(null); + if (Build.VERSION.SDK_INT < 11) { + writeButton.setVisibility(View.VISIBLE); } + } else { + writeButton.setTag(0); } - }); - writeButtonAnimation.start(); + if (writeButtonAnimation != null) { + AnimatorSetProxy old = writeButtonAnimation; + writeButtonAnimation = null; + old.cancel(); + } + writeButtonAnimation = new AnimatorSetProxy(); + if (setVisible) { + writeButtonAnimation.setInterpolator(new DecelerateInterpolator()); + writeButtonAnimation.playTogether( + ObjectAnimatorProxy.ofFloat(writeButton, "scaleX", 1.0f), + ObjectAnimatorProxy.ofFloat(writeButton, "scaleY", 1.0f), + ObjectAnimatorProxy.ofFloat(writeButton, "alpha", 1.0f) + ); + } else { + writeButtonAnimation.setInterpolator(new AccelerateInterpolator()); + writeButtonAnimation.playTogether( + ObjectAnimatorProxy.ofFloat(writeButton, "scaleX", 0.2f), + ObjectAnimatorProxy.ofFloat(writeButton, "scaleY", 0.2f), + ObjectAnimatorProxy.ofFloat(writeButton, "alpha", 0.0f) + ); + } + writeButtonAnimation.setDuration(150); + writeButtonAnimation.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (writeButtonAnimation != null && writeButtonAnimation.equals(animation)) { + writeButton.clearAnimation(); + if (Build.VERSION.SDK_INT < 11) { + writeButton.setVisibility(setVisible ? View.VISIBLE : View.GONE); + } + writeButtonAnimation = null; + } + } + }); + writeButtonAnimation.start(); + } } } - avatarImage.setRoundRadius(AndroidUtilities.dp(avatarSize / 2)); - layoutParams = (FrameLayout.LayoutParams) avatarImage.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(avatarSize); - layoutParams.height = AndroidUtilities.dp(avatarSize); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(avatarX); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(avatarX) : 0; - layoutParams.bottomMargin = avatarY; - avatarImage.setLayoutParams(layoutParams); - - ViewProxy.setPivotX(nameTextView, 0); - ViewProxy.setPivotY(nameTextView, 0); - ViewProxy.setScaleX(nameTextView, scale); - ViewProxy.setScaleY(nameTextView, scale); - layoutParams = (FrameLayout.LayoutParams) nameTextView.getLayoutParams(); - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? nameEndX : nameX); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? nameX : nameEndX); - layoutParams.bottomMargin = nameY; - nameTextView.setLayoutParams(layoutParams); - - layoutParams = (FrameLayout.LayoutParams) onlineTextView.getLayoutParams(); - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? nameEndX : nameX); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? nameX : nameEndX); - layoutParams.bottomMargin = statusY; - onlineTextView.setLayoutParams(layoutParams); + float avatarY = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() / 2.0f * (1.0f + diff) - 21 * AndroidUtilities.density + 27 * AndroidUtilities.density * diff; + if (Build.VERSION.SDK_INT < 11) { + layoutParams = (FrameLayout.LayoutParams) avatarImage.getLayoutParams(); + layoutParams.height = layoutParams.width = (int) Math.ceil(AndroidUtilities.dp(42) * (42 + 18 * diff) / 42.0f); + layoutParams.leftMargin = (int) Math.ceil(AndroidUtilities.dp(64) - AndroidUtilities.dp(47) * diff); + layoutParams.topMargin = (int) Math.ceil(avatarY); + avatarImage.setLayoutParams(layoutParams); + avatarImage.setRoundRadius(layoutParams.height / 2); + } else { + ViewProxy.setScaleX(avatarImage, (42 + 18 * diff) / 42.0f); + ViewProxy.setScaleY(avatarImage, (42 + 18 * diff) / 42.0f); + ViewProxy.setTranslationX(avatarImage, -AndroidUtilities.dp(47) * diff); + ViewProxy.setTranslationY(avatarImage, (float) Math.ceil(avatarY)); + } + ViewProxy.setTranslationX(nameTextView, -21 * AndroidUtilities.density * diff); + ViewProxy.setTranslationY(nameTextView, (float) Math.floor(avatarY) - (float) Math.ceil(AndroidUtilities.density) + (float) Math.floor(7 * AndroidUtilities.density * diff)); + ViewProxy.setTranslationX(onlineTextView, -21 * AndroidUtilities.density * diff); + ViewProxy.setTranslationY(onlineTextView, (float) Math.floor(avatarY) + AndroidUtilities.dp(22) + (float )Math.floor(11 * AndroidUtilities.density) * diff); + ViewProxy.setScaleX(nameTextView, 1.0f + 0.12f * diff); + ViewProxy.setScaleY(nameTextView, 1.0f + 0.12f * diff); } } @@ -1008,22 +1023,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. fixLayout(); } - @Override - public boolean needAddActionBar() { - return false; - } - + @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, final Object... args) { if (id == NotificationCenter.updateInterfaces) { - int mask = (Integer)args[0]; + int mask = (Integer) args[0]; if (user_id != 0) { if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0 || (mask & MessagesController.UPDATE_MASK_NAME) != 0 || (mask & MessagesController.UPDATE_MASK_STATUS) != 0) { updateProfileData(); } if ((mask & MessagesController.UPDATE_MASK_PHONE) != 0) { if (listView != null) { - listView.invalidateViews(); + ListAdapter.Holder holder = (ListAdapter.Holder) listView.findViewHolderForPosition(phoneRow); + if (holder != null) { + listAdapter.onBindViewHolder(holder, phoneRow); + } } } } else if (chat_id != 0) { @@ -1052,20 +1066,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (id == NotificationCenter.contactsDidLoaded) { createActionBarMenu(); } else if (id == NotificationCenter.mediaCountDidLoaded) { - long uid = (Long)args[0]; - if (user_id != 0) { - if (uid > 0 && user_id == uid && dialog_id == 0 || dialog_id != 0 && dialog_id == uid) { - totalMediaCount = (Integer) args[1]; - if (listView != null) { - listView.invalidateViews(); - } - } - } else if (chat_id != 0) { - int lower_part = (int)uid; - if (lower_part < 0 && chat_id == -lower_part) { - totalMediaCount = (Integer)args[1]; - if (listView != null) { - listView.invalidateViews(); + long uid = (Long) args[0]; + int lower_part = (int) uid; + if (user_id != 0 && (uid > 0 && user_id == uid && dialog_id == 0 || dialog_id != 0 && dialog_id == uid) || chat_id != 0 && (lower_part < 0 && chat_id == -lower_part)) { + totalMediaCount = (Integer) args[1]; + if (listView != null) { + ListAdapter.Holder holder = (ListAdapter.Holder) listView.findViewHolderForPosition(sharedMediaRow); + if (holder != null) { + listAdapter.onBindViewHolder(holder, sharedMediaRow); } } } @@ -1084,7 +1092,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }); } } else if (id == NotificationCenter.encryptedChatUpdated) { - TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat)args[0]; + TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) args[0]; if (currentEncryptedChat != null && chat.id == currentEncryptedChat.id) { currentEncryptedChat = chat; updateRowsIds(); @@ -1118,6 +1126,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. botInfo = info; updateRowsIds(); } + } if (id == NotificationCenter.didReceivedNewMessages) { + long did = (Long) args[0]; + if (did == dialog_id) { + ArrayList arr = (ArrayList) args[1]; + for (int a = 0; a < arr.size(); a++) { + MessageObject obj = arr.get(a); + if (currentEncryptedChat != null && obj.messageOwner.action != null && obj.messageOwner.action instanceof TLRPC.TL_messageEncryptedAction && obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { + TLRPC.TL_decryptedMessageActionSetMessageTTL action = (TLRPC.TL_decryptedMessageActionSetMessageTTL) obj.messageOwner.action.encryptedAction; + if (listAdapter != null) { + listAdapter.notifyDataSetChanged(); + checkListViewScroll(); + } + } + } + } } } @@ -1131,6 +1154,114 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. fixLayout(); } + public void setPlayProfileAnimation(boolean value) { + if (!AndroidUtilities.isTablet()) { + playProfileAnimation = value; + } + } + + @Override + protected void onTransitionAnimationStart(boolean isOpen, boolean backward) { + if (!backward && playProfileAnimation) { + openAnimationInProgress = true; + } + NotificationCenter.getInstance().setAnimationInProgress(true); + } + + @Override + protected void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (!backward && playProfileAnimation) { + openAnimationInProgress = false; + } + NotificationCenter.getInstance().setAnimationInProgress(false); + } + + public float getAnimationProgress() { + return animationProgress; + } + + public void setAnimationProgress(float progress) { + animationProgress = progress; + ViewProxy.setAlpha(listView, progress); + ViewProxy.setTranslationX(listView, AndroidUtilities.dp(48) * (1.0f - progress)); + int color = AvatarDrawable.getProfileBackColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id); + int rD = (int) ((Color.red(color) - 0x54) * progress); + int gD = (int) ((Color.green(color) - 0x75) * progress); + int bD = (int) ((Color.blue(color) - 0x9e) * progress); + actionBar.setBackgroundColor(Color.rgb(0x54 + rD, 0x75 + gD, 0x9e + bD)); + extraHeightView.setBackgroundColor(Color.rgb(0x54 + rD, 0x75 + gD, 0x9e + bD)); + color = AvatarDrawable.getProfileTextColorForId(user_id != 0 || ChatObject.isChannel(chat_id) ? 5 : chat_id); + rD = (int) ((Color.red(color) - 0xd7) * progress); + gD = (int) ((Color.green(color) - 0xe8) * progress); + bD = (int) ((Color.blue(color) - 0xf7) * progress); + onlineTextView.setTextColor(Color.rgb(0xd7 + rD, 0xe8 + gD, 0xf7 + bD)); + extraHeight = (int) (initialAnimationExtraHeight * progress); + needLayout(); + } + + @Override + protected AnimatorSetProxy onCustomTransitionAnimation(final boolean isOpen, final Runnable callback) { + if (playProfileAnimation) { + final AnimatorSetProxy animatorSet = new AnimatorSetProxy(); + animatorSet.setDuration(150); + if (Build.VERSION.SDK_INT > 15) { + listView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + if (isOpen) { + initialAnimationExtraHeight = AndroidUtilities.dp(88); + fragmentView.setBackgroundColor(0); + setAnimationProgress(0); + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimatorProxy.ofFloat(this, "animationProgress", 0.0f, 1.0f)); + if (writeButton != null) { + ViewProxy.setScaleX(writeButton, 0.2f); + ViewProxy.setScaleY(writeButton, 0.2f); + ViewProxy.setAlpha(writeButton, 0.0f); + animators.add(ObjectAnimatorProxy.ofFloat(writeButton, "scaleX", 1.0f)); + animators.add(ObjectAnimatorProxy.ofFloat(writeButton, "scaleY", 1.0f)); + animators.add(ObjectAnimatorProxy.ofFloat(writeButton, "alpha", 1.0f)); + } + animatorSet.playTogether(animators); + } else { + initialAnimationExtraHeight = extraHeight; + ArrayList animators = new ArrayList<>(); + animators.add(ObjectAnimatorProxy.ofFloat(this, "animationProgress", 1.0f, 0.0f)); + if (writeButton != null) { + animators.add(ObjectAnimatorProxy.ofFloat(writeButton, "scaleX", 0.2f)); + animators.add(ObjectAnimatorProxy.ofFloat(writeButton, "scaleY", 0.2f)); + animators.add(ObjectAnimatorProxy.ofFloat(writeButton, "alpha", 0.0f)); + } + animatorSet.playTogether(animators); + } + animatorSet.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (Build.VERSION.SDK_INT > 15) { + listView.setLayerType(View.LAYER_TYPE_NONE, null); + } + callback.run(); + } + + @Override + public void onAnimationCancel(Object animation) { + if (Build.VERSION.SDK_INT > 15) { + listView.setLayerType(View.LAYER_TYPE_NONE, null); + } + } + }); + animatorSet.setInterpolator(new DecelerateInterpolator()); + + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + animatorSet.start(); + } + }, 20); + return animatorSet; + } + return null; + } + @Override public void updatePhotoAtIndex(int index) { @@ -1168,6 +1299,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. object.thumb = object.imageReceiver.getBitmap(); object.size = -1; object.radius = avatarImage.getImageReceiver().getRoundRadius(); + object.scale = ViewProxy.getScaleX(avatarImage); return object; } return null; @@ -1193,7 +1325,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public void setPhotoChecked(int index) { } @Override - public void cancelButtonPressed() { } + public boolean cancelButtonPressed() { return true; } @Override public void sendButtonPressed(int index) { } @@ -1202,10 +1334,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public int getSelectedCount() { return 0; } private void updateOnlineCount() { + onlineCount = 0; if (!(info instanceof TLRPC.TL_chatFull)) { return; } - onlineCount = 0; int currentTime = ConnectionsManager.getInstance().getCurrentTime(); sortedUsers.clear(); int i = 0; @@ -1266,8 +1398,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. FileLog.e("tmessages", e); //TODO find crash } - if (listView != null) { - listView.invalidateViews(); + if (listAdapter != null) { + listAdapter.notifyItemRangeChanged(emptyRowChat2 + 1, sortedUsers.size()); } } @@ -1286,6 +1418,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); } MessagesController.getInstance().deleteUserFromChat(chat_id, MessagesController.getInstance().getUser(UserConfig.getClientUserId()), info); + playProfileAnimation = false; finishFragment(); } } @@ -1415,12 +1548,24 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. AvatarDrawable avatarDrawable = new AvatarDrawable(user); avatarImage.setImage(photo, "50_50", avatarDrawable); - nameTextView.setText(UserObject.getUserName(user)); - if ((user.flags & TLRPC.USER_FLAG_BOT) != 0) { - onlineTextView.setText(LocaleController.getString("Bot", R.string.Bot)); - } else { - onlineTextView.setText(LocaleController.formatUserStatus(user)); + String newString; + newString = UserObject.getUserName(user); + if (!nameTextView.getText().equals(newString)) { + nameTextView.setText(newString); } + if (user.id == 333000 || user.id == 777000) { + newString = LocaleController.getString("ServiceNotifications", R.string.ServiceNotifications); + } else if ((user.flags & TLRPC.USER_FLAG_BOT) != 0) { + newString = LocaleController.getString("Bot", R.string.Bot); + } else { + newString = LocaleController.formatUserStatus(user); + } + if (!onlineTextView.getText().equals(newString)) { + onlineTextView.setText(newString); + } + + int leftIcon = currentEncryptedChat != null ? R.drawable.ic_lock_header : 0; + nameTextView.setCompoundDrawablesWithIntrinsicBounds(leftIcon, 0, 0, 0); avatarImage.getImageReceiver().setVisible(!PhotoViewer.getInstance().isShowingImage(photoBig), false); } else if (chat_id != 0) { @@ -1430,20 +1575,31 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { chat = currentChat; } - nameTextView.setText(chat.title); + if (chat.title != null && !nameTextView.getText().equals(chat.title)) { + nameTextView.setText(chat.title); + } + if ((chat.flags & TLRPC.CHAT_FLAG_IS_VERIFIED) != 0) { + if (nameTextView.getCompoundDrawables()[2] == null) { + nameTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.check_profile_fixed, 0); + } + } else { + if (nameTextView.getCompoundDrawables()[2] != null) { + nameTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); + } + } + String newString; if (ChatObject.isChannel(chat)) { if (info == null || info.participants_count == 0 || ((currentChat.flags & TLRPC.CHAT_FLAG_ADMIN) != 0 || (info.flags & 8) != 0)) { if ((chat.flags & TLRPC.CHAT_FLAG_IS_PUBLIC) != 0) { - onlineTextView.setText(LocaleController.getString("ChannelPublic", R.string.ChannelPublic).toLowerCase()); + newString = LocaleController.getString("ChannelPublic", R.string.ChannelPublic).toLowerCase(); } else { - onlineTextView.setText(LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate).toLowerCase()); + newString = LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate).toLowerCase(); } } else { int result[] = new int[1]; String shortNumber = LocaleController.formatShortNumber(info.participants_count, result); - String text = LocaleController.formatPluralString("Members", result[0]).replace(String.format("%d", result[0]), shortNumber); - onlineTextView.setText(text); + newString = LocaleController.formatPluralString("Members", result[0]).replace(String.format("%d", result[0]), shortNumber); } } else { int count = chat.participants_count; @@ -1451,11 +1607,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. count = info.participants.participants.size(); } if (count != 0 && onlineCount > 1) { - onlineTextView.setText(String.format("%s, %s", LocaleController.formatPluralString("Members", count), LocaleController.formatPluralString("Online", onlineCount))); + newString = String.format("%s, %s", LocaleController.formatPluralString("Members", count), LocaleController.formatPluralString("Online", onlineCount)); } else { - onlineTextView.setText(LocaleController.formatPluralString("Members", count)); + newString = LocaleController.formatPluralString("Members", count); } } + if (!onlineTextView.getText().equals(newString)) { + onlineTextView.setText(newString); + } TLRPC.FileLocation photo = null; TLRPC.FileLocation photoBig = null; @@ -1464,7 +1623,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. photoBig = chat.photo.photo_big; } avatarImage.setImage(photo, "50_50", new AvatarDrawable(chat, true)); - avatarImage.getImageReceiver().setVisible(!PhotoViewer.getInstance().isShowingImage(photoBig), false); } } @@ -1557,192 +1715,226 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } - private class ListAdapter extends BaseFragmentAdapter { + private class ListAdapter extends RecyclerListView.Adapter { private Context mContext; + private class Holder extends RecyclerView.ViewHolder { + + public Holder(View itemView) { + super(itemView); + } + } + public ListAdapter(Context context) { mContext = context; } @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int i) { - if (user_id != 0) { - return i == phoneRow || i == settingsTimerRow || i == settingsKeyRow || i == settingsNotificationsRow || i == sharedMediaRow || i == startSecretChatRow; - } else if (chat_id != 0) { - return i == settingsNotificationsRow || i == sharedMediaRow || i > emptyRowChat2 && i < membersEndRow || i == addMemberRow || i == channelNameRow || i == leaveChannelRow || i == membersRow || i == managementRow || i == blockedUsersRow || i == channelInfoRow; - } - return false; - } - - @Override - public int getCount() { - return rowCount; - } - - @Override - public Object getItem(int i) { - return null; - } - - @Override - public long getItemId(int i) { - return i; - } - - @Override - public boolean hasStableIds() { - return false; - } - - @Override - public View getView(int i, View view, ViewGroup viewGroup) { - int type = getItemViewType(i); - if (type == 0) { - if (view == null) { + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = null; + switch (viewType) { + case 0: view = new EmptyCell(mContext); - } - if (i == overscrollRow) { - ((EmptyCell) view).setHeight(AndroidUtilities.dp(88)); - } else if (i == emptyRowChat || i == emptyRowChat2) { - ((EmptyCell) view).setHeight(AndroidUtilities.dp(8)); - } else { - ((EmptyCell) view).setHeight(AndroidUtilities.dp(36)); - } - } else if (type == 1) { - if (view == null) { + break; + case 1: view = new DividerCell(mContext); view.setPadding(AndroidUtilities.dp(72), 0, 0, 0); - } - } else if (type == 2) { - if (view == null) { - view = new TextDetailCell(mContext); - } - TextDetailCell textDetailCell = (TextDetailCell) view; - - if (i == phoneRow) { - String text; - final TLRPC.User user = MessagesController.getInstance().getUser(user_id); - if (user.phone != null && user.phone.length() != 0) { - text = PhoneFormat.getInstance().format("+" + user.phone); - } else { - text = LocaleController.getString("NumberUnknown", R.string.NumberUnknown); - } - textDetailCell.setTextAndValueAndIcon(text, LocaleController.getString("PhoneMobile", R.string.PhoneMobile), R.drawable.phone_grey); - } else if (i == usernameRow) { - String text; - final TLRPC.User user = MessagesController.getInstance().getUser(user_id); - if (user != null && user.username != null && user.username.length() != 0) { - text = "@" + user.username; - } else { - text = "-"; - } - textDetailCell.setTextAndValue(text, LocaleController.getString("Username", R.string.Username)); - } else if (i == channelNameRow) { - String text; - if (currentChat != null && currentChat.username != null && currentChat.username.length() != 0) { - text = "@" + currentChat.username; - } else { - text = "-"; - } - textDetailCell.setTextAndValue(text, "telegram.me/" + currentChat.username); - } - } else if (type == 3) { - if (view == null) { - view = new TextCell(mContext); - } - TextCell textCell = (TextCell) view; - textCell.setTextColor(0xff212121); - - if (i == sharedMediaRow) { - String value; - if (totalMediaCount == -1) { - value = LocaleController.getString("Loading", R.string.Loading); - } else { - value = String.format("%d", totalMediaCount); - } - textCell.setMultiline(false); - textCell.setTextAndValue(LocaleController.getString("SharedMedia", R.string.SharedMedia), value); - } else if (i == settingsTimerRow) { - TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat((int)(dialog_id >> 32)); - String value; - if (encryptedChat.ttl == 0) { - value = LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever); - } else { - value = AndroidUtilities.formatTTLString(encryptedChat.ttl); - } - textCell.setMultiline(false); - textCell.setTextAndValue(LocaleController.getString("MessageLifetime", R.string.MessageLifetime), value); - } else if (i == settingsNotificationsRow) { - textCell.setMultiline(false); - textCell.setTextAndIcon(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.profile_list); - } else if (i == startSecretChatRow) { - textCell.setMultiline(false); - textCell.setText(LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat)); - textCell.setTextColor(0xff37a919); - } else if (i == settingsKeyRow) { - IdenticonDrawable identiconDrawable = new IdenticonDrawable(); - TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat((int)(dialog_id >> 32)); - identiconDrawable.setEncryptedChat(encryptedChat); - textCell.setMultiline(false); - textCell.setTextAndValueDrawable(LocaleController.getString("EncryptionKey", R.string.EncryptionKey), identiconDrawable); - } else if (i == botInfoRow) { - textCell.setMultiline(true); - textCell.setTextAndIcon(botInfo.share_text, R.drawable.bot_info); - } else if (i == channelInfoRow) { - textCell.setMultiline(true); - textCell.setTextAndIcon(info.about, R.drawable.bot_info); - } else if (i == leaveChannelRow) { - textCell.setTextColor(0xffed3d39); - textCell.setMultiline(false); - textCell.setText(LocaleController.getString("LeaveChannel", R.string.LeaveChannel)); - } else if (i == membersRow) { - textCell.setMultiline(false); - if (info != null) { - textCell.setTextAndValue(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants_count)); - } else { - textCell.setText(LocaleController.getString("ChannelMembers", R.string.ChannelMembers)); - } - } else if (i == managementRow) { - textCell.setMultiline(false); - if (info != null) { - textCell.setTextAndValue(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", info.admins_count)); - } else { - textCell.setText(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators)); - } - } else if (i == blockedUsersRow) { - textCell.setMultiline(false); - if (info != null) { - textCell.setTextAndValue(LocaleController.getString("ChannelBlockedUsers", R.string.ChannelBlockedUsers), String.format("%d", info.kicked_count)); - } else { - textCell.setText(LocaleController.getString("ChannelBlockedUsers", R.string.ChannelBlockedUsers)); - } - } - } else if (type == 4) { - if (view == null) { - view = new UserCell(mContext, 61); - } - TLRPC.TL_chatParticipant part = info.participants.participants.get(sortedUsers.get(i - emptyRowChat2 - 1)); - ((UserCell) view).setData(MessagesController.getInstance().getUser(part.user_id), null, null, i == emptyRowChat2 + 1 ? R.drawable.menu_newgroup : 0); - } else if (type == 5) { - if (view == null) { + break; + case 2: + view = new TextDetailCell(mContext) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (Build.VERSION.SDK_INT >= 21 && getBackground() != null) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { + getBackground().setHotspot(event.getX(), event.getY()); + } + } + return super.onTouchEvent(event); + } + }; + break; + case 3: + view = new TextCell(mContext) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (Build.VERSION.SDK_INT >= 21 && getBackground() != null) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { + getBackground().setHotspot(event.getX(), event.getY()); + } + } + return super.onTouchEvent(event); + } + }; + break; + case 4: + view = new UserCell(mContext, 61) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (Build.VERSION.SDK_INT >= 21 && getBackground() != null) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { + getBackground().setHotspot(event.getX(), event.getY()); + } + } + return super.onTouchEvent(event); + } + }; + break; + case 5: view = new ShadowSectionCell(mContext); - } - } else if (type == 6) { - if (view == null) { + break; + case 6: view = new AddMemberCell(mContext); if (chat_id > 0) { ((AddMemberCell) view).setText(LocaleController.getString("AddMember", R.string.AddMember)); } else { ((AddMemberCell) view).setText(LocaleController.getString("AddRecipient", R.string.AddRecipient)); } + break; + } + return new Holder(view); + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder holder, int i) { + boolean checkBackground = true; + switch (holder.getItemViewType()) { + case 0: + if (i == overscrollRow) { + ((EmptyCell) holder.itemView).setHeight(AndroidUtilities.dp(88)); + } else if (i == emptyRowChat || i == emptyRowChat2) { + ((EmptyCell) holder.itemView).setHeight(AndroidUtilities.dp(8)); + } else { + ((EmptyCell) holder.itemView).setHeight(AndroidUtilities.dp(36)); + } + break; + case 2: + TextDetailCell textDetailCell = (TextDetailCell) holder.itemView; + if (i == phoneRow) { + String text; + final TLRPC.User user = MessagesController.getInstance().getUser(user_id); + if (user.phone != null && user.phone.length() != 0) { + text = PhoneFormat.getInstance().format("+" + user.phone); + } else { + text = LocaleController.getString("NumberUnknown", R.string.NumberUnknown); + } + textDetailCell.setTextAndValueAndIcon(text, LocaleController.getString("PhoneMobile", R.string.PhoneMobile), R.drawable.phone_grey); + } else if (i == usernameRow) { + String text; + final TLRPC.User user = MessagesController.getInstance().getUser(user_id); + if (user != null && user.username != null && user.username.length() != 0) { + text = "@" + user.username; + } else { + text = "-"; + } + textDetailCell.setTextAndValue(text, LocaleController.getString("Username", R.string.Username)); + } else if (i == channelNameRow) { + String text; + if (currentChat != null && currentChat.username != null && currentChat.username.length() != 0) { + text = "@" + currentChat.username; + } else { + text = "-"; + } + textDetailCell.setTextAndValue(text, "telegram.me/" + currentChat.username); + } + break; + case 3: + TextCell textCell = (TextCell) holder.itemView; + textCell.setTextColor(0xff212121); + + if (i == sharedMediaRow) { + String value; + if (totalMediaCount == -1) { + value = LocaleController.getString("Loading", R.string.Loading); + } else { + value = String.format("%d", totalMediaCount); + } + textCell.setMultiline(false); + textCell.setTextAndValue(LocaleController.getString("SharedMedia", R.string.SharedMedia), value); + } else if (i == settingsTimerRow) { + TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat((int)(dialog_id >> 32)); + String value; + if (encryptedChat.ttl == 0) { + value = LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever); + } else { + value = AndroidUtilities.formatTTLString(encryptedChat.ttl); + } + textCell.setMultiline(false); + textCell.setTextAndValue(LocaleController.getString("MessageLifetime", R.string.MessageLifetime), value); + } else if (i == settingsNotificationsRow) { + textCell.setMultiline(false); + textCell.setTextAndIcon(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.profile_list); + } else if (i == startSecretChatRow) { + textCell.setMultiline(false); + textCell.setText(LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat)); + textCell.setTextColor(0xff37a919); + } else if (i == settingsKeyRow) { + IdenticonDrawable identiconDrawable = new IdenticonDrawable(); + TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat((int)(dialog_id >> 32)); + identiconDrawable.setEncryptedChat(encryptedChat); + textCell.setMultiline(false); + textCell.setTextAndValueDrawable(LocaleController.getString("EncryptionKey", R.string.EncryptionKey), identiconDrawable); + } else if (i == botInfoRow) { + textCell.setMultiline(true); + textCell.setTextAndIcon(botInfo.share_text, R.drawable.bot_info); + } else if (i == channelInfoRow) { + textCell.setMultiline(true); + textCell.setTextAndIcon(info.about, R.drawable.bot_info); + } else if (i == leaveChannelRow) { + textCell.setTextColor(0xffed3d39); + textCell.setMultiline(false); + textCell.setText(LocaleController.getString("LeaveChannel", R.string.LeaveChannel)); + } else if (i == membersRow) { + textCell.setMultiline(false); + if (info != null) { + textCell.setTextAndValue(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), String.format("%d", info.participants_count)); + } else { + textCell.setText(LocaleController.getString("ChannelMembers", R.string.ChannelMembers)); + } + } else if (i == managementRow) { + textCell.setMultiline(false); + if (info != null) { + textCell.setTextAndValue(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators), String.format("%d", info.admins_count)); + } else { + textCell.setText(LocaleController.getString("ChannelAdministrators", R.string.ChannelAdministrators)); + } + } else if (i == blockedUsersRow) { + textCell.setMultiline(false); + if (info != null) { + textCell.setTextAndValue(LocaleController.getString("ChannelBlockedUsers", R.string.ChannelBlockedUsers), String.format("%d", info.kicked_count)); + } else { + textCell.setText(LocaleController.getString("ChannelBlockedUsers", R.string.ChannelBlockedUsers)); + } + } + break; + case 4: + TLRPC.TL_chatParticipant part = info.participants.participants.get(sortedUsers.get(i - emptyRowChat2 - 1)); + ((UserCell) holder.itemView).setData(MessagesController.getInstance().getUser(part.user_id), null, null, i == emptyRowChat2 + 1 ? R.drawable.menu_newgroup : 0); + break; + default: + checkBackground = false; + } + if (checkBackground) { + boolean enabled = false; + if (user_id != 0) { + enabled = i == phoneRow || i == settingsTimerRow || i == settingsKeyRow || i == settingsNotificationsRow || i == sharedMediaRow || i == startSecretChatRow || i == usernameRow; + } else if (chat_id != 0) { + enabled = i == settingsNotificationsRow || i == sharedMediaRow || i > emptyRowChat2 && i < membersEndRow || i == addMemberRow || i == channelNameRow || i == leaveChannelRow || i == membersRow || i == managementRow || i == blockedUsersRow || i == channelInfoRow; + } + if (enabled) { + if (holder.itemView.getBackground() == null) { + holder.itemView.setBackgroundResource(R.drawable.list_selector); + } + } else { + if (holder.itemView.getBackground() != null) { + holder.itemView.setBackgroundDrawable(null); + } } } - return view; + } + + @Override + public int getItemCount() { + return rowCount; } @Override @@ -1765,14 +1957,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return 0; } - @Override - public int getViewTypeCount() { - return 7; - } + /*@Override + public boolean isEnabled(int i) { - @Override - public boolean isEmpty() { return false; - } + }*/ } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 915bfc16c..1efda4c27 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.4.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java index cf2c24d98..9ca19d128 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -18,6 +18,7 @@ import android.graphics.PixelFormat; import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.os.Build; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; @@ -257,12 +258,20 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD BitmapDrawable drawable = ImageLoader.getInstance().getImageFromMemory(sizeFull.location, null, null); if (drawable == null) { File file = FileLoader.getPathToAttach(sizeFull); - Bitmap bitmap; + Bitmap bitmap = null; + BitmapFactory.Options options = null; + if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 21) { + options = new BitmapFactory.Options(); + options.inDither = true; + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + options.inPurgeable = true; + options.inSampleSize = 1; + options.inMutable = true; + } try { - bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); + bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options); } catch (Throwable e) { - ImageLoader.getInstance().clearMemory(); - bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); + FileLog.e("tmessages", e); } if (bitmap != null) { drawable = new BitmapDrawable(bitmap); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index 09f6ce299..35690078a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index 8c1170404..61f4d19a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -105,6 +105,10 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private ImageView writeButton; private AnimatorSetProxy writeButtonAnimation; private AvatarUpdater avatarUpdater = new AvatarUpdater(); + private View extraHeightView; + private View shadowView; + + private int extraHeight; private int overscrollRow; private int emptyRow; @@ -270,17 +274,13 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter avatarUpdater.clear(); } - @Override - public boolean needAddActionBar() { - return false; - } - @Override public View createView(Context context) { actionBar.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(5)); actionBar.setItemsBackground(AvatarDrawable.getButtonColorForId(5)); actionBar.setBackButtonImage(R.drawable.ic_ab_back); - actionBar.setExtraHeight(AndroidUtilities.dp(88), false); + actionBar.setAddToContainer(false); + extraHeight = 88; if (AndroidUtilities.isTablet()) { actionBar.setOccupyStatusBar(false); } @@ -346,41 +346,6 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter }; FrameLayout frameLayout = (FrameLayout) fragmentView; - avatarImage = new BackupImageView(context); - avatarImage.setRoundRadius(AndroidUtilities.dp(30)); - actionBar.addView(avatarImage, LayoutHelper.createFrame(60, 60, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM, LocaleController.isRTL ? 0 : 17, 0, LocaleController.isRTL ? 17 : 0, 22)); - avatarImage.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId()); - if (user.photo != null && user.photo.photo_big != null) { - PhotoViewer.getInstance().setParentActivity(getParentActivity()); - PhotoViewer.getInstance().openPhoto(user.photo.photo_big, SettingsActivity.this); - } - } - }); - - nameTextView = new TextView(context); - nameTextView.setTextColor(0xffffffff); - nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - nameTextView.setLines(1); - nameTextView.setMaxLines(1); - nameTextView.setSingleLine(true); - nameTextView.setEllipsize(TextUtils.TruncateAt.END); - nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - actionBar.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM, LocaleController.isRTL ? 16 : 97, 0, LocaleController.isRTL ? 97 : 16, 51)); - - onlineTextView = new TextView(context); - onlineTextView.setTextColor(AvatarDrawable.getProfileTextColorForId(5)); - onlineTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - onlineTextView.setLines(1); - onlineTextView.setMaxLines(1); - onlineTextView.setSingleLine(true); - onlineTextView.setEllipsize(TextUtils.TruncateAt.END); - onlineTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - actionBar.addView(onlineTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM, LocaleController.isRTL ? 16 : 97, 0, LocaleController.isRTL ? 97 : 16, 30)); - listView = new ListView(context); listView.setDivider(null); listView.setDividerHeight(0); @@ -600,6 +565,54 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter frameLayout.addView(actionBar); + extraHeightView = new View(context); + ViewProxy.setPivotY(extraHeightView, 0); + extraHeightView.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(5)); + frameLayout.addView(extraHeightView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 88)); + + shadowView = new View(context); + shadowView.setBackgroundResource(R.drawable.header_shadow); + frameLayout.addView(shadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3)); + + avatarImage = new BackupImageView(context); + avatarImage.setRoundRadius(AndroidUtilities.dp(21)); + ViewProxy.setPivotX(avatarImage, 0); + ViewProxy.setPivotY(avatarImage, 0); + frameLayout.addView(avatarImage, LayoutHelper.createFrame(42, 42, Gravity.TOP | Gravity.LEFT, 64, 0, 0, 0)); + avatarImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TLRPC.User user = MessagesController.getInstance().getUser(UserConfig.getClientUserId()); + if (user.photo != null && user.photo.photo_big != null) { + PhotoViewer.getInstance().setParentActivity(getParentActivity()); + PhotoViewer.getInstance().openPhoto(user.photo.photo_big, SettingsActivity.this); + } + } + }); + + nameTextView = new TextView(context); + nameTextView.setTextColor(0xffffffff); + nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + nameTextView.setLines(1); + nameTextView.setMaxLines(1); + nameTextView.setSingleLine(true); + nameTextView.setEllipsize(TextUtils.TruncateAt.END); + nameTextView.setGravity(Gravity.LEFT); + nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + ViewProxy.setPivotX(nameTextView, 0); + ViewProxy.setPivotY(nameTextView, 0); + frameLayout.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 48, 0)); + + onlineTextView = new TextView(context); + onlineTextView.setTextColor(AvatarDrawable.getProfileTextColorForId(5)); + onlineTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + onlineTextView.setLines(1); + onlineTextView.setMaxLines(1); + onlineTextView.setSingleLine(true); + onlineTextView.setEllipsize(TextUtils.TruncateAt.END); + onlineTextView.setGravity(Gravity.LEFT); + frameLayout.addView(onlineTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, 48, 0)); + writeButton = new ImageView(context); writeButton.setBackgroundResource(R.drawable.floating_user_states); writeButton.setImageResource(R.drawable.floating_camera); @@ -617,7 +630,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }); } - frameLayout.addView(writeButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 16 : 0, 0, LocaleController.isRTL ? 0 : 16, 0)); + frameLayout.addView(writeButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.TOP, 0, 0, 16, 0)); writeButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -660,6 +673,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } }); + needLayout(); + listView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { @@ -677,8 +692,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter if (firstVisibleItem == 0) { height = AndroidUtilities.dp(88) + (child.getTop() < 0 ? child.getTop() : 0); } - if (actionBar.getExtraHeight() != height) { - actionBar.setExtraHeight(height, true); + if (extraHeight != height) { + extraHeight = height; needLayout(); } } @@ -718,6 +733,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter object.thumb = object.imageReceiver.getBitmap(); object.size = -1; object.radius = avatarImage.getImageReceiver().getRoundRadius(); + object.scale = ViewProxy.getScaleX(avatarImage); return object; } } @@ -748,7 +764,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } @Override - public void cancelButtonPressed() { + public boolean cancelButtonPressed() { + return true; } @Override @@ -892,32 +909,29 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter private void needLayout() { FrameLayout.LayoutParams layoutParams; + int newTop = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight(); if (listView != null) { layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight(); - listView.setLayoutParams(layoutParams); + if (layoutParams.topMargin != newTop) { + layoutParams.topMargin = newTop; + listView.setLayoutParams(layoutParams); + ViewProxy.setTranslationY(extraHeightView, newTop); + } } if (avatarImage != null) { - float diff = actionBar.getExtraHeight() / (float) AndroidUtilities.dp(88); - float diffm = 1.0f - diff; + float diff = extraHeight / (float) AndroidUtilities.dp(88); + ViewProxy.setScaleY(extraHeightView, diff); + ViewProxy.setTranslationY(shadowView, newTop + extraHeight); - int avatarSize = 42 + (int) (18 * diff); - int avatarX = 17 + (int) (47 * diffm); - int avatarY = AndroidUtilities.dp(22) - (int) ((AndroidUtilities.dp(22) - (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff)); - int nameX = 97 + (int) (21 * diffm); - int nameEndX = 16 + (int) (32 * diffm); - int nameY = avatarY + AndroidUtilities.dp(29 - 13 * diffm); - int statusY = avatarY + AndroidUtilities.dp(8 - 7 * diffm); - float scale = 1.0f - 0.12f * diffm; + if (Build.VERSION.SDK_INT < 11) { + layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams(); + layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + extraHeight - AndroidUtilities.dp(29.5f); + writeButton.setLayoutParams(layoutParams); + } else { + ViewProxy.setTranslationY(writeButton, (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + extraHeight - AndroidUtilities.dp(29.5f)); + } - layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams(); - layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f); - writeButton.setLayoutParams(layoutParams); - - //ViewProxy.setScaleX(writeButton, diff > 0.2f ? 1.0f : diff / 0.2f); - //ViewProxy.setScaleY(writeButton, diff > 0.2f ? 1.0f : diff / 0.2f); - //ViewProxy.setAlpha(writeButton, diff > 0.2f ? 1.0f : diff / 0.2f); final boolean setVisible = diff > 0.2f; boolean currentVisible = writeButton.getTag() == null; if (setVisible != currentVisible) { @@ -962,30 +976,17 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter writeButtonAnimation.start(); } - avatarImage.setRoundRadius(AndroidUtilities.dp(avatarSize / 2)); - layoutParams = (FrameLayout.LayoutParams) avatarImage.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(avatarSize); - layoutParams.height = AndroidUtilities.dp(avatarSize); - layoutParams.leftMargin = LocaleController.isRTL ? 0 : AndroidUtilities.dp(avatarX); - layoutParams.rightMargin = LocaleController.isRTL ? AndroidUtilities.dp(avatarX) : 0; - layoutParams.bottomMargin = avatarY; - avatarImage.setLayoutParams(layoutParams); - - ViewProxy.setPivotX(nameTextView, 0); - ViewProxy.setPivotY(nameTextView, 0); - ViewProxy.setScaleX(nameTextView, scale); - ViewProxy.setScaleY(nameTextView, scale); - layoutParams = (FrameLayout.LayoutParams) nameTextView.getLayoutParams(); - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? nameEndX : nameX); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? nameX : nameEndX); - layoutParams.bottomMargin = nameY; - nameTextView.setLayoutParams(layoutParams); - - layoutParams = (FrameLayout.LayoutParams) onlineTextView.getLayoutParams(); - layoutParams.leftMargin = AndroidUtilities.dp(LocaleController.isRTL ? nameEndX : nameX); - layoutParams.rightMargin = AndroidUtilities.dp(LocaleController.isRTL ? nameX : nameEndX); - layoutParams.bottomMargin = statusY; - onlineTextView.setLayoutParams(layoutParams); + ViewProxy.setScaleX(avatarImage, (42 + 18 * diff) / 42.0f); + ViewProxy.setScaleY(avatarImage, (42 + 18 * diff) / 42.0f); + float avatarY = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() / 2.0f * (1.0f + diff) - 21 * AndroidUtilities.density + 27 * AndroidUtilities.density * diff; + ViewProxy.setTranslationX(avatarImage, -AndroidUtilities.dp(47) * diff); + ViewProxy.setTranslationY(avatarImage, (float) Math.ceil(avatarY)); + ViewProxy.setTranslationX(nameTextView, -21 * AndroidUtilities.density * diff); + ViewProxy.setTranslationY(nameTextView, (float) Math.floor(avatarY) - (float) Math.ceil(AndroidUtilities.density) + (float) Math.floor(7 * AndroidUtilities.density * diff)); + ViewProxy.setTranslationX(onlineTextView, -21 * AndroidUtilities.density * diff); + ViewProxy.setTranslationY(onlineTextView, (float) Math.floor(avatarY) + AndroidUtilities.dp(22) + (float )Math.floor(11 * AndroidUtilities.density) * diff); + ViewProxy.setScaleX(nameTextView, 1.0f + 0.12f * diff); + ViewProxy.setScaleY(nameTextView, 1.0f + 0.12f * diff); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickerPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/StickerPreviewViewer.java index 758368610..01e654707 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StickerPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StickerPreviewViewer.java @@ -107,7 +107,6 @@ public class StickerPreviewViewer { } else { windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; } - centerImage.setAspectFit(true); centerImage.setInvalidateAll(true); centerImage.setParentView(containerView); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java index abc2c89ec..7e66da82a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 2.x.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java index 32f2b54ab..ed96a2c20 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java @@ -1,5 +1,5 @@ /* - * This is the source code of Telegram for Android v. 2.x + * This is the source code of Telegram for Android v. 3.x.x * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * @@ -27,7 +27,6 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import android.view.inputmethod.EditorInfo; import android.widget.AdapterView; import android.widget.EditText; @@ -465,9 +464,8 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific } @Override - public void onOpenAnimationEnd() { - super.onOpenAnimationEnd(); - if (type == 1) { + public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { + if (isOpen && type == 1) { AndroidUtilities.showKeyboard(passwordEditText); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java index 789b939da..e0c2095d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.7.x. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013-2014. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java index 73e57387c..10a497155 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java @@ -1,9 +1,9 @@ /* - * This is the source code of Telegram for Android v. 1.3.2. + * This is the source code of Telegram for Android v. 3.x.x. * It is licensed under GNU GPL v. 2 or later. * You should have received a copy of the license in this archive (see LICENSE). * - * Copyright Nikolai Kudashov, 2013. + * Copyright Nikolai Kudashov, 2013-2015. */ package org.telegram.ui; @@ -16,6 +16,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.Point; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -86,7 +87,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent selectedBackground = preferences.getInt("selectedBackground", 1000001); selectedColor = preferences.getInt("selectedColor", 0); MessagesStorage.getInstance().getWallpapers(); - File toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper-temp.jpg"); + File toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper-temp.jpg"); toFile.delete(); return true; } @@ -124,7 +125,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(wallPaper.sizes, Math.min(width, height)); String fileName = size.location.volume_id + "_" + size.location.local_id + ".jpg"; File f = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); - File toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper.jpg"); + File toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg"); try { done = AndroidUtilities.copyFile(f, toFile); } catch (Exception e) { @@ -133,8 +134,8 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent } } else { if (selectedBackground == -1) { - File fromFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper-temp.jpg"); - File toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper.jpg"); + File fromFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper-temp.jpg"); + File toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg"); done = fromFile.renameTo(toFile); } else { done = true; @@ -247,11 +248,12 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent try { Point screenSize = AndroidUtilities.getRealScreenSize(); Bitmap bitmap = ImageLoader.loadBitmap(currentPicturePath, null, screenSize.x, screenSize.y, true); - File toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper-temp.jpg"); + File toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper-temp.jpg"); stream = new FileOutputStream(toFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream); selectedBackground = -1; selectedColor = 0; + Drawable drawable = backgroundImage.getDrawable(); backgroundImage.setImageBitmap(bitmap); } catch (Exception e) { FileLog.e("tmessages", e); @@ -272,11 +274,12 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent try { Point screenSize = AndroidUtilities.getRealScreenSize(); Bitmap bitmap = ImageLoader.loadBitmap(null, data.getData(), screenSize.x, screenSize.y, true); - File toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper-temp.jpg"); + File toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper-temp.jpg"); FileOutputStream stream = new FileOutputStream(toFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 87, stream); selectedBackground = -1; selectedColor = 0; + Drawable drawable = backgroundImage.getDrawable(); backgroundImage.setImageBitmap(bitmap); } catch (Exception e) { FileLog.e("tmessages", e); @@ -346,9 +349,9 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent backgroundImage.setBackgroundColor(0); selectedColor = 0; } else if (selectedBackground == -1) { - File toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper-temp.jpg"); + File toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper-temp.jpg"); if (!toFile.exists()) { - toFile = new File(ApplicationLoader.applicationContext.getFilesDir(), "wallpaper.jpg"); + toFile = new File(ApplicationLoader.getFilesDirFixed(), "wallpaper.jpg"); } if (toFile.exists()) { backgroundImage.setImageURI(Uri.fromFile(toFile)); @@ -361,6 +364,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent return; } if (wallPaper instanceof TLRPC.TL_wallPaperSolid) { + Drawable drawable = backgroundImage.getDrawable(); backgroundImage.setImageBitmap(null); selectedColor = 0xff000000 | wallPaper.bg_color; backgroundImage.setBackgroundColor(selectedColor); diff --git a/TMessagesProj/src/main/res/drawable-hdpi/check_list.png b/TMessagesProj/src/main/res/drawable-hdpi/check_list.png new file mode 100644 index 000000000..e739bea2f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/check_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/check_profile.png b/TMessagesProj/src/main/res/drawable-hdpi/check_profile.png new file mode 100644 index 000000000..380a8ebff Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/check_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/dialogs_badge2.9.png b/TMessagesProj/src/main/res/drawable-hdpi/dialogs_badge2.9.png new file mode 100755 index 000000000..76ff17ccc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/dialogs_badge2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/editheader.9.png b/TMessagesProj/src/main/res/drawable-hdpi/editheader.9.png deleted file mode 100644 index 00240da64..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/editheader.9.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_fp_40px.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_fp_40px.png new file mode 100644 index 000000000..48ebd8ad7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/ic_fp_40px.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/logo_avatar.png b/TMessagesProj/src/main/res/drawable-hdpi/logo_avatar.png new file mode 100644 index 000000000..8892c08dc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/logo_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_pause.png deleted file mode 100644 index 9643e6522..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_pause.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_play.png deleted file mode 100644 index 8b4bb5712..000000000 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/menu_play.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mic_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/mic_pressed.png old mode 100755 new mode 100644 index 3cf43e04b..ae9ea3bf4 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/mic_pressed.png and b/TMessagesProj/src/main/res/drawable-hdpi/mic_pressed.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_close.png b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_close.png new file mode 100755 index 000000000..ee4972c7a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_pause.png new file mode 100755 index 000000000..390a69c76 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_play.png b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_play.png new file mode 100755 index 000000000..7e3d35f71 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/miniplayer_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tip4.png b/TMessagesProj/src/main/res/drawable-hdpi/tip4.png new file mode 100644 index 000000000..cdc21ca78 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/tip4.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/check_list.png b/TMessagesProj/src/main/res/drawable-mdpi/check_list.png new file mode 100644 index 000000000..4061ffae9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/check_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/check_profile.png b/TMessagesProj/src/main/res/drawable-mdpi/check_profile.png new file mode 100644 index 000000000..ada9e496d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/check_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/dialogs_badge2.9.png b/TMessagesProj/src/main/res/drawable-mdpi/dialogs_badge2.9.png new file mode 100755 index 000000000..45eaa60e0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/dialogs_badge2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/editheader.9.png b/TMessagesProj/src/main/res/drawable-mdpi/editheader.9.png deleted file mode 100644 index e7f67fe07..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/editheader.9.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_fp_40px.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_fp_40px.png new file mode 100644 index 000000000..122f44257 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/ic_fp_40px.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/logo_avatar.png b/TMessagesProj/src/main/res/drawable-mdpi/logo_avatar.png new file mode 100644 index 000000000..c2de7747c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/logo_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png deleted file mode 100644 index befe821c8..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_play.png deleted file mode 100644 index 6d2ad6b3f..000000000 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/menu_play.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mic_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/mic_pressed.png old mode 100755 new mode 100644 index e1b29c5bc..ed471652e Binary files a/TMessagesProj/src/main/res/drawable-mdpi/mic_pressed.png and b/TMessagesProj/src/main/res/drawable-mdpi/mic_pressed.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_close.png b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_close.png new file mode 100755 index 000000000..1f5816b6f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_pause.png new file mode 100755 index 000000000..9f4edcc7d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_play.png b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_play.png new file mode 100755 index 000000000..088f15e25 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/miniplayer_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tip4.png b/TMessagesProj/src/main/res/drawable-mdpi/tip4.png new file mode 100644 index 000000000..a73985ca7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/tip4.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/check_list.png b/TMessagesProj/src/main/res/drawable-xhdpi/check_list.png new file mode 100644 index 000000000..7bc4bc303 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/check_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/check_profile.png b/TMessagesProj/src/main/res/drawable-xhdpi/check_profile.png new file mode 100644 index 000000000..36efe5482 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/check_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/dialogs_badge2.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/dialogs_badge2.9.png new file mode 100755 index 000000000..ad1d30b65 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/dialogs_badge2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/editheader.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/editheader.9.png deleted file mode 100644 index 50261891c..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/editheader.9.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_fp_40px.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_fp_40px.png new file mode 100644 index 000000000..e1c9590bb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_fp_40px.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/logo_avatar.png b/TMessagesProj/src/main/res/drawable-xhdpi/logo_avatar.png new file mode 100644 index 000000000..10c2dc9af Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/logo_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png deleted file mode 100644 index 54f0f7bcd..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png deleted file mode 100644 index 718da7c4e..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mic_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/mic_pressed.png old mode 100755 new mode 100644 index 62e655bea..bebe93611 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/mic_pressed.png and b/TMessagesProj/src/main/res/drawable-xhdpi/mic_pressed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_close.png b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_close.png new file mode 100755 index 000000000..07d83314b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_pause.png new file mode 100755 index 000000000..38746874f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_play.png new file mode 100755 index 000000000..e4e14c38a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/miniplayer_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tip4.png b/TMessagesProj/src/main/res/drawable-xhdpi/tip4.png new file mode 100644 index 000000000..e27f791d8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/tip4.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/check_list.png b/TMessagesProj/src/main/res/drawable-xxhdpi/check_list.png new file mode 100644 index 000000000..fd5a56b44 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/check_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/check_profile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/check_profile.png new file mode 100644 index 000000000..30bfdb482 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/check_profile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/dialogs_badge2.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/dialogs_badge2.9.png new file mode 100755 index 000000000..05816fe12 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/dialogs_badge2.9.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/editheader.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/editheader.9.png deleted file mode 100644 index a58727f98..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/editheader.9.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_fp_40px.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_fp_40px.png new file mode 100644 index 000000000..f7e87240e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_fp_40px.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/logo_avatar.png b/TMessagesProj/src/main/res/drawable-xxhdpi/logo_avatar.png new file mode 100644 index 000000000..df02f04f7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/logo_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png deleted file mode 100644 index 7bb5c4539..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png deleted file mode 100644 index 3279b876b..000000000 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png and /dev/null differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mic_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mic_pressed.png old mode 100755 new mode 100644 index c972af2bd..e7ca00427 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/mic_pressed.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/mic_pressed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_close.png b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_close.png new file mode 100755 index 000000000..909458acf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_pause.png new file mode 100755 index 000000000..1fb43f08b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_pause.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_play.png new file mode 100755 index 000000000..ee163892d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/miniplayer_play.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/tip4.png b/TMessagesProj/src/main/res/drawable-xxhdpi/tip4.png new file mode 100644 index 000000000..b78bf58de Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/tip4.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/sheet_shadow.9.png new file mode 100644 index 000000000..1520a1fc0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/sheet_shadow.9.png differ diff --git a/TMessagesProj/src/main/res/drawable/bar_selector_lock.xml b/TMessagesProj/src/main/res/drawable/bar_selector_lock.xml index ad45bba68..ea81ccde7 100644 --- a/TMessagesProj/src/main/res/drawable/bar_selector_lock.xml +++ b/TMessagesProj/src/main/res/drawable/bar_selector_lock.xml @@ -1,5 +1,5 @@ diff --git a/TMessagesProj/src/main/res/drawable/ic_emoji_backspace.xml b/TMessagesProj/src/main/res/drawable/ic_emoji_backspace.xml index 41ea5b772..51a217e25 100644 --- a/TMessagesProj/src/main/res/drawable/ic_emoji_backspace.xml +++ b/TMessagesProj/src/main/res/drawable/ic_emoji_backspace.xml @@ -1,7 +1,7 @@ + android:enterFadeDuration="1" + android:exitFadeDuration="200"> diff --git a/TMessagesProj/src/main/res/drawable/ic_emoji_bell.xml b/TMessagesProj/src/main/res/drawable/ic_emoji_bell.xml index 17b59fd60..224474574 100644 --- a/TMessagesProj/src/main/res/drawable/ic_emoji_bell.xml +++ b/TMessagesProj/src/main/res/drawable/ic_emoji_bell.xml @@ -1,8 +1,8 @@ + android:enterFadeDuration="1" + android:exitFadeDuration="200"> diff --git a/TMessagesProj/src/main/res/drawable/ic_emoji_car.xml b/TMessagesProj/src/main/res/drawable/ic_emoji_car.xml index 30c4baa25..464dc4346 100644 --- a/TMessagesProj/src/main/res/drawable/ic_emoji_car.xml +++ b/TMessagesProj/src/main/res/drawable/ic_emoji_car.xml @@ -1,8 +1,8 @@ + android:enterFadeDuration="1" + android:exitFadeDuration="200"> diff --git a/TMessagesProj/src/main/res/drawable/ic_emoji_symbol.xml b/TMessagesProj/src/main/res/drawable/ic_emoji_symbol.xml index 63a97e2f1..e3b405a7b 100644 --- a/TMessagesProj/src/main/res/drawable/ic_emoji_symbol.xml +++ b/TMessagesProj/src/main/res/drawable/ic_emoji_symbol.xml @@ -1,8 +1,8 @@ + android:enterFadeDuration="1" + android:exitFadeDuration="200"> diff --git a/TMessagesProj/src/main/res/drawable/ic_fingerprint_error.xml b/TMessagesProj/src/main/res/drawable/ic_fingerprint_error.xml new file mode 100644 index 000000000..be46116da --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/ic_fingerprint_error.xml @@ -0,0 +1,28 @@ + + + + + + diff --git a/TMessagesProj/src/main/res/drawable/mic_button_states.xml b/TMessagesProj/src/main/res/drawable/mic_button_states.xml deleted file mode 100644 index 791017eda..000000000 --- a/TMessagesProj/src/main/res/drawable/mic_button_states.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 0bff16ff1..3ef6aaa68 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -81,7 +81,7 @@ غادر القناة غادر القناة الإعدادات - دخول + اشترك معلومات القناة رسالة جماعية تعليق @@ -132,6 +132,7 @@ هل ترغب بإضافة %1$s للقناة؟ المعذرة, هذا المستخدم قرر مغادرة المجموعة, لا يمكنك دعوته مرة أخرى للمجموعة. المعذرة، لا يمكنك إضافة هذا المستخدم للقنوات. + المعذرة، يوجد الكثير من الإداريين في هذه القناة. المعذرة، يمكنك إضافة أول ٢٠٠ عضو للقناة فقط. يمكن لعدد غير محدود من الأعضاء الدخول للقناة عن طريق رابط القناة. un1 قام بإضافتك لهذه القناة لقد قمت بالدخول للقناة. @@ -147,14 +148,14 @@ %1$s قام بإرسال ملف للقناة %2$s %1$s قام بإرسال مقطع صوتي للقناة %2$s %1$s قام بإرسال ملصق للقناة %2$s - رسالة جديدة في القناة %1$s - صورة جديدة في القناة %1$s - مقطع مرئي جديد في القناة %1$s - تم مشاركة جهة اتصال في القناة %1$s - تم مشاركة مكان في القناة %1$s - ملف جديد في القناة %1$s - ملاحظة صوتية جديدة في القناة %1$s - ملصق جديد في القناة %1$s + %1$s أرسل رسالة + %1$s أرسل صورة + %1$s أرسل مقطع مرئي + %1$s أرسل جهة اتصال + %1$s قام بإرسال موقع + %1$s أرسل ملف + %1$s أرسل رسالة صوتية + %1$s أرسل ملصق رسالة جماعية جديدة أدخل اسم القائمة @@ -239,6 +240,7 @@ هل أنت متأكد من رغبتك في الإبلاغ عن هذه المجموعة كغير مرغوب بها؟ المعذرة، يمكنك فقط إرسال رسائل لمن يمتلك رقمك وتمتلك رقمه في الوقت الحالي. المعذرة، يمكنك فقط إضافة من يمتلك رقمك وتمتلك رقمه للمجموعة في الوقت الحالي. + https://telegram.org/faq/can-39t-send-messages-to-non-contacts ملعومات إضافية %1$s قام بتعيين عداد التدمير الذاتي إلى to %2$s @@ -289,6 +291,7 @@ متصل آخر ظهور آخر ظهور + آخر ظهور قبل قليل قم بدعوة صديق بحث شامل آخر ظهور كان قريب @@ -493,11 +496,17 @@ اطلب رمز المرور إذا غبت فترة محددة من الزمن. خلال %1$s معطّل + قم بالفتح بالبصمة + قم بتأكيد البصمة للإستمرار + حساس اللمس + لم يتم التعرف على البصمة. حاول مرة أخرى شارك المقاطع المرئية والصور في هذه المحادثة لتستطيع الوصول إليها من أية جهاز من أجهزتك الملفات المشاركة الوسائط المشتركة الروابط المشاركة + الموسيقى المشتركة + قم بإرسال مقاطع موسيقية لهذه المحادثة ليمكنك الوصول إليها من أجهزتك الأخرى. شارك الملفات والمستندات في هذه المحادثة لتستطيع الوصول إليها من أية جهاز من أجهزتك شارك الروابط في هذه المحادثة لتستطيع الوصول إليها من أية جهاز من أجهزتك @@ -745,6 +754,12 @@ .Sorry, this feature is currently not available in your country لا يوجد حساب تيليجرام بهذا الاسم. هذا البوت لا يستطيع الدخول للمجموعات. + + تيليجرام يحتاج للسماح له بالوصول لجهات الاتصال الخاصة بك لتتمكن من محادثة أصدقائك من كافة أجهزتك. + تيليجرام يحتاج للسماح له بالوصول للذاكرة الخاصة بك لتتمكن من إرسال وحفظ الصور، المقاطع المرئية، الموسيقى وغيرها من الوسائط. + تيليجرام يحتاج للسماح له بالوصول للمايكروفون الخاص بك لتتمكن من إرسال رسائل صوتية. + تيليجرام يحتاج للسماح له بالوصول لمكانك لتتمكن من مشاركته مع أصدقائك من خلاله. + الإعدادات تيليجرام سريع @@ -882,6 +897,18 @@ %1$d صور %1$d صور %1$d صور + آخر ظهور قبل %1$d دقيقة + آخر ظهور قبل %1$d دقيقة + آخر ظهور قبل %1$d دقيقة + آخر ظهور قبل %1$d دقيقة + آخر ظهور قبل %1$d دقيقة + آخر ظهور قبل %1$d دقيقة + آخر ظهور قبل %1$d ساعة + آخر ظهور قبل %1$d ساعة + آخر ظهور قبل %1$d ساعة + آخر ظهور قبل %1$d ساعة + آخر ظهور قبل %1$d ساعة + آخر ظهور قبل %1$d ساعة %1$d رسالة معاد توجيهها الرسالة المعاد توجيهها @@ -949,6 +976,6 @@ h:mm a %1$s الساعة %2$s - تم تحديث تيليجرام نسخة الآندرويد. الجديد في نسخة 3.2.0:\n\n- إضافة خدمة القنوات - وسيلة جديدة رائعة لإرسال الرسائل الجماعية لعدد لا محدود من الجماهير (تستبدل الرسائل الجماعية القديمة). \n\n- اللاستزادة، اقرأ هنا: https://telegram.org/blog/channels - 614 + تم تحديث تيليجرام على الأندرويد. الجديد في النسخة رقم 3.2.5:\n\n- تحسين للواجهة البصرية للتطبيق\n- دعم للإيموجي الجديدة\n- تحسينات أخرى وإصلاح للثغرات + 647 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index ba2f265df..06a420c65 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -132,6 +132,7 @@ %1$s zum Kanal hinzufügen? Dieser Nutzer hat sich entschieden die Gruppe zu verlassen, deshalb kannst du ihn nicht wieder einladen. Du kannst diesen Nutzer nicht einladen. + Es gibt bereits zu viele Administratoren in diesem Kanal. Du kannst nur die ersten 200 Leute einladen, aber unbegrenzt viele können dem Kanal über den Einladungslink beitreten. un1 hat dich hinzugefügt Du bist dem Kanal beigetreten @@ -147,14 +148,14 @@ %1$s hat eine Datei an den Kanal %2$s gesendet %1$s hat eine Sprachnachricht an den Kanal %2$s gesendet %1$s hat einen Sticker an den Kanal %2$s gesendet - Neue Nachricht im Kanal %1$s - Neues Bild im Kanal %1$s - Neues Video im Kanal %1$s - Kontakt im Kanal %1$s geteilt - Neuer Standort im Kanal %1$s - Neue Datei im Kanal %1$s - Neue Sprachnachricht im Kanal %1$s - Neuer Sticker im Kanal %1$s + %1$s hat eine Nachricht gesendet + %1$s hat ein Bild gesendet + %1$s hat ein Video gesendet + %1$s hat einen Kontakt gesendet + %1$s hat einen Standort gesendet + %1$s hat eine Datei gesendet + %1$s hat eine Sprachnachricht gesendet + %1$s hat einen Sticker gesendet Neue Broadcast Liste Listenname @@ -239,6 +240,7 @@ Sicher, dass du Spam von dieser Gruppe melden willst? Derzeit kannst du nur Kontakten schreiben, die auch deine Nummer haben. Derzeit kannst du nur Kontakte hinzufügen, die auch deine Nummer haben. + https://telegram.org/faq/de#kann-keine-nachrichten-an-nicht-kontakte-senden Mehr Infos %1$s hat den Selbstzerstörungs-Timer auf %2$s gesetzt @@ -289,6 +291,7 @@ online zul. online zul. online + zul. online gerade eben Freunde einladen GLOBALE SUCHE zuletzt kürzlich gesehen @@ -493,11 +496,17 @@ Sperrt App bei Inaktivität automatisch. in %1$s Deaktiviert + Per Fingerabdruck entsperren + Fingerabdruck bestätigen + Berührungssensor + Abdruck nicht erkannt; erneut versuchen Die hier geteilten Bilder und Videos kannst du von jedem deiner Geräte aufrufen. Geteilte Dateien Geteilte Medien Geteilte Links + Geteilte Musik + Die hier geteilten Lieder kannst du von jedem deiner Geräte aufrufen. Die hier geteilten Dateien kannst du von jedem deiner Geräte aufrufen. Die hier geteilten Links kannst du von jedem deiner Geräte aufrufen. @@ -730,7 +739,7 @@ Nachricht an %1$s senden? Wirklich abmelden?\n\nDu kannst Telegram von all deinen Geräten gleichzeitig nutzen.\n\nWichtig: Abmelden löscht deine Geheimen Chats. Sicher, dass du alle anderen Geräte abmelden möchtest? - Diese Gruppe wirklich löschen und verlassen? + Gruppe löschen und verlassen? Möchtest du wirklich diesen Chat löschen? Wirklich die eigenen Kontaktinformationen teilen? Diesen Kontakt wirklich blockieren? @@ -745,6 +754,12 @@ Verzeihung, diese Funktion ist derzeit in deinem Land nicht verfügbar. Kein Konto mit diesem Benutzernamen Keine Gruppen mit diesem Bot möglich + + Telegram benötigt Zugriff auf deine Kontakte um dich auf all denen Geräten mit deinen Freunden zu verbinden. + Telegram benötigt Zugriff auf deinen Speicher, damit du Bilder, Videos und Musik senden und speichern kannst. + Telegram benötigt Zugriff auf dein Mikrofon, damit du Sprachnachrichten senden kannst. + Telegram benötigt Zugriff auf deinen Standort, damit du ihn mit Freunden teilen kannst. + EINSTELLUNGEN Telegram Schnell @@ -882,6 +897,18 @@ %1$d Bilder %1$d Bilder %1$d Bilder + zul. online vor %1$d Minuten + zul. online vor %1$d Minute + zul. online vor %1$d Minuten + zul. online vor %1$d Minuten + zul. online vor %1$d Minuten + zul. online vor %1$d Minuten + zul. online vor %1$d Stunden + zul. online vor %1$d Stunde + zul. online vor %1$d Stunden + zul. online vor %1$d Stunden + zul. online vor %1$d Stunden + zul. online vor %1$d Stunden %1$d angehängten Nachrichten Angehängte Nachricht @@ -949,6 +976,6 @@ h:mm a %1$s um %2$s - Telegram für Android wurde aktualisiert. Neu in Version 3.2.0:\n\n- Kanäle: Du kannst nun Nachrichten an eine unbegrenzte Anzahl von Leuten schicken (ersetzen die Verteilerlisten).\n\n Mehr Infos über dieses Update: https://telegram.org/blog/channels - 614 + Telegram für Android wurde aktualisiert. Neu in Version 3.2.5:\n\n- Neue Animationen und optische Verbesserungen\n- Neue Emoji\n- Sonstige Verbesserungen und Fehlerbehebungen + 647 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 39936a5f5..0b5b7a4d7 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -132,6 +132,7 @@ ¿Añadir a %1$s al canal? Lo sentimos, este usuario decidió dejar el grupo, así que no puedes invitarlo otra vez. Lo sentimos, no puedes añadir a este usuario a canales. + Lo sentimos, hay demasiados administradores en el canal. Lo sentimos, sólo puedes añadir a los primeros 200 miembros a un canal. Sin embargo, una cantidad ilimitada de personas pueden unirse por el enlace del canal. un1 te añadió a este canal Te uniste al canal @@ -147,14 +148,14 @@ %1$s envió un archivo al canal %2$s %1$s envió un audio al canal %2$s %1$s envió un sticker al canal %2$s - Nuevo mensaje en el canal %1$s - Nueva foto en el canal %1$s - Nuevo vídeo en el canal %1$s - Contacto compartido en el canal %1$s - Nueva ubicación compartida en el canal %1$s - Nuevo archivo compartido en el canal %1$s - Nueva nota de voz compartida en el canal %1$s - Nuevo sticker compartido en el canal %1$s + %1$s publicó un mensaje + %1$s publicó una foto + %1$s publicó un vídeo + %1$s publicó un contacto + %1$s publicó una ubicación + %1$s publicó un archivo + %1$s publicó un mensaje de voz + %1$s publicó un sticker Nueva difusión Nombre de la lista @@ -238,7 +239,8 @@ ¿Quieres reportar a este usuario como spam? ¿Quieres reportar a este grupo como spam? Lo sentimos, por ahora puedes enviar mensajes sólo a contactos mutuos. - Lo sentimos, por ahora sólo puedes añadir a contactos mutuos a un grupo. + Lo sentimos, por ahora sólo puedes añadir contactos mutuos a un grupo. + https://telegram.org/faq/es#no-puedo-enviar-mensajes-a-quienes-no-son-mis-contactos Más información %1$s activó la autodestrucción en %2$s @@ -289,6 +291,7 @@ en línea últ. vez últ. vez el + últ. vez hace un momento Invitar a amigos BÚSQUEDA GLOBAL últ. vez recientemente @@ -315,7 +318,7 @@ Compartir enlace Cualquiera que tenga Telegram instalada podrá unirse a tu grupo siguiendo este enlace. - Todos los archivos + Multimedia Ajustes Añadir miembro Eliminar y dejar el grupo @@ -493,11 +496,17 @@ El bloqueo se activará transcurrido este tiempo. en %1$s Desactivado + Desbloquear con la huella digital + Confirma la huella digital para continuar + Sensor táctil + Huella digital no reconocida. Reinténtalo Comparte fotos y vídeos en este chat y accede a ellos desde cualquier dispositivo. Archivos Multimedia Enlaces + Música + Comparte música en este chat y accede a ella desde cualquier dispositivo. Comparte archivos en este chat y accede a ellos desde cualquier dispositivo. Comparte enlaces en este chat y accede a ellos desde cualquiera de tus dispositivos. @@ -745,6 +754,12 @@ Lo sentimos, esta característica no está disponible en tu país actualmente. No hay ninguna cuenta de Telegram con este alias. Este bot no puede unirse a grupos. + + Telegram necesita el acceso a tus contactos, para que puedas comunicarte con ellos en todos tus dispositivos. + Telegram necesita acceso a tu almacenamiento, para que puedas enviar y guardar fotos, vídeos, música y otros archivos. + Telegram necesita acceso a tu micrófono, para que puedas enviar mensajes de voz. + Telegram necesita acceso a tu ubicación, para que puedas compartirla con tus amigos. + AJUSTES Telegram Rápida @@ -882,6 +897,18 @@ %1$d fotos %1$d fotos %1$d fotos + últ. vez hace %1$d minutos + últ. vez hace %1$d minuto + últ. vez hace %1$d minutos + últ. vez hace %1$d minutos + últ. vez hace %1$d minutos + últ. vez hace %1$d minutos + últ. vez hace %1$d horas + últ. vez hace %1$d hora + últ. vez hace %1$d horas + últ. vez hace %1$d horas + últ. vez hace %1$d horas + últ. vez hace %1$d horas %1$d mensajes adjuntos Mensaje adjunto @@ -949,6 +976,6 @@ h:mm a %1$s a las %2$s - Telegram para Android ha sido actualizada. Novedades en la versión 3.2.0\n\n- Presentamos los Canales - una nueva gran forma de difundir tus mensajes a audiencias ilimitadas (reemplaza a las antiguas difusiones).\n\n Conoce más: https://telegram.org/blog/channels - 614 + Telegram para Android ha sido actualizada. Novedades en la versión 3.2.5:\n\n- Nuevas animaciones y muchas mejoras visuales\n- Soporte para los nuevos emojis\n- Otras mejoras y correcciones de errores + 647 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 73586f5b2..803b8fb98 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -112,7 +112,7 @@ Foto del canale rimossa Nome del canale cambiato in un2 un1 ti ha aggiunto al canale un2 - Spiacenti, hai creato troppi canali pubblici. Puoi o creare un canale privato o eliminare uno dei tuoi precedenti canali per poi crearne un altro. + Spiacenti, hai creato troppi canali pubblici. Puoi creare un canale privato o eliminare un tuo canale pubblico. Moderatore Creatore Amministratore @@ -132,6 +132,7 @@ Aggiungere %1$s al canale? Spiacenti, questo utente ha deciso di lasciare il gruppo, quindi non puoi reinvitarlo. Spiacenti, non puoi aggiungere questo utente ai canali. + Spiacenti, troppi amministratori in questo canale. Spiacenti, puoi aggiungere solo i primi 200 membri a un canale. Ricorda che un numero illimitato di persone potrebbe unirsi tramite il link del canale. un1 ti ha aggiunto a questo canale Ti sei unito al canale @@ -147,14 +148,14 @@ %1$s ha inviato un file al canale %2$s %1$s ha inviato un audio al canale %2$s %1$s ha inviato uno sticker al canale %2$s - Nuovo messaggio nel canale %1$s - Nuova foto nel canale %1$s - Nuovo video nel canale %1$s - Contatto condiviso nel canale %1$s - Nuova posizione condivisa nel canale %1$s - Nuovo file condiviso nel canale %1$s - Nuova nota vocale condivisa nel canale %1$s - Nuovo sticker condiviso nel canale %1$s + %1$s ha pubblicato un messaggio + %1$s ha pubblicato una foto + %1$s ha pubblicato un video + %1$s ha pubblicato un contatto + %1$s ha pubblicato una posizione + %1$s ha pubblicato un file + %1$s ha pubblicato un messaggio vocale + %1$s ha pubblicato uno sticker Nuova lista broadcast Inserisci il nome della lista @@ -239,6 +240,7 @@ Sei sicuro di voler segnalare dello spam in questo gruppo? Spiacenti, ma al momento puoi scrivere solo a contatti in comune. Spiacenti, ma al momento puoi aggiungere ai gruppi solo a contatti in comune. + https://telegram.org/faq/it#non-posso-inviare-messaggi-a-chi-non-far-parte-dei-miei-contatti Più info %1$s ha impostato il timer di autodistruzione a %2$s @@ -289,6 +291,7 @@ in linea ultimo accesso ultimo accesso + ultimo accesso adesso Invita amici RICERCA GLOBALE ultimo accesso di recente @@ -350,7 +353,7 @@ Un username deve avere almeno 5 caratteri. Il massimo per un username è 32 caratteri. Spiacenti, un username non può iniziare con un numero. - Puoi scegliere un username su ]]>Telegram]]>. Se lo fai, le altre persone potranno trovarti tramite questo nome utente e contattarti senza conoscere il tuo numero di telefono.
]]>Puoi usare ]]>a–z]]>, ]]>0–9]]> e underscore. La lunghezza minima è di ]]>5]]> caratteri.
+ Puoi scegliere un username su ]]>Telegram]]>. Se lo fai, le altre persone potranno trovarti tramite questo username e contattarti senza conoscere il tuo numero di telefono.
]]>Puoi usare ]]>a–z]]>, ]]>0–9]]> e underscore. La lunghezza minima è di ]]>5]]> caratteri.
Controllo l\'username... %1$s è disponibile. Nessuno @@ -493,11 +496,17 @@ Richiede il codice se lontano per del tempo. tra %1$s Disabilitato + Sblocca con impronta digitale + Conferma impronta digitale per continuare + Sensore touch + Impronta digitale non riconosciuta. Riprova Condividi foto e video in questa chat e accedi ad essi da ogni tuo dispositivo. File condivisi Media condivisi Link condivisi + Musica condivisa + Condividi musica in questa chat e accedi ad essa da ogni tuo dispositivo. Condividi file e documenti in questa chat e accedi ad essi da ogni tuo dispositivo. Condividi link in questa chat ed accedi ad essi da ogni tuo dispositivo. @@ -745,6 +754,12 @@ Spiacenti, questa funzione non è disponibile nel tuo paese. Non esiste alcun account Telegram con questo username. Questo bot non può unirsi ai gruppi. + + Telegram deve accedere ai tuoi contatti per poterti connettere con i tuoi amici su tutti i tuoi dispositivi. + Telegram deve accedere alla tua memoria per poter inviare e salvare foto,video, musica e altri media. + Telegram deve accedere al microfono per poter inviare messaggi vocali. + Telegram deve accedere alla tua posizione per poterla condividere con i tuoi amici. + IMPOSTAZIONI Telegram Veloce @@ -882,6 +897,18 @@ %1$d foto %1$d foto %1$d foto + ultimo accesso %1$d minuti fa + ultimo accesso %1$d minuto fa + ultimo accesso %1$d minuti fa + ultimo accesso %1$d minuti fa + ultimo accesso %1$d minuti fa + ultimo accesso %1$d minuti fa + ultimo accesso %1$d ore fa + ultimo accesso %1$d ora fa + ultimo accesso %1$d ore fa + ultimo accesso %1$d ore fa + ultimo accesso %1$d ore fa + ultimo accesso %1$d ore fa %1$d messaggi inoltrati Messaggio inoltrato @@ -949,6 +976,6 @@ h:mm a %1$s alle %2$s - Telegram per Android si è aggiornato. Nuovo nella versione 3.2.0:\n\n- Nuovi Canali - una nuova modalità per diffondere i tuoi messaggi ad un pubblico infinito (rimpiazzano le vecchie liste broadcast).\n\nPiù info: https://telegram.org/blog/channels - 614 + Telegram per Android si è aggiornato. Nuovo nella versione 3.2.5:\n\n- Nuove animazioni e miglioramenti di interfaccia\n- Supporto per le nuove emoji\n- Altri miglioramenti e risoluzione di problemi + 647 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 7434f8a4e..3c48a77c3 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -132,6 +132,7 @@ %1$s 님을 이 채널에 추가할까요 해당 유저가 스스로 채널에서 퇴장을 하여 다시 초대할 수 없습니다. 죄송합니다, 이 유저를 채널에 추가 할 수 없습니다. + 죄송합니다, 채널에 너무 많은 관리자가 있습니다. 죄송합니다, 채널에는 첫 200명까지만 초대가 가능합니다. 채널 링크를 통하여 무제한 입장이 가능합니다. 이 채널에 un1님이 초대하였습니다. 채널에 참여하였습니다. @@ -147,14 +148,14 @@ %1$s님이 %2$s 채널에 파일을 보냈습니다 %1$s님이 %2$s 채널에 오디오를 보냈습니다 %1$s님이 %2$s 채널에 스티커를 보냈습니다 - %1$s채널에 새 메시지가 있습니다. - %1$s채널에 새 사진이 있습니다. - %1$s채널에 새 비디오가 있습니다. - %1$s채널에 새 연락처가 있습니다. - %1$s채널에 새 위치가 있습니다. - %1$s채널에 새 파일이 있습니다. - %1$s채널에 새 음성 메시지가 있습니다. - %1$s채널에 새 스티커가 있습니다. + %1$s 님이 메시지를 보냈습니다 + %1$s 님이 사진을 보냈습니다 + %1$s 님이 동영상을 보냈습니다 + %1$s님이 연락처를 공유했습니다 + %1$s님이 위치를 보냈습니다 + %1$s 님이 파일을 보냈습니다 + %1$s님이 음성메시지를 보냈습니다 + %1$s님이 스티커를 보냈습니다 새 단체 메시지 리스트 리스트 이름을 입력하세요 @@ -239,6 +240,7 @@ 이 그룹 메시지를 스팸신고 하시겠습니까? 죄송합니다, 서로 연락처가 추가된 경우에만 메시지 전송이 가능합니다. 죄송합니다, 서로 연락처가 추가된 경우에만 그룹에 구성원을 추가 할 수 있습니다. + https://telegram.org/faq#can-39t-send-messages-to-non-contacts 더 보기 %1$s님이 자동삭제를 %2$s 후로 설정했습니다 @@ -289,6 +291,7 @@ 온라인 마지막 접속: 마지막 접속: + 방금 전에 확인 친구 초대 전체 검색 최근에 접속 @@ -493,11 +496,17 @@ 일정 시간 후에 잠금코드 활성화 %1$s 후에 비활성화됨 + 지문으로 언락하기 + 지문인식 후 진행해주세요 + 터치 센서 + 지문인식이 실패하였습니다. 다시 시도해주세요. 이 채팅방에서 사진이나 동영상을 공유하면 다른 기기에서도 보실 수 있습니다. 공유한 파일 공유된 미디어 공유한 링크 + 공유된 음악 + 이 채팅방에서 음악을 공유하면 다른 기기에서도 보실 수 있습니다. 이 채팅방에서 파일이나 문서를 공유하면 다른 기기에서도 보실 수 있습니다. 이 채팅방에서 파일이나 문서를 공유하면 다른 기기에서도 보실 수 있습니다. @@ -745,6 +754,12 @@ 이 기능은 회원님의 국가에서는 사용할 수 없습니다. 입력된 아이디와 일치하는 텔레그램 계정이 없습니다. 이 봇은 그룹에 참여 할 수 없습니다. + + Telegram은 여러 기기에서 친구와 메시지를 주고받을 수 있도록 회원님의 연락처 접근이 필요합니다. + Telegram은 사진, 비디오, 음악 및 다양한 미디어를 공유 및 저장하기 위하여 스토리지 접근이 필요합니다. + Telegram이 음성 메시지를 보내기 위하여 마이크에 대한 접근이 필요합니다. + Telegram이 위치를 친구분들과 공유하기 위해 위치에 대한 접근 권한을 필요로 합니다. + 설정 텔레그램 눈부신 속도 @@ -882,6 +897,18 @@ %1$d 개의 사진 %1$d 개의 사진 %1$d 개의 사진 + %1$d 분 전에 확인 + %1$d 분 전에 확인 + %1$d 분 전에 확인 + %1$d 분 전에 확인 + %1$d 분 전에 확인 + %1$d 분 전에 확인 + %1$d 시간 전에 확인 + %1$d 시간 전에 확인 + %1$d 시간 전에 확인 + %1$d 시간 전에 확인 + %1$d 시간 전에 확인 + %1$d 시간 전에 확인 %1$d 개의 전달된 메시지 전달된 메시지 @@ -949,6 +976,6 @@ a h:mm %1$s %2$s - 텔레그램 안드로이드 버전이 업데이트 되었습니다. 새로운 버전은 3.2.0 입니다:\n\n-- 채널을 소개합니다. - 인원제한 없이 단체 메시지를 보낼 수 있는 새롭고 멋진 기능입니다. (기존 단체 메시지 대체)\n\nhttps://telegram.org/blog/channels에서 자세한 사항을 알아보세요. - 614 + 텔레그램 안드로이드 버전이 업데이트 되었습니다. 새로운 버전은 3.2.5 입니다:\n\n- 새로운 애니메이션 및 다양한 비쥬얼 향상\n- 신규 이모티콘 지원\n- 기타 기능 향상 및 버그 수정 + 647 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index 214c19890..745f4f335 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -101,9 +101,9 @@ Beheerders Kanaal verwijderen Kanaal verwijderen - Kanaal echt verwijderen? Berichten worden gewist en alle deelnemers worden verwijderd. + Kanaal echt verwijderen? Berichten worden gewist en alle deelnemers verwijderd. Kanaal echt verlaten? - Je raakt alle berichten in de kanaal kwijt. + Je raakt alle berichten in dit kanaal kwijt. Wijzig Als je een publieke link voor je kanaal instelt kan iedereen deze vinden en deelnemen via de zoekfunctie.\n\nStel geen link in als je je kanaal privé wilt houden. Stel een link in voor je publieke kanaal, om deze vindbaar te maken via de zoekfunctie en te delen met anderen.\n\nWil je dit niet dan kun je een privé-kanaal aanmaken. @@ -111,7 +111,7 @@ Kanaalfoto bijgewerkt Kanaalfoto verwijderd Kanaalnaam gewijzigd naar un2 - un1 heeft je toegevoegd aan kanaal un2 + un1 heeft je toegevoegd aan het kanaal un2 Het maximale aantal publieke kanalen is bereikt. Je kunt een privé-kanaal maken of een kanaal verwijderen om een nieuwe te maken. Moderator Maker @@ -132,12 +132,13 @@ %1$s toevoegen aan het kanaal? Deze gebruiker heeft de groep verlaten. Je kunt hem/haar niet meer uitnodigen. Je kunt deze gebruiker niet toevoegen aan kanalen. + Maximaal aantal administrators bereikt. Je kunt 200 deelnemers handmatig toevoegen aan een kanaal. Een ongelimiteerd aantal mensen kan deelnemen via de link van het kanaal. un1 heeft je toegevoegd aan dit kanaal Je neemt deel aan het kanaal Verwijderen uit kanaal Je hebt alleen leesrechten in dit kanaal. - %1$s heeft je toegevoegd aan kanaal %2$s + %1$s heeft je toegevoegd aan het kanaal %2$s Kanaalfoto van %1$s bijgewerkt %1$s heeft een bericht gestuurd naar het kanaal %2$s %1$s heeft een foto gestuurd naar het kanaal %2$s @@ -147,14 +148,14 @@ %1$s heeft een bestand gestuurd naar het kanaal %2$s %1$s heeft een geluidsbestand gestuurd naar het kanaal %2$s %1$s heeft een sticker gestuurd naar het kanaal %2$s - Nieuw bericht in het kanaal %1$s - Nieuwe foto in het kanaal %1$s - Nieuwe video in het kanaal %1$s - Contact gedeeld in het kanaal %1$s - Nieuwe locatie gedeeld in het kanaal %1$s - Nieuw bestand gedeeld in het kanaal %1$s - Nieuw geluidsbestand gedeeld in het kanaal %1$s - Nieuwe sticker gedeeld in het kanaal %1$s + %1$s plaatste een bericht + %1$s plaatste een foto + %1$s plaatste een video + %1$s plaatste een contact + %1$s plaatste een locatie + %1$s plaatste een bestand + %1$s plaatste een spraakbericht + %1$s plaatste een sticker Nieuwe verzendlijst Naam van lijst @@ -239,6 +240,7 @@ Spam van deze groep echt melden? Je kunt momenteel alleen berichten sturen aan onderlingen contacten. Je kunt momenteel alleen onderlinge contacten aan groepen toevoegen + https://telegram.org/faq#can-39t-send-messages-to-non-contacts Meer informatie %1$s heeft de zelfvernietigingstimer ingesteld op %2$s @@ -289,6 +291,7 @@ online gezien gezien + laatst gezien zojuist Vrienden uitnodigen WERELDWIJD ZOEKEN recent gezien @@ -405,7 +408,7 @@ Contact lid van Telegram PEBBLE Taal - De ondersteuning van Telegram wordt gedaan door vrijwilligers. We doen ons best om zo snel mogelijk te antwoorden.
]]>Bekijk ook de veelgestelde vragen]]>: Hierhier staan de antwoorden op de meeste vragen en belangrijke tips voor het oplossen van problemen]]>.
+ De ondersteuning van Telegram wordt gedaan door vrijwilligers. We doen ons best om zo snel mogelijk te antwoorden.
]]>Bekijk ook de veelgestelde vragen]]>: Hier staan de antwoorden op de meeste vragen en belangrijke tips voor het oplossen van problemen]]>.
Vraag een vrijwilliger Veelgestelde vragen https://telegram.org/faq @@ -493,11 +496,17 @@ Vraag om toegangscode indien afwezig over %1$s Uitgeschakeld + Ontgrendel met vingerafdruk + Vingerafdruk bevestigen + Vingerafdruksensor + Vingerafdruk niet herkend, probeer opnieuw Deel foto\'s en video\'s in deze chat om ze op al je apparaten te kunnen benaderen. Gedeelde bestanden Gedeelde media Gedeelde links + Gedeelde muziek + Deel muziek in deze chat om ze op al je apparaten te kunnen benaderen. Deel bestanden en documenten in deze chat om ze op al je apparaten te kunnen benaderen. Deel links in deze chat om ze op al je apparaten te kunnen benaderen. @@ -745,6 +754,12 @@ Sorry, deze functie is momenteel niet beschikbaar in jouw land. Er is geen Telegram-account met deze gebruikersnaam. Deze bot kan geen groepslid worden. + + Telegram heeft toegang tot je contacten nodig zodat je kan chatten met je vrienden vanaf al je apparaten. + Telegram heeft toegang tot je opslaggeheugen nodig zodat je foto\'s, video\'s, muziek en andere media kunt opslaan en versturen. + Telegram heeft toegang tot je microfoon nodig om spraakberichten te kunnen verzenden. + Telegram heeft toegang tot je locatie nodig om deze te kunnen delen met je vrienden. + INSTELLINGEN Telegram Snel @@ -793,7 +808,7 @@ %1$d berichten %1$d berichten %1$d reacties - %1$d reacties + %1$d reactie %1$d reacties %1$d reacties %1$d reacties @@ -882,6 +897,18 @@ %1$d foto\'s %1$d foto\'s %1$d foto\'s + laatst gezien %1$d minuten geleden + laatst gezien %1$d minuut geleden + laatst gezien %1$d minuten geleden + laatst gezien %1$d minuten geleden + laatst gezien %1$d minuten geleden + laatst gezien %1$d minuten geleden + laatst gezien %1$d uur geleden + laatst gezien %1$d uur geleden + laatst gezien %1$d uur geleden + laatst gezien %1$d uur geleden + laatst gezien %1$d uur geleden + laatst gezien %1$d uur geleden Bijlage: %1$d berichten Bijlage: 1 bericht @@ -949,6 +976,6 @@ h:mm a %1$s om %2$s - Telegram voor Android is bijgewerkt. Nieuw in versie 3.2.0:\n\n- Nieuw, kanalen - een perfecte manier om berichten naar een ongelimiteerd publiek te versturen (vervangt de oude verzendlijsten).\n\nMeer over deze update: https://telegram.org/blog/channels - 614 + Telegram voor Android is bijgewerkt. Nieuw in versie 3.2.5:\n\n- Nieuwe animaties en andere visuele verbeteringen\n- Ondersteuning voor nieuwe Emoji\n-Tijdsaanduiding voor laatst gezien gelijk aan iOS\n-Probleemoplossing en andere verbeteringen + 647 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index 594158f59..8b4c7b15b 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -132,6 +132,7 @@ Adicionar %1$s ao canal? Desculpe, esse usuário decidiu sair do grupo, você não pode adicioná-lo novamente. Desculpe, você não pode adicionar esse usuário em canais. + Desculpe, muitos administradores nesse canal. Desculpe, você só pode adicionar os primeiros 200 membros ao canal. Note que um número ilimitado de pessoas podem entrar via link do canal. un1 adicionou você ao canal Você entrou no canal @@ -147,14 +148,14 @@ %1$s enviou um arquivo ao canal %2$s %1$s enviou um áudio ao canal %2$s %1$s enviou um sticker ao canal %2$s - Nova mensagem no canal %1$s - Nova foto no canal %1$s - Novo vídeo no canal %1$s - Contato compartilhado no canal %1$s - Nova localização compartilhada no canal %1$s - Novo arquivo compartilhado no canal %1$s - Nova mensagem de voz compartilhada no canal %1$s - Novo sticker compartilhado no canal %1$s + %1$s postou uma mensagem + %1$s postou uma foto + %1$s postou um vídeo + %1$s postou um contato + %1$s postou uma foto + %1$s postou um arquivo + %1$s postou uma mensagem de voz + %1$s postou um sticker Nova Lista de Transmissão Digite o nome da lista @@ -239,6 +240,7 @@ Você tem certeza que deseja reportar esse grupo por spam? Desculpe, você pode enviar mensagens somente para contatos mútuos no momento. Desculpe, você só pode adicionar contatos mútuos à grupos no momento. + https://telegram.org/faq/br#no-consigo-enviar-mensagens-para-no-contatos Mais informações %1$s estabeleceu o tempo de autodestruição para %2$s @@ -289,6 +291,7 @@ online visto visto + visto agora mesmo Convidar Amigos BUSCA GLOBAL visto recentemente @@ -301,7 +304,7 @@ Digite o nome do grupo Nome do grupo %1$d/%2$d membros - Você deseja entrar no chat \'%1$s1? + Você deseja entrar no chat \'%1$s\'? Desculpe, este grupo já está lotado. Desculpe, esse chat não existe. Link copiado para área de transferência @@ -493,11 +496,17 @@ Requisitar senha se estiver ausente por muito tempo. em %1$s Desativado + Desbloquear com Impressão Digital + Confirme a impressão digital para continuar + Toque o sensor + Impressão digital não reconhecida. Compartilhar fotos e vídeos no chat e acessá-los em qualquer um de seus dispositivos. Arquivos Compartilhados Mídia Compartilhada Links Compartilhados + Música Compartilhada + Compartilhe músicas nesse chat e os acesse de qualquer um de seus dispositivos. Compartilhar arquivos e documentos no chat e acessá-los de qualquer um de seus dispositivos. Compartilhe links nesse chat e os acesse de qualquer um de seus dispositivos @@ -745,6 +754,12 @@ Desculpe, esta funcionalidade não está disponível para seu país. Não há conta do Telegram com esse nome de usuário Esse bot não pode entrar em grupos. + + Telegram precisa acessar seus contatos para que você possa se conectar aos seus amigos em todos os seus dispositivos. + Telegram precisa acessar seu armazenamento para que você possa enviar e salvar fotos, vídeos, músicas e outras mídias. + Telegram precisa acessar seu microfone para que você possa enviar mensagens de voz. + Telegram precisa acessar sua localização para que você possa compartilhar com seus amigos. + CONFIGURAÇÕES Telegram Rápido @@ -882,6 +897,18 @@ %1$d fotos %1$d fotos %1$d fotos + visto há %1$d minutos + visto há %1$d minuto + visto há %1$d minutos + visto há %1$d minutos + visto há %1$d minutos + visto há %1$d minutos + visto há %1$d horas + visto há %1$d hora + visto há %1$d horas + visto há %1$d horas + visto há %1$d horas + visto há %1$d horas %1$d mensagens encaminhadas Mensagem encaminhada @@ -949,6 +976,6 @@ h:mm a %1$s às %2$s - Telegram para Android foi atualizado. Novidade na versão 3.2.0:\n\n- Introduzindo Canais – Uma grande nova maneira de transmitir suas mensagens, com audiência ilimitada (substitui as antigas Transmissões).\n\nMais sobre a atualização: https://telegram.org/blog/channels - 614 + Telegram para Android foi atualizado. Novidades na versão 3.2.5:\n\n- Novas animações e melhorias no visual\n- Suporte para novos emojis\n- Outras melhorias e resoluções de bugs + 647 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml index 899fcefd2..0ef348354 100644 --- a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml @@ -132,6 +132,7 @@ Adicionar %1$s ao canal? Desculpe, esse usuário decidiu sair do grupo, você não pode adicioná-lo novamente. Desculpe, você não pode adicionar esse usuário em canais. + Desculpe, muitos administradores nesse canal. Desculpe, você só pode adicionar os primeiros 200 membros ao canal. Note que um número ilimitado de pessoas podem entrar via link do canal. un1 adicionou você ao canal Você entrou no canal @@ -147,14 +148,14 @@ %1$s enviou um arquivo ao canal %2$s %1$s enviou um áudio ao canal %2$s %1$s enviou um sticker ao canal %2$s - Nova mensagem no canal %1$s - Nova foto no canal %1$s - Novo vídeo no canal %1$s - Contato compartilhado no canal %1$s - Nova localização compartilhada no canal %1$s - Novo arquivo compartilhado no canal %1$s - Nova mensagem de voz compartilhada no canal %1$s - Novo sticker compartilhado no canal %1$s + %1$s postou uma mensagem + %1$s postou uma foto + %1$s postou um vídeo + %1$s postou um contato + %1$s postou uma foto + %1$s postou um arquivo + %1$s postou uma mensagem de voz + %1$s postou um sticker Nova Lista de Transmissão Digite o nome da lista @@ -239,6 +240,7 @@ Você tem certeza que deseja reportar esse grupo por spam? Desculpe, você pode enviar mensagens somente para contatos mútuos no momento. Desculpe, você só pode adicionar contatos mútuos à grupos no momento. + https://telegram.org/faq/br#no-consigo-enviar-mensagens-para-no-contatos Mais informações %1$s estabeleceu o tempo de autodestruição para %2$s @@ -289,6 +291,7 @@ online visto visto + visto agora mesmo Convidar Amigos BUSCA GLOBAL visto recentemente @@ -301,7 +304,7 @@ Digite o nome do grupo Nome do grupo %1$d/%2$d membros - Você deseja entrar no chat \'%1$s1? + Você deseja entrar no chat \'%1$s\'? Desculpe, este grupo já está lotado. Desculpe, esse chat não existe. Link copiado para área de transferência @@ -493,11 +496,17 @@ Requisitar senha se estiver ausente por muito tempo. em %1$s Desativado + Desbloquear com Impressão Digital + Confirme a impressão digital para continuar + Toque o sensor + Impressão digital não reconhecida. Compartilhar fotos e vídeos no chat e acessá-los em qualquer um de seus dispositivos. Arquivos Compartilhados Mídia Compartilhada Links Compartilhados + Música Compartilhada + Compartilhe músicas nesse chat e os acesse de qualquer um de seus dispositivos. Compartilhar arquivos e documentos no chat e acessá-los de qualquer um de seus dispositivos. Compartilhe links nesse chat e os acesse de qualquer um de seus dispositivos @@ -745,6 +754,12 @@ Desculpe, esta funcionalidade não está disponível para seu país. Não há conta do Telegram com esse nome de usuário Esse bot não pode entrar em grupos. + + Telegram precisa acessar seus contatos para que você possa se conectar aos seus amigos em todos os seus dispositivos. + Telegram precisa acessar seu armazenamento para que você possa enviar e salvar fotos, vídeos, músicas e outras mídias. + Telegram precisa acessar seu microfone para que você possa enviar mensagens de voz. + Telegram precisa acessar sua localização para que você possa compartilhar com seus amigos. + CONFIGURAÇÕES Telegram Rápido @@ -882,6 +897,18 @@ %1$d fotos %1$d fotos %1$d fotos + visto há %1$d minutos + visto há %1$d minuto + visto há %1$d minutos + visto há %1$d minutos + visto há %1$d minutos + visto há %1$d minutos + visto há %1$d horas + visto há %1$d hora + visto há %1$d horas + visto há %1$d horas + visto há %1$d horas + visto há %1$d horas %1$d mensagens encaminhadas Mensagem encaminhada @@ -949,6 +976,6 @@ h:mm a %1$s às %2$s - Telegram para Android foi atualizado. Novidade na versão 3.2.0:\n\n- Introduzindo Canais – Uma grande nova maneira de transmitir suas mensagens, com audiência ilimitada (substitui as antigas Transmissões).\n\nMais sobre a atualização: https://telegram.org/blog/channels - 614 + Telegram para Android foi atualizado. Novidades na versão 3.2.5:\n\n- Novas animações e melhorias no visual\n- Suporte para novos emojis\n- Outras melhorias e resoluções de bugs + 647 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-v21/styles.xml b/TMessagesProj/src/main/res/values-v21/styles.xml index 5f8d4a200..61779ddf7 100644 --- a/TMessagesProj/src/main/res/values-v21/styles.xml +++ b/TMessagesProj/src/main/res/values-v21/styles.xml @@ -1,9 +1,9 @@ Add %1$s to the channel? Sorry, this user decided to leave this group, so you cannot invite them back here. Sorry, you can\'t add this user to channels. + Sorry, too many admins in this channel. Sorry, you can only add the first 200 members to a channel. Note that an unlimited number of people may join via the channel\'s link. un1 added you to this channel You joined the channel @@ -147,14 +148,14 @@ %1$s sent a file to the channel %2$s %1$s sent an audio to the channel %2$s %1$s sent a sticker to the channel %2$s - New message in the channel %1$s - New photo in the channel %1$s - New video in the channel %1$s - Contact shared in the channel %1$s - New location shared in the channel %1$s - New file shared in the channel %1$s - New voice note shared in the channel %1$s - New sticker shared in the channel %1$s + %1$s posted a message + %1$s posted a photo + %1$s posted a video + %1$s posted a contact + %1$s posted a location + %1$s posted a file + %1$s posted a voice message + %1$s posted a sticker New Broadcast List Enter list name @@ -239,6 +240,7 @@ Are you sure you want to report spam from this group? Sorry, you can only send messages to mutual contacts at the moment. Sorry, you can only add mutual contacts to groups at the moment. + https://telegram.org/faq#can-39t-send-messages-to-non-contacts More info %1$s set the self-destruct timer to %2$s @@ -289,6 +291,7 @@ online last seen last seen + last seen just now Invite Friends GLOBAL SEARCH last seen recently @@ -493,11 +496,17 @@ Require passcode if away for a time. in %1$s Disabled + Unlock with Fingerprint + Confirm fingerprint to continue + Touch sensor + Fingerprint not recognized. Try again Share photos and videos in this chat and access them on any of your devices. Shared Files Shared Media Shared Links + Shared Music + Share music in this chat and access them on any of your devices. Share files and documents in this chat and access them on any of your devices. Share links in this chat and access them on any of your devices. @@ -745,6 +754,12 @@ Sorry, this feature is currently not available in your country. There is no Telegram account with this username. This bot can\'t join groups. + + Telegram needs access to your contacts so that you can connect with your friends across all your devices. + Telegram needs access to your storage so that you can send and save photos, videos, music and other media. + Telegram needs access to your microphone so that you can send voice messages. + Telegram needs access to your location so that you can share it with your friends. + SETTINGS Telegram Fast @@ -882,6 +897,18 @@ %1$d photos %1$d photos %1$d photos + last seen %1$d minutes ago + last seen %1$d minute ago + last seen %1$d minutes ago + last seen %1$d minutes ago + last seen %1$d minutes ago + last seen %1$d minutes ago + last seen %1$d hours ago + last seen %1$d hour ago + last seen %1$d hours ago + last seen %1$d hours ago + last seen %1$d hours ago + last seen %1$d hours ago %1$d forwarded messages Forwarded message @@ -949,6 +976,6 @@ h:mm a %1$s at %2$s - Telegram for Android has been updated. New in version 3.2.0:\n\n- Introducing Channels – a great new way to broadcast your messages to unlimited audiences (replaces old Broadcasts).\n\nRead more: https://telegram.org/blog/channels - 614 + Telegram for Android has been updated. New in version 3.2.5:\n\n- New animations and many visual improvements\n- Support for new emoji\n- Other improvements and bug fixes + 647 \ No newline at end of file