From 8233e89daa2f80efb3db8f6ac62a3ccbe5689568 Mon Sep 17 00:00:00 2001 From: DrKLO Date: Mon, 1 Dec 2014 09:56:31 -0800 Subject: [PATCH] Perfect forward secrecy in secret chats, phone change, telegram.me links support --- TMessagesProj/build.gradle | 4 +- .../config/debug/AndroidManifest.xml | 2 +- TMessagesProj/config/foss/AndroidManifest.xml | 2 +- .../config/release/AndroidManifest.xml | 2 +- TMessagesProj/jni/Android.mk | 2 +- TMessagesProj/jni/gif.c | 28 +- .../{libtmessages.3.so => libtmessages.4.so} | Bin 1037088 -> 1037088 bytes .../{libtmessages.3.so => libtmessages.4.so} | Bin 951052 -> 951052 bytes .../{libtmessages.3.so => libtmessages.4.so} | Bin 1624308 -> 1624308 bytes TMessagesProj/src/main/AndroidManifest.xml | 39 +- .../org/telegram/PhoneFormat/PhoneFormat.java | 2 +- .../org/telegram/SQLite/SQLiteDatabase.java | 2 +- .../telegram/android/AndroidUtilities.java | 28 +- .../telegram/android/AppStartReceiver.java | 2 +- .../telegram/android/ContactsController.java | 2 +- .../main/java/org/telegram/android/Emoji.java | 2 +- .../android/GcmBroadcastReceiver.java | 2 +- .../org/telegram/android/ImageLoader.java | 2 +- .../telegram/android/LocaleController.java | 2 +- .../org/telegram/android/MediaController.java | 6 +- .../org/telegram/android/MessageObject.java | 71 +- .../telegram/android/MessagesController.java | 873 +------- .../org/telegram/android/MessagesStorage.java | 91 +- .../org/telegram/android/NativeLoader.java | 2 +- .../android/NotificationsController.java | 2 +- .../android/NotificationsService.java | 2 +- .../org/telegram/android/ScreenReceiver.java | 2 +- .../telegram/android/SecretChatHelper.java | 1756 +++++++++++++++++ .../telegram/android/SendMessagesHelper.java | 719 +------ .../android/VideoEncodingService.java | 2 +- .../{ui => messenger}/ApplicationLoader.java | 7 +- .../messenger/ConnectionsManager.java | 23 +- .../org/telegram/messenger/Datacenter.java | 2 - .../java/org/telegram/messenger/FileLog.java | 1 - .../messenger/FileUploadOperation.java | 2 - .../org/telegram/messenger/RPCRequest.java | 1 + .../org/telegram/messenger/TLClassStore.java | 7 + .../java/org/telegram/messenger/TLRPC.java | 189 +- .../org/telegram/messenger/UserConfig.java | 1 - .../org/telegram/messenger/Utilities.java | 2 - .../ui/ActionBar/ActionBarMenuItem.java | 39 +- .../ui/ActionBar/ActionBarPopupWindow.java | 12 + .../ui/ActionBar/DrawerLayoutContainer.java | 47 +- .../telegram/ui/Adapters/CountryAdapter.java | 2 +- .../ui/Adapters/DialogsSearchAdapter.java | 277 ++- .../org/telegram/ui/Cells/ChatActionCell.java | 2 +- .../org/telegram/ui/Cells/ChatAudioCell.java | 6 +- .../org/telegram/ui/Cells/ChatBaseCell.java | 4 +- .../telegram/ui/Cells/ChatContactCell.java | 2 +- .../org/telegram/ui/Cells/ChatMediaCell.java | 235 +-- .../telegram/ui/Cells/ChatMessageCell.java | 4 +- .../org/telegram/ui/Cells/DialogCell.java | 2 +- .../telegram/ui/Cells/DrawerProfileCell.java | 4 +- .../telegram/ui/Cells/ProfileSearchCell.java | 2 +- .../org/telegram/ui/Cells/TextCheckCell.java | 4 +- .../ui/Cells/TextDetailDocumentsCell.java | 4 +- .../ui/Cells/TextDetailSettingsCell.java | 2 +- .../java/org/telegram/ui/Cells/UserCell.java | 6 +- .../telegram/ui/ChangeChatNameActivity.java | 5 +- .../org/telegram/ui/ChangeNameActivity.java | 7 +- .../org/telegram/ui/ChangePhoneActivity.java | 1089 ++++++++++ .../telegram/ui/ChangePhoneHelpActivity.java | 163 ++ .../telegram/ui/ChangeUsernameActivity.java | 9 +- .../java/org/telegram/ui/ChatActivity.java | 24 +- .../{Views => Components}/AvatarDrawable.java | 11 +- .../{Views => Components}/AvatarUpdater.java | 2 +- .../BackupImageView.java | 2 +- .../ChatActivityEnterView.java | 154 +- .../ui/{Views => Components}/CheckBox.java | 2 +- .../ClippingImageView.java | 2 +- .../ColorPickerView.java | 2 +- .../ui/{Views => Components}/EmojiView.java | 2 +- .../FrameLayoutFixed.java | 2 +- .../ui/{Views => Components}/GifDrawable.java | 2 +- .../HorizontalListView.java | 2 +- .../IdenticonDrawable.java | 29 +- .../{Views => Components}/LayoutListView.java | 2 +- .../{Views => Components}/NumberPicker.java | 2 +- .../PagerSlidingTabStrip.java | 2 +- .../{Views => Components}/PopupAudioView.java | 2 +- .../{Views => Components}/ProgressView.java | 2 +- .../ui/Components/RadialProgress.java | 163 ++ .../ui/{Views => Components}/Scroller.java | 2 +- .../SectionsListView.java | 2 +- .../ui/{Views => Components}/SeekBar.java | 2 +- .../SizeNotifierRelativeLayout.java | 2 +- .../org/telegram/ui/Components/SlideView.java | 52 + .../ui/{Views => Components}/Switch.java | 2 +- .../{Views => Components}/TimerDrawable.java | 2 +- .../telegram/ui/Components/TypefaceSpan.java | 35 + .../TypingDotsDrawable.java | 2 +- .../URLSpanNoUnderline.java | 2 +- .../VideoSeekBarView.java | 2 +- .../VideoTimelineView.java | 2 +- .../org/telegram/ui/ContactAddActivity.java | 56 +- .../org/telegram/ui/ContactsActivity.java | 7 +- .../telegram/ui/CountrySelectActivity.java | 2 +- .../org/telegram/ui/GroupCreateActivity.java | 5 +- .../telegram/ui/GroupCreateFinalActivity.java | 8 +- .../org/telegram/ui/IdenticonActivity.java | 7 +- .../org/telegram/ui/LastSeenActivity.java | 1 + .../java/org/telegram/ui/LaunchActivity.java | 153 +- .../org/telegram/ui/LocationActivity.java | 5 +- .../java/org/telegram/ui/LoginActivity.java | 86 +- .../java/org/telegram/ui/MediaActivity.java | 8 +- .../ui/NotificationsSettingsActivity.java | 7 +- .../org/telegram/ui/PhotoPickerActivity.java | 5 +- .../java/org/telegram/ui/PhotoViewer.java | 6 +- .../ui/PopupNotificationActivity.java | 83 +- .../java/org/telegram/ui/ProfileActivity.java | 21 +- .../ui/ProfileNotificationsActivity.java | 5 +- .../org/telegram/ui/SettingsActivity.java | 13 +- .../org/telegram/ui/VideoEditorActivity.java | 5 +- .../org/telegram/ui/WallpapersActivity.java | 5 +- .../main/res/drawable-hdpi/phone_change.png | Bin 0 -> 3363 bytes .../main/res/drawable-mdpi/phone_change.png | Bin 0 -> 2552 bytes .../main/res/drawable-xhdpi/phone_change.png | Bin 0 -> 4188 bytes .../main/res/drawable-xxhdpi/phone_change.png | Bin 0 -> 6094 bytes .../res/layout-ar/location_view_layout.xml | 2 +- .../src/main/res/layout/chat_layout.xml | 18 +- .../main/res/layout/location_view_layout.xml | 2 +- .../main/res/layout/media_photo_layout.xml | 2 +- .../main/res/layout/media_video_layout.xml | 2 +- .../res/layout/photo_picker_album_layout.xml | 2 +- .../res/layout/photo_picker_photo_layout.xml | 2 +- .../main/res/layout/popup_image_layout.xml | 2 +- .../res/layout/popup_notification_layout.xml | 12 +- .../layout/settings_color_dialog_layout.xml | 2 +- .../res/layout/settings_wallpapers_layout.xml | 2 +- .../layout/settings_wallpapers_other_row.xml | 2 +- .../main/res/layout/video_editor_layout.xml | 4 +- .../src/main/res/values-ar/strings.xml | 20 +- .../src/main/res/values-de/strings.xml | 14 +- .../src/main/res/values-es/strings.xml | 10 +- .../src/main/res/values-it/strings.xml | 24 +- .../src/main/res/values-ko/strings.xml | 10 +- .../src/main/res/values-nl/strings.xml | 160 +- .../src/main/res/values-pt-rBR/strings.xml | 28 +- .../src/main/res/values-pt-rPT/strings.xml | 28 +- .../src/main/res/values-v21/styles.xml | 1 + TMessagesProj/src/main/res/values/strings.xml | 8 + gradle/wrapper/gradle-wrapper.properties | 4 +- 142 files changed, 4842 insertions(+), 2334 deletions(-) rename TMessagesProj/libs/armeabi-v7a/{libtmessages.3.so => libtmessages.4.so} (89%) rename TMessagesProj/libs/armeabi/{libtmessages.3.so => libtmessages.4.so} (85%) rename TMessagesProj/libs/x86/{libtmessages.3.so => libtmessages.4.so} (76%) create mode 100644 TMessagesProj/src/main/java/org/telegram/android/SecretChatHelper.java rename TMessagesProj/src/main/java/org/telegram/{ui => messenger}/ApplicationLoader.java (97%) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/AvatarDrawable.java (96%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/AvatarUpdater.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/BackupImageView.java (98%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/ChatActivityEnterView.java (89%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/CheckBox.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/ClippingImageView.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/ColorPickerView.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/EmojiView.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/FrameLayoutFixed.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/GifDrawable.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/HorizontalListView.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/IdenticonDrawable.java (74%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/LayoutListView.java (98%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/NumberPicker.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/PagerSlidingTabStrip.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/PopupAudioView.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/ProgressView.java (97%) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/Scroller.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/SectionsListView.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/SeekBar.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/SizeNotifierRelativeLayout.java (98%) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/Switch.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/TimerDrawable.java (99%) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/TypingDotsDrawable.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/URLSpanNoUnderline.java (94%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/VideoSeekBarView.java (99%) rename TMessagesProj/src/main/java/org/telegram/ui/{Views => Components}/VideoTimelineView.java (99%) create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/phone_change.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/phone_change.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/phone_change.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/phone_change.png diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 1f144ec1..e5696e53 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -80,7 +80,7 @@ android { defaultConfig { minSdkVersion 8 targetSdkVersion 21 - versionCode 397 - versionName "2.0.5" + versionCode 403 + versionName "2.1.0" } } diff --git a/TMessagesProj/config/debug/AndroidManifest.xml b/TMessagesProj/config/debug/AndroidManifest.xml index dc448b5f..7836674f 100644 --- a/TMessagesProj/config/debug/AndroidManifest.xml +++ b/TMessagesProj/config/debug/AndroidManifest.xml @@ -23,7 +23,7 @@ android:icon="@drawable/ic_launcher" android:label="@string/AppName" android:theme="@style/Theme.TMessages.Start" - android:name="org.telegram.ui.ApplicationLoader" + android:name=".ApplicationLoader" android:hardwareAccelerated="true" android:largeHeap="true"> diff --git a/TMessagesProj/config/foss/AndroidManifest.xml b/TMessagesProj/config/foss/AndroidManifest.xml index 17b3445e..df2d1e24 100644 --- a/TMessagesProj/config/foss/AndroidManifest.xml +++ b/TMessagesProj/config/foss/AndroidManifest.xml @@ -8,7 +8,7 @@ android:icon="@drawable/ic_launcher" android:label="@string/AppName" android:theme="@style/Theme.TMessages.Start" - android:name="org.telegram.ui.ApplicationLoader" + android:name=".ApplicationLoader" android:hardwareAccelerated="true" android:largeHeap="true"> diff --git a/TMessagesProj/config/release/AndroidManifest.xml b/TMessagesProj/config/release/AndroidManifest.xml index 46361638..17c2c245 100644 --- a/TMessagesProj/config/release/AndroidManifest.xml +++ b/TMessagesProj/config/release/AndroidManifest.xml @@ -23,7 +23,7 @@ android:icon="@drawable/ic_launcher" android:label="@string/AppName" android:theme="@style/Theme.TMessages.Start" - android:name="org.telegram.ui.ApplicationLoader" + android:name=".ApplicationLoader" android:hardwareAccelerated="true" android:largeHeap="true"> diff --git a/TMessagesProj/jni/Android.mk b/TMessagesProj/jni/Android.mk index 5c2a6c04..bd2a81f0 100755 --- a/TMessagesProj/jni/Android.mk +++ b/TMessagesProj/jni/Android.mk @@ -2,7 +2,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false -LOCAL_MODULE := tmessages.3 +LOCAL_MODULE := tmessages.4 LOCAL_CFLAGS := -w -std=gnu99 -O2 -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 LOCAL_CFLAGS += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -fno-math-errno LOCAL_CFLAGS += -DANDROID_NDK -DDISABLE_IMPORTGL -fno-strict-aliasing -fprefetch-loop-arrays -DAVOID_TABLES -DANDROID_TILE_BASED_DECODE -DANDROID_ARMV6_IDCT -DHAVE_STRCHRNUL=0 diff --git a/TMessagesProj/jni/gif.c b/TMessagesProj/jni/gif.c index 06b7a628..c47cdbd9 100644 --- a/TMessagesProj/jni/gif.c +++ b/TMessagesProj/jni/gif.c @@ -589,7 +589,7 @@ static jint open(GifFileType *GifFileIn, int Error, int startPos, JNIEnv *env, j return (jint)(Error == 0 ? info : NULL); } -JNIEXPORT jlong JNICALL Java_org_telegram_ui_Views_GifDrawable_getAllocationByteCount(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT jlong JNICALL Java_org_telegram_ui_Components_GifDrawable_getAllocationByteCount(JNIEnv *env, jclass class, jobject gifInfo) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL) { return 0; @@ -602,7 +602,7 @@ JNIEXPORT jlong JNICALL Java_org_telegram_ui_Views_GifDrawable_getAllocationByte return sum; } -JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_reset(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_reset(JNIEnv *env, jclass class, jobject gifInfo) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL) { return; @@ -610,7 +610,7 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_reset(JNIEnv *env, reset(info); } -JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_setSpeedFactor(JNIEnv *env, jclass class, jobject gifInfo, jfloat factor) { +JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_setSpeedFactor(JNIEnv *env, jclass class, jobject gifInfo, jfloat factor) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL) { return; @@ -618,7 +618,7 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_setSpeedFactor(JNI info->speedFactor = factor; } -JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_seekToTime(JNIEnv *env, jclass class, jobject gifInfo, jint desiredPos, jintArray jPixels) { +JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_seekToTime(JNIEnv *env, jclass class, jobject gifInfo, jint desiredPos, jintArray jPixels) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL || jPixels == NULL) { return; @@ -665,7 +665,7 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_seekToTime(JNIEnv } } -JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_seekToFrame(JNIEnv *env, jclass class, jobject gifInfo, jint desiredIdx, jintArray jPixels) { +JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_seekToFrame(JNIEnv *env, jclass class, jobject gifInfo, jint desiredIdx, jintArray jPixels) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL|| jPixels==NULL) { return; @@ -701,7 +701,7 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_seekToFrame(JNIEnv } } -JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_renderFrame(JNIEnv *env, jclass class, jintArray jPixels, jobject gifInfo, jintArray metaData) { +JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_renderFrame(JNIEnv *env, jclass class, jintArray jPixels, jobject gifInfo, jintArray metaData) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL || jPixels == NULL) { return; @@ -752,7 +752,7 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_renderFrame(JNIEnv (*env)->ReleaseIntArrayElements(env, metaData, rawMetaData, 0); } -JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_free(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_free(JNIEnv *env, jclass class, jobject gifInfo) { if (gifInfo == NULL) { return; } @@ -765,7 +765,7 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_free(JNIEnv *env, cleanUp(info); } -JNIEXPORT jstring JNICALL Java_org_telegram_ui_Views_GifDrawable_getComment(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT jstring JNICALL Java_org_telegram_ui_Components_GifDrawable_getComment(JNIEnv *env, jclass class, jobject gifInfo) { if (gifInfo == NULL) { return NULL; } @@ -773,14 +773,14 @@ JNIEXPORT jstring JNICALL Java_org_telegram_ui_Views_GifDrawable_getComment(JNIE return (*env)->NewStringUTF(env, info->comment); } -JNIEXPORT jint JNICALL Java_org_telegram_ui_Views_GifDrawable_getLoopCount(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_GifDrawable_getLoopCount(JNIEnv *env, jclass class, jobject gifInfo) { if (gifInfo == NULL) { return 0; } return ((GifInfo *)gifInfo)->loopCount; } -JNIEXPORT jint JNICALL Java_org_telegram_ui_Views_GifDrawable_getDuration(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_GifDrawable_getDuration(JNIEnv *env, jclass class, jobject gifInfo) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL) { return 0; @@ -793,7 +793,7 @@ JNIEXPORT jint JNICALL Java_org_telegram_ui_Views_GifDrawable_getDuration(JNIEnv return sum; } -JNIEXPORT jint JNICALL Java_org_telegram_ui_Views_GifDrawable_getCurrentPosition(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_GifDrawable_getCurrentPosition(JNIEnv *env, jclass class, jobject gifInfo) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL) { return 0; @@ -811,7 +811,7 @@ JNIEXPORT jint JNICALL Java_org_telegram_ui_Views_GifDrawable_getCurrentPosition return (int) (sum + remainder); } -JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_saveRemainder(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_saveRemainder(JNIEnv *env, jclass class, jobject gifInfo) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL) { return; @@ -819,7 +819,7 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_saveRemainder(JNIE info->lastFrameReaminder = getRealTime() - info->nextStartTime; } -JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_restoreRemainder(JNIEnv *env, jclass class, jobject gifInfo) { +JNIEXPORT void JNICALL Java_org_telegram_ui_Components_GifDrawable_restoreRemainder(JNIEnv *env, jclass class, jobject gifInfo) { GifInfo *info = (GifInfo *)gifInfo; if (info == NULL || info->lastFrameReaminder == ULONG_MAX) { return; @@ -828,7 +828,7 @@ JNIEXPORT void JNICALL Java_org_telegram_ui_Views_GifDrawable_restoreRemainder(J info->lastFrameReaminder = ULONG_MAX; } -JNIEXPORT jint JNICALL Java_org_telegram_ui_Views_GifDrawable_openFile(JNIEnv *env, jclass class, jintArray metaData, jstring jfname) { +JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_GifDrawable_openFile(JNIEnv *env, jclass class, jintArray metaData, jstring jfname) { if (jfname == NULL) { setMetaData(0, 0, 0, D_GIF_ERR_OPEN_FAILED, env, metaData); return (jint) NULL; diff --git a/TMessagesProj/libs/armeabi-v7a/libtmessages.3.so b/TMessagesProj/libs/armeabi-v7a/libtmessages.4.so similarity index 89% rename from TMessagesProj/libs/armeabi-v7a/libtmessages.3.so rename to TMessagesProj/libs/armeabi-v7a/libtmessages.4.so index 6d9c8366b7232ed9892ec09bcdffe389c5c856c6..c38583ba533627a9e80384b78599d77a91af4ccd 100755 GIT binary patch delta 44409 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 diff --git a/TMessagesProj/libs/armeabi/libtmessages.3.so b/TMessagesProj/libs/armeabi/libtmessages.4.so similarity index 85% rename from TMessagesProj/libs/armeabi/libtmessages.3.so rename to TMessagesProj/libs/armeabi/libtmessages.4.so index 98fb21768c8fed373bd7bf41333b75204c075d72..25188ed1368963bf0cf622d822010b31c9079776 100755 GIT binary patch delta 44630 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 delta 44554 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 diff --git a/TMessagesProj/libs/x86/libtmessages.3.so b/TMessagesProj/libs/x86/libtmessages.4.so similarity index 76% rename from TMessagesProj/libs/x86/libtmessages.3.so rename to TMessagesProj/libs/x86/libtmessages.4.so index 61ccbf61fb0eefd3ec0fc18e7389728cfe619af7..e0f20794eae7a9a468c2833dd88457a7b5a4e7d1 100755 GIT binary patch delta 125489 zcmbTf2Y3@l_wPTm(yncaC0jC>F2HmGqJ&;VAXF1XLJt8^LPB?_p#&LBbBw`6gn>|E z0s%q^P6#Z75Jc}pl!OkV1=E6Pq2v1zRxa&HNf}{vj5`B&5uD2z9xZ~6NEZNKGlZfo z4EFb-GFb52U`IbnS_NrYfih%op&2CEag#BpFsR%&uOg9%y zrlcu8c>qiBNovZ(D-2eFvun%5ATszF?3_wTsk$Niyee=`V2o8%jzDe#rG` z2a8Cb2hKLgq?^#U%#Z$Wwj0P)AxH%K&<hz4{@2OR&x0 zd0{N+c1Fu2N96M<#HonmH1gx+N(Y;(7>G~k7lMf_lVsuc2e3<#$yULez$x1(887Vj zg9E=&!UqiZcM|O1PRXY+A---TeTj3w-glqFAQc?$yD?}HKe)AUP!w!GpmSAlY6Lgt zi~;bY$e;r_;CU{Wa@$ds=_0IgkmkHCll%DOVSR~DXFVfXBsd$N-iautu>S#^f@&!s zqBsb4T%#BUq4amSJ@~BPLJFGeIwc81wFIP1P%jfqjHwtyaBgDB+hdO*ogkzqF&_#RSiX8D}+ zBTDv)A@(&m`z0Dm1h5`#ex>taa4NWr(BB1n(V@dN6cvpCz_oN$x_6naa( z{wUFV5*aN@SRo(!$OjUcB@7yXz3>(<9CQRb=SbwB2(Ujm;6VX|{b+F3TLuER!GNZL zNj1;yn3C>Eh#OrrSW$Z*_JEOVkS~EN)k`2)OM`q5+%KY>BtI0;R}%UJu;aBv4ug5a zln3{OJ=!gpzCL(Ng#YCHF!MK0AU0v(g24dK!hEINb76+ygUQxIItz>u73AaKT}YK6 z_$HV^kID$@Uw{v_On~nYo6+^NTP2WR1Xlt3{peq!cAJ2|iO4Ux00vK>vxL<51bdp?|>fXPKkTM45Ps5et0>7oEdz_u)jR1y9wfSuq@g6p{<$blfdMR4*2Xn#Ju zc?JW){$>fJqTnguEEu;C87$?Djmjg@BtL^)^CdDH9gdf98&AIl(?wi}kAR&n11T-i ze|(uIc-uf03Be0+WlUJG4+fBk&4&ZLKyY=iKZ09=Q{UC~AAxPCp|JfZu**|Fwz|7N zMkk^SdOZi}XA#5b9(a7ju;JM+ju-}|z)QhJMEZtcFW4ry3)l~ao1p(s!36z1te+f* zo@R>>d;3F^E1l#@wi+TPe*jyPsPv~>OsXYv2gy4U<{vU}P71d}# z{rm4rz#2H;(fFoVuue>(%2B1)VBCg78Tr*S<>=mPVAvcXw69<3B@`a9>3 z45XyU@EX`T1Q`lF!8V@^GmzcfpBoV-Lg0e{6GAZJs$f?UqqhHQ0nYl&zz<15eK)RO zU?4c71o<~=niS$W;B1^~ETT`X20MHPGEt=80rnj>kbYqFzbJA7g4F2-@=WxB z>tOHS1~LR~%k@vW{!2`6JYul1FdTq0urP2g1ooc73MKS)x&Ewyq>BLBg2|r-az_+! zFxZAu&)a;H%N=AwkaOLj9c5O4T?oJ>9RAE5lr)kY5#V;P{e^)X75aT(AG+L41j_wg z273z|wIkOvZ~*6`Q=$pt&|6(s4WuPMjPe9EAPAt!si-1cSrGElpdG8*f&B*!1m}XF z{cy1PQs(BI?^h^+AwZogC}*b)Z)889b1YsjRou+I-RS2vPTf=hw3z(+sbXx;()WS=$1)1qbHK#3J-vI5#$u!=gq8aIPhjAB4Z*U~f|+@rq75 z8EjjjuN5=FsqY%yWU8q0`4D6w;^D%Jc))*f z{@6%LiVV+#U4x9;Ma2!UAI!I+-2M^RJlJgv4o5D?Ulb0;=&MsPu(`QRW{4731!uRH zNt(!@KG^<&OrphN)Q0OFvUcw415U+F$SP4oW`oV{Niu1T?FtWI83Z|F zWKuvR*a-HHl}RPR2f^75W%5AO*m-bDKbg!Ed>!ogNG7L5jr{`-d@d6lWP<*U#Sp** znPiF@NCdmR5Ihh9I|R;`M)Hr~CSb=aBY7?YNCx}R3F`=b4{$0v={Uikf^De(CRlcP zfkuE`)p1l8`l(>2T_!IC&o9Q0QMh_3BQjXQ4YFnJE^af}3oauP90UizytDHRE`ZI; zbbSEq0CyC60~U?!2rkSQk?(Z-a>X&j*&_tCVc_x%EL_U%T!DrWZu&wR0Jjuje#YHK z=+nTdEA=afxnKvlp-BHd*tbgOEnxF%J&YsV9$Z$~Uo4J#Nr9lI5Zs4B4melvD{wY0 zHm(ZJhr6e&H8LqBI1!u!P7+)J><5R(RxPk|tsFf6@_KZDQ^BQ$eftuamvSHoSNw z2*F{nAIukN9`Pk`AVU8T?D|P}Xefyc!2Be@?F)fZBe*O$D}wFdZ17BB?`{Es{b!k! z7lJNeR|F5>4#45DFc$0sWA_ova3(ka{#o!su;Uk*6c#o11K70*V@2qH180NphS*I` zK#;XfCJr&WZ-9L}WHL-7cn)@WW$oHA9~$2k!8ULzc#*KL1-9*!$tuC^z&>y@!9BQs zS9rzg8bv;ZARB_Oguz&_W49jhOmHeV+=dLC1>Ps@SAku7^!vum;2h7{qPPIxCu^6V zHzBp{M?H#J@i|X*R3eec`Lc_27X*-x_THL+4)LY;btx9d0Ad ziS19BERjMD<>n4f%LE_6hMSE){NTZYmx7&VWU@x^k6?1vbEsHJci^mkOMHTh&&y;f zK6r=A1!sdh34RWC-NphfIJz|cxFBnLszk689Iow(-~c$>+)co)iby9a3~DSmu1pM@Kl}v{92sK7lExM639ow!3u6)Q_;4i>%iVxigwTL1v_y0*-30+ zPJpxPDrAE2f4#IDEmuz=i-q6;3`k#v^b`DoJB0ol!7&)zj(!UHLU2j2tG=GT3LpFp zbo&P2Z14bK-wJGQsA#il2R8&x2*Pv1hhSF(4+N)xn+XS_!Cvq$f~SB}8!6h8f;pTU z>-G%n1HUEgSA$6tg?ud7odZD%1mQ971!sX52!q35dsBss7JLbu15Ti!HoOh?ITXS- zZ@ka^%elKkuxv!M1lbUT=kULvor!M1UVb~s)S_JPj`{WfsQbiF-}CE>z0J5ABXwjTyL;}z0QWEcRG ziHf$Xeg$@de-jR4$|2w{bWQ;Kz<&sR5;)tl)mF;wM-|NzRn`j9)G3N~Jo*sq1)mhD zQo!b^igsa_#_hr3%i*uN9=p(fa;TcV2fLOi=O0`u;>LM^foY=uaJ*Kff|9wuhY-?t-+4(6oM5g*iZYG z$JCGwLAaldhJi1F)49XtinbSD1h#|2_8Y)1aE5TW51hI}Au)n4f>Ty1!8-yzaPDyX z)e4y*^e>Yj2te?Y5EOvtoFDXFS^+%DGpnHVKC| zunUZ1ZZN}IVA~%`@OFpSLo0A#ShTk5>A}-S=u^O15&CHrk$-B0!4eqcM6e3>gTn!w z0tX`W0kF-dXpg6*N+kj&X1E&@3 z;re*6%dgkim*AW$3i(}RxEgHxTM6D4@fz6)_TE+qE(wDHod5^!={4xS0l{5d(L}=m zzs-39Hvgj=D3#GCz~MHtfgKTC3+#;G7GN(p+=RWrz6kv=uwQ4Ke<27!@Tn-lLa^(; zqU}U~=6WzrD!~%$0hY!*KJRry5Qy+SE>pfzr9gtX*asERgGTI1IMJK9ER z3wA4T4j45OtjfM%KRCbOG2A{mN_)&Vn{)dpZSVL!I3*=YyBXZ^7RIlAR21Q1alz3v>xnmU18uT z7p=uT6r2SP>nDS=%SUSq^8&EnbE`6*cGrs5CgCHHrhXW$T{K+)JNiaz*DQ~~cGOn5 z5sg^qQwKzo0V0Y*-~hOR;0oZBh*hBpw~ye?HPOwpA$U(D7z~5x(s-^TwoRkK#D>SO zg5BU8k8bbb`gzgXtiKX$`&!rk3QhsPBmDco-U$88n%H5R=j#S9Vc=NhDO$Cp+cqLb zyRS+@fAf!y(e5Cdg0sfNkV(SthhXzqokxLl@GSqF(9h=f6Jp4(f>(o`6Jtn6QLf$G z{)-rG>OEfz6=RzeqdgqC4}*X^Mr+UL+9+tM&LzQ4aJZko1@?oRiws+W?UQxx0rstp z(N@2aT#t7NdJFrs+8F;?5QLY%c`$IUk0Ck2U^!3lQ;c>h-O3&QtY>f(Y}*(^mJ9nU zTn`Qh^oZ+!iP5f&quxdb1&8%TT0jthAXzx50(NYQA?bpffPLWbRaghGd2@_*T<8b( zd!E15)a|+*quqRd2WiTk7_CEW1*iTKqa8JmfNl3<$Z3(wMKB4(Xt&+>!2ZWE#3JSo zBW`JYFJj0;VPBH-%NT8()v1GqG{1_`Mt)lu;RSRnDh9Mwr{qI0~GV6svXZ8DRgpf&?!<1p`_P4wQ}6dd5#+2kgT=WjELx zk^UsuRyCGHiyBL~0YOgnSZy#r2WNZQ*h|$&b;fG9TxIG(8o|}UUhpYVjwW31S!mC5 z=X8uE*&?_@kUHYcWRl?XVCM(1+Bx|F_p&xt+Zen7r$*@G>!UKD?;vt10nULwybRU^ zlTNYPD;BNl^Nm60Sn{<<&>aRoa5uq2!S*h(+J&nd>;i{3fpfvm#j)@bs@?B-dg#9r zycO)29jnc_e}GfE#%d?u>-CY+*)2AFok*U+Ag8HW>+upM|J1&*q^zisqF{StGbtuA zNCNu?#gbm4c^ZKIBVx5RCK;S_)kJ<2`kvryzllhKhq!ryize+!_(ZUyLm}cohJ2qr zhx3$Jf+w-T{<8|~ni)%qiV^cW*tRZ~U?&jNp91?bW3{9EO|Ts=hSV47-+*(nVzn2X z+=VdZc+bRYPdh4ub8g2H{zfeC;EllM%dw<|;7*)T0|_F-zTg1bJRHC{aMt=*QdiX2 zY_RXgSZ%Ri33hFOK9t@~wn2~$0RjtVcm(VRFB2v7gR_2#)%LW{z|KvvWQWKgUn2yh z#*&Sqgk``k1Q@R3+Tff(Ecsa2CxdMdW5p|9*w_z(z=3yRa)d!D*f-atEqC+4u0AGh zd0Yz){Hu?O-C)~OozH@uV7yQfEYMxB<3()nwHsceuX%cKV_snXU^@XXKtPu_jP2d1E65g+u0sE+liP#G^McxlgeOK@}K~*Cz4e1KxW8 z=j55R%ZFBA-)#h>gdB7QyKb1sV6ljP0`@mEk>?_Sap08ZCbCad?p&^KZ6aMnfmSwk zBciq@?V*th1Jc=~UDq7~=YZ!5hu6VQlz6(}Jg}{+UIQf^2ngI?=o@qHX3`eXZr~Jf zme9N15SRy>w2L$bcJ4EgW5Qr7IOi*q_Dtq5*yk~kRH45C&R%HJX7Q(7Z!;6TYY}XM zg3S;>L$h{;UKZ>sef43n7j-O2AlBkmRIq%UUoCbF8)k~BEPWj73h_K(!*)y(Q zZ|d@#tyjwJwV1UvtM)rcYt^|0I1r)l1olE7?#q3_wg~&rz^UNyj$hyUED`Av-Ym_QLyhFv$o5)0(LYv2ftInyWnlG({r#sO7e9a z`B(~7W8vnAtd*J65L^@NYGWqnMI^1jj<#kpQE+Fl7u;Ax(F;tH%>);@!Dbl(PJQ33 z?e<1<{=iJW73n86$H>Uu6GwWAnRq4)Y@N)+CD;RYQVa2m1k1sWsqusf-o|;Mh5Re{ zEZF{)&iBBn-OQwi@b`@CB@6jb6fnAl8yzbxo-7m&Y%SpM8;kZ}ya_nvYn|T*`+MpR zKLQ8L7Lq82=1{IjfZqsz)4+~J7V<{$a&XFgomDqC=wl}F#!!_V0sE?0NREi`EZDrl zqU}F!fdg6b+LvHngIyn^^BF_wqu+(Uym*pNq)!B=M%Y&e`^QFMCd1jor84yS>T)qW?=JRUH=_81)MMB&rN=W!2f+bzUmXo zUFJf0sKJQzMZo@u^mcI8$Z&eB&W#}; zKg5&mB7hFylnEB?DAphB^2C$RL_lAFv&V)VM3Grw@0xh>M5NCK+a_AbdSS1E{SoO; zfO95@^n7)`!X2!OCs&1oCtx2Oj1&$Ev_b&$^Z+V=y>2sUUkXHOVP&`3l2wZdZ5>^N247ZRSq6XT71H*Lg1158H zheLRJyn)$L^!kZle}unzVEbo!`k%omDV#C>c>wz$aCpr8MXw+q2WOp*C-~M)kgxIt zOXIcsf|uYNHC}s9IJyl2njf!y7p?@@m1@yu%6eeGTjw@l-*nU<@(*V4DL0s=SLqjE z=K?*TnVipJ<`X4c2qxd^RsJ(LYos&Si%v? zx6Dka5(=mw*uN!SJGm7D+v{0KX%Rq0uw$7XKqIhsrA2!j*#(>$!2`hl$rkM(|2f!~ zW0`h^$9*edqxdu-CQlHvi zaQ!cOdbu6^4@8^b+atjyNPr+E!a+r_4Z|e7HZ%pBf7PejwqVEa`pniDoDIG$hGidc z&X4hAsqjAn?EJz)=7<8$024RfL?0mp*$`yy(jBbf34YQYYz6xx92^0sMx?*Sc^}Rt zqKyOKz{Ys;r>J2GcS9+YEZQAXVX&Lb(TANKf~-TjgQj5Lrg(Bs1o#0s00&bA4+5t~ zq@M=PKBlLi2lj4`*UrAHxjkz9eUW}gG9Q0fox)S=IT+-eFbBUe$A{$&&IjVjW>JDi z;FLr0!(_XQKWaZNB-Fh^l>`|200O( zFca)Jt+)9C?qIT&tS%htGt0r|i)Qkp2;fJs7yN_Zt>BbPX0k!>9f0$E8XFj+`fYD?;FnF>N}_(Ie(|In;e0_ zHeGjk9qh%;M0iJZADmK2cbLZ=Wa|N0I)In!Tm$Tl@Ye?HH^veE?NHvQI)k%}7Lpts zmRSD>Kw$S+NFmWFCV(C3@!DZy9@rbLJ6H<#D`5vwWIfn9PfzdV`iS(W!Py1$^nZiB z`7H!r`U;)SUqFz9SG?zlP7?3LA2anDsRm9p>kb-&?J*XDFVX}{)Di3$s;3_acFoY! zPvdOW(|^S|)0f8+dfM3Dc5doY6I}+naTK-Um*TMF!R_(m_80>!!-ysn- z_?qjt$7vH=!Hy{4R-H?L18R^%>;GF2q-@g-8iRdh<4Eb)P=@Wm=HKJAiQ_}A?;TG* z6d4WxJAc#lW58Lz>O7s>Z_#-^nAD6T9r)Kyc&AtaLF$k=ZQ|Jgb~)q76VW8Uf&-uE z`n_OV=QwS>_i_FEaioF>=safx5T4rafL&i;aTA^JUoe@B<=idWFbZ>`A78^ME><@y z*fv||vS9OPdH~hH*`sxR1F)-Ooc5x|yI?X?*LMQjd&iMVVxH*@PC*m6M~D&*=LQjN zX5?95m4gk>6g@=YN z=M!zxh9~I6zX=uU6P>`>5!{5%3UjR#OWpBlruh|G}btyDpRK@vWU+!rwA* z0F0}yV4vH@?cHm2gR@+~^u_2NcM!41lRF{e#un{0atoNiVTN#+1h&Ipn45B5qVK3W zfo-iV1Yeg72G9rW_BGc_Fq|8#vyfWCp&RT1rwh&kJJ;*_HQ+38Sicu+k62C5f_)JI z`~yz?HJ&7iQS!1ADmw>X#abZ*F`bcNy1q>=%K1xu(^wVkkI=UQJ2NcW9~Omcey|C1he!2e&sw{58w#c7oooicFfTOFmyqH5dkEE z0}%mK1KYiN4K#E^;M%FzKpU_#QxBjA*pa0NFa+$2(9Zzd=js70=jkK*&=zpkV!Z~A zfm7zik=mk36HY;p13|nHTm}0)XWLbG+ZSLy6H>h5NV1m4k)K7^v4B%u7Sc~}64r+C*`li!0H>nF*kcC+C<9LUS}$=UFgb|%Gd#P1voXDeE4~ZZek6_z z7yf#4{n0q`iQrG&5Sagn)3%Bu!8s8;3GDR65u>QmFTttREV$na1vDS*TVc_j`+X12 z0^`|0FyKvK*Qq!%SEToX$yuGZ7$E};?FdpVAr5H-|_>uXua;E;be=?XzAW^8`H&f9n}IQv?hcEtRg>)Tqi zL;4KP2mrsp5VZdW?1%j!5%3Cd&fnu6g?%Nt#%te) zISTd{(9>T8d)r$`kMI`~AMyl0S+o;fJ`9Jf2nXfCJ~L`a45J!g^A%jsiU68|y+}V_ zl(-|V z;RRu^jwf(h$Z-+zK5%w51QZ<_=YN1nCku%ZHE;);BOi8PfjYQn5dm4j zDR;2X5*d~S`w$S8fS~=`T;CA=f2&CFE(HGW7BXH0&;{(km36pHhk>(K=sW|Q^Sgz_ zi2zoDoxkb44eZ-tAvJ{lEI4Jm&iBA(_s8foBEmP^V3&oYi3IVz(Pqo_VOAMzMgZYq z*BoqveKS#_zF;2~t1yoR+uw~R`-OfoIOTafv55R;f!$8kqJ2f=8wf~CJ;7RV*2{R( zOa!zY?1O!{Pn_T!VSfqie-%$Ui45+5&08$m7ZzWFvs=Y$6I(tP#(w}ew(CU(C0%f^ z$D&=vy$vSGxHA_HTZ6MlTF5kE?*g0mS+w_jCV~U+>BIC(uzj?J;HP1NZN3DYh0_G$ z2=Ydk8-INeue}Db2L>r)^$o;1Z~zGghy;(o=89JBYqf(>IZ zgBn~94tKhyU`LO5GF|L|+Pfjh`Xrvz5uLCn*f$teC>#s|+lS~pj@yIr)uvzuGr_4N z;lZWKHB)OIt?Zh^+WhI zuz9zBC;kBJ*b}e)bOx^q|6YCbT>xy}uj`9|okuY9h5WloMF_~zcx|Gn56%IHzed{@ z9QXshUJ3=&1Dtvyp6nDn1nm4Xp41XNiR+z(@OAFcn=iA#=FWJ|LPO~ngR{DXueh=P zuY|zc%|eO@gNjDN}&L(;Ow`oWG8QOzW$eoAkf81t_cVA!QNU{vO*;208Xi6CHPU9V3T|Twso^= zKS(thoK@dSN=AkB^SC|U;cOuavs z*Ie+Ag{%?=--7+%@IHP6m^`p(0qp|&9>Rgh;0))-7VX*E1F-jBY|%sw8b3z*=lY?( zDA@dx`^Wg_5m$!5{@OxL2#1ZiL7s(-5e}T-ENUe$1rOkCv}*5Jjs^R`O+*1QczW5Y z{mR~VV25JWo+SMSPKmOT65-3VlMrM@qm4xX_rN(ZR$>+zJ_md8V;>uZJ{mJpYC$XU z3N8$Gn5^V0!Ii*%vz7D|=^Jvr#Y*r)M8N`g0J{oVG5-sL{t)Egr@tx-g9+S0F};Md zz_#Lg3A4EaaQG|ADmc4@ReL$(IM`Xrs=fS?%hTJe+RyY!pCF*pR<~9~aS)`Gv1)t1 zvfvztm6TON5!dJ3O7CPXz-A0HY-B>64s64(n-muO5!eAPBX}@4tDTk95xOa1MBhaPSk?zi-uE;XK0Ae_+*K$hidefu9Qd z$DBLq^MEoCCT<7-A*M^MyDW92jFIX9V{Lr!KUTBdBv; z;t^oyPgc@J^r?y9oQ*oCgUy?*WUmNl&OjvdLlFKMjYTlXk>mo`bzRG;{rFCGADO`z{3`oU>}r)z5(K=dIeEYC)7O z1zb$z@D4c3)7{nEZN6Y7e+lWgkOsg91g`;mFIvgBqFZbNyDsY!#v^blmW|g#;Wayz$646N28*_unRVLIymKDtM+=-0kHWg_9sFw zjX`sQs|aoic7gGmOTqM`z~O(q5aYrA7gll#fAeW3eGK2Vi+|kUtN%*y4d+*ISTvO2 z@PFyA{1?CYFHRVX8Z4ARdZFcbhAqM2e>}hT4hZ~36SNY2#0`q!2M$FQehqGMDlwSG zOdjMd{x4p=aazAGM#eNBJ~U^YQMR2nOL{?2V8eMmQ!ztx0Fcge;9w;L3x!w;4G7p?}u zvMoXyh?I}AfNh?e;`zJliz5F~c4}U~|xH~IzRC)42E+0jccb5$5b2HOs!97p7 zk1c9M%SgATupNzP^L+Ncuks$5%$}-!S%Jp%oV8wvjZ;k3_KqFSHMRS)7meuzsa{_; zwh2w5i`n8PbOAozZb~=c<3>|DMS{^l2i-*{s8yTM3kqGT#+R#PO)TO@a zNax737@O6V4yS9`tFE*?t)RB;MoUxLkPYchC(;G%R(JXq9nT8)K-&6jSP#${rMw$$3SD)(mwPnsZn26voDgDWa)kBA^HL9 z)Q^smE`6vT>PH7e(=lp|A+#DT8!C7A3S(%3q7zuv&*>t%l^yt;)~9orG>$f;16h-C)WHMA4{%pA(oSr{7gP;>lvJlp zLgh$@o3e{;`bhe#iFzWHHZ;(MYV1_HU$(64j|jF0-sI(FY){NXpUSwa=BCr(CaJ*3 zYWIb7aJ~wmF4A*aC#WBpx~FvumaPYBu3K91k6-0IG{vEPHmi4*)7^$rv*0i@;|O;< zjk`5Xt8o=>Jv<}s{OBrrEUr+eppWj;S_FMoKK2N{P=KGdqFc~$tlBoZ`hQj$ySWVw zaYbVLf1_`tD^%UToo-R+12uIIohijFeO8E%4Xwv~t`^x($5Co!o&&UM%(?++d3D|g zKe7V{=yKi%57N2x2lnP5{eo6u6A#hW|C=oTJVd+EacZ^0)GyJ#%yf(vO=$ILUf!J* zS)J2wbnWs%?!aMrd6Rb!RGS>5TO|6c`V?PPFw!+@)Son0lGK~(gVQuAKb^}8U86&3 zSvK_=+Vw7bbd4U6?wnJ%U#I0L_}UHXr3SX*Z#syMV5XahJesB7q&1~Gr`h(Kv;!T* z3g*&}(a}fd(x%emzt}Ii=rBXr{ajj$PGx0pp)VX^y>DUiD5lQ3MMudrh0*)eMmw-F z_i6dKUcUdVpn9zPeOiW>{XVV72h!&IG*5bPjHvgLp3P@M!3bwwWR5@mKXiRTg%=`rn3dc${-(K7g9k1&(%sM9KHB~%5)jKLbOg$m_adiDt zz~u{&(p2s0m_k7vn-nXRjn59rOw&hT@qm2W3brv;D&I&8CFuI{RLo%A&xRd|z|JAC zi@~6li=ZyRYSB8DV3L~T7X!CIQf_nB%Op84v43llN=n5)W;;w$65YX5_G({~biK6g)(W1t9$%YP5E?z3{)*K#2!bPEK?{*b-S5N~tf>pmr_(#?6I>7yV z{?q?)Q|BY5E~v?#Xg)L!GQBkdWf_pgBQz-{JczQG8&<}GKM`tU`tqBefYbG`w{m>VN_R=Dapj+55t5ghY%$HWFl;t-h&dA&ntn+TDEOUmJ{brTA(`~F!f;5HhVG9$a zy7T}$o*)%U40Vxi7!X&-l*#mjmV$1cPAo40E`MXi3Q6569)U~lXjJgC$9XI^i;{wi zO-KCQ<2-8kq^X+6#}*aBh&{!M6qai6@tj;(8dziq5}7LI@=~PW&szMe+Mb9St- zREC>9EG)H)o;4U@|CTXJeK%2hER}VHvO)v)#@Oj`_#wJ?Rb)B9RPD-`raTxw>sd_t ziJoM!#W6Tf1?{_gt_MHOi{Q3-aj6W=Wdn*!4KSrID=xi-k3Wh_MNw0?i%X?S@UmyN zPldCMuR_Vz5{zN+a$`SMzJye=Xdo!>7VJ~eL0w#13jKsguT8`!+gU76kKLlummEMNJ%qE`p@lm+3A0xBMWHs} zMUE?g-ALS$XQ;8<(}jZ77KDpSLd|Q=C=SP&X`vL|52x=!Xrc|fe|;o0?3PaqmZ3ZR z^$4Y_V(ON$CsZ&#s2ACSPC`MMr{xCQr)RLpDAybtCZeQ%Y=cdzMpM}(n^du0$h7Aj zUUR8IM{%20AU9LRrx-ksP1W|9rsFq+2=r;8*=8T|Npr9!rKQ5WvbvU*+=-zO_|_$^ zMN%~WH<)#O6)O|!!9B6~nAe6YjMvPJIw3n$$Lk7GUmj?miU@QTn_N+9!f|IsseVEz zNv|_VzFdR`&!$S!`!OMv8IcaEB$ejNKmU-P&tn@ZORceKe^wc*aA9s{ntlv(3<_Hn z6$V!sI4caRDkT=<%@W)=cQbX}&GQgWGwl7?vZ_+?YN8h&4EDm@KV$OpF7`}Hd}ylL zA}KLcE8R0{hny}>yUXrWmC}&&@VBJT!#V%;KXQIkO-d{q>JU3a!H6I}{l7=hIO_i% zL36gRx>QG0U0na9Znv_6OA#*}i?d6!XpFklE)}6TuWYG-h4mD>SVJ03OR68#lv*n^ zKU-W+y3fx^^`)mJ%1$dpGDaoY_M>;MFyjDMI|+XVPldV1S#|@dy|i_zdcT46P@;dR zR~t*m@=?NmYAsFVo8~ssW_p3$XoFlZ#U^vzW?nm)i%&rwO>!^ zbv|lV`+Oojr2McoP^!W=-~*+ClonBE50d^c&=1sJ!=xQ%e3o=eA4xoj$xC5RtK7>&dHLB8>E+2)b$=IMWX3y$@!96kltZ`Etjg&-&Mm3X^l~O zUP#@rT6!;*ZdBiFmcHdxx^#=Qk(N^5-zqiCPiwK+d!*{rp#Hu`DkVz?pQx7)N{yt1 z>tk^k+0+fYOViW>`Or6aOl^Lb*^fwVX&rUK5y=~aIlIwcXa=0GPD@MZP4&=eDP2MV zI-QdSO46;X>W&N21p}`sztjw_&#ISiNGpxBzdHT4lpu4(eaR)!U)0wRq+JH-=0SDm z6X^m%RF^)LN*d{7b^A+cb`+{U*newK3JI6hEhh}6_X7vT87O@HuRxh^+B@XHwn%1V+TWTg%`Pt;kJSP$ewpM zG^c}D;~s_z`Tesnb8OgUn40m74ewzn9nA$9Q_~Kp3wjuq2TR= zx3A%v^yWjhrk|miwCzLnUO&T9h0jcb40X|UJF>k)4f{9`GwhIf4SZ%eZKP=|X^i2Z zw6!(6KgRF_O=Jtl8s4L4)!ea$t5NiC^|0H}kn+>pWW#xh9#gNS8NQ^nIU6?3@CU^q zZ@Qs_k$3bj4RZ?8bXIbK;WXW*{=2~NiIKKZdo3~4GthG?%QpONq?Oc3-y0-_+SSQx z4L$?yt-im((6Bg9e%LV7NY|>b{xDpj^rU*}xZw|3dVW*gaN2MwIFQa7F6JxJ5SQ6F z(LTl7DBF*SyY) zd_CK^gZ5M3qsC7u&ZeqltfA1E>aA#Fk^*_G$+#q+^zwUkeG#MAfF>GN!kA~^S23lH z=djIfQ^q(?I=Gl!E@Qj|{JpGkHFc<;BpDS->#M`c87ZZ8SxR~1F*-zTTESQ?nv1I& zmqhcyUC;QfEWMnpu5S!IkFu$8hs^u#yT-gIeq++!c$-dCE4*j?htgSUA*XRM1#j$V zY%9?p)Hfd(Uz_>WQGerrBE61d*Rdk$H%#y!_Uir7?$Ay)bK?+o!pFumBi+UF1{xO@ zi0y188N7$4CCz3l1{upnU&fQI%*i!pvp)tIt8uS`jMWw1ML#n>pmSB*2xDe&dK_u| znL1gYQO5Ep{>)Lv)-=G5k202|$JM|nV|9tnP;Fz4(-8ce;;qO^UuI|#@REGk?Vvd?(ZOAQnJRJ^p941E%SJ;f6BP_ypC9Z4KXm znA4KkFB^{^SU~D3xfeQa@{FUavyBV`7)~C$0b?SwU#_uU@txnlw>?9ZF+m9_I zbPAX;HR!2(TBCmIyHdN9z5<#*IcSk;{F?u12~~eR;~bAck7lyi3OJ(pJBE|B`WKL3F73ca6qqx`8cv zY@CBdp~@3uMG1ERot_#ypf9g@YP>_~6_)kfm_|L!`ocI0^L+XX;}p7x6?kd9&j;X3 zV}F^pRQpi*4TfQ&z`Jka}#N~+E&mn&*N#`f3N8gdN@^M9bd5$b? z9irZUUp^qwyXuzCa`Px2P*3@aBpvLnUhXZUuEwhNe)1BdbhfMd$0zbS1HY^pEW2V> z+(5gjQzzg$cCcKIu2b_5k*^x0tsT_+!{tYm9%I)&li$K^V%!M%F~*QG5^*hN_eaW? zA^c;M{5dX3T91}X(^hQIXxUE(uy$i)8^0MDBb$PQb*x;SN-tZo^`Fa4izQzVHhNMG z@3e!X&A3JzDIyrTm_?04PV3aS$H|+iw5|0>P2Pf5Q+H*^DHOL_wKC z8(aF2q~e&-l1wuK7*QEhH{MnEtd&O@=rC4)1M-3O2Dz#9#-y&T-Ul+i4!}=%P z&6t>Eo0d1KQ$|#{phweQ=4G@phw=9yTEn=3UHw^JOe-??M%03fE!!v;$GZ3XM!7v7 zF2BfK%a)k(GA~_8-@o6O#Q)EPatm^9X->y5P9io4UQK4xf036Zxbxv%ynjcTv3<=Q zh_fC4?93W%l1pLm_uM4Aa5K1llUxrU|8A1I)2^y>Gb))jU^7(IM=^D!Dt~XFAFfK? zhCcKQYyX=(pB`n`e?v$4fkkgeN1e$k@sCefTmI3K4dx%^*ew2GWb66IHFj*f+?sx) z7XDpsLs6tYJJ4pBMRv#=Xg}7%D}O8Pe#35fdt zEnZ^`m#jX&u0+X3v*Nqux_mRd8$GZp`+B!rh4+cwaxHYdC%ffpeAlrD?OltF+9MB7 zI6nJT9^c{feLdetr8i2-EyAAdk>}DG?908V2^ZVBSN@8-+$YbF4nJcT_sNgT-XDer zOir?8bhKtPD_$vpCkH$IhTvRmd>Gu29aSIimuDKV&;R1E+!cp`KM%{NaRI*mh&+Y| zaa8V1-(usB%3JA3R{I!2!hQ5HdAPJOz@8kFhnbq=g?8R^GNSmAQWir!l{%?%lW*2;NqYAVC!Rvs#(kCV*rk@^L zg9qH@*`y7%6Swu{?=)E7(dRP zmaA4c(CcMh+MB%5H#6Q1K7`u>&UiN%&ide=1$boNvHLLQ&v?$DE8h8=Z9jvVrwcoO zMm{4wy1_P`m21Sc{Rl}rCACKTCZfS}8?dJk({8NNIoVFTvL5H;3Wn-EUj{egY%xf> zcAf1#hh?fRdvQ)4h(X-{yxhCsHM}N{O{9%?**?s7UT&DM2qF~!6vU2<7D+95P;tz5 zLC#EgjBa}ld$`IG*TW6Y`C!H-=LaLZs>mk0k0KE7MP zo?ntHn5M%P+c^H%Co|1FhgH8USE6TF_sjAJ^pv{(vW)S5jBWJG73rVsf?sY$KVnH& z_ix!H zRhgrCejm?$6z=`omuDlsX=#y;y9n{rbHR>)_LtC*nFY|64!q#X&7Hai+ zde0;?A56KA-g}9MM~{xPP50zUd`$i$ZM@_iJ&-R*TaT*u zAIL5P{fRlB$nAJ%dm=9_$*)anc=>LwHNSqT_ym7uIPoVw7bUZ9|H_*%-Nimdk8rZ) zPv!D4-9ncr%X_jBPvutmj@%B~&Pu$%c0ZL*6?6sF-A>~M%Hv`yo?$&mX8WGWb>lmQ zw~I?rx4~?f>A5_mYUt*sst;9fP50eu$eR~WrD2iAlicdh1!KTHaRs*hxjdDA%-(q+ zPq5s=E5gBUmU_1|CINJxoy_+_b`(f$$a_&mE*Y&Be<{zwUSyZL{*`RU>3h3+nJVw$ zps7|K3gW!m+4qjIseMbM|xmQ{Bno4upL>*aE znMsSR#m`Hi?7w6TN$QU|cL-Kdds(caLz%TUoHk^2YAc)Q*X(X>~>vcA)oH+ zDc?q=;Vbf7R=K{iP`Wma?X9n@11r#C9lSN|ajB2lGI3k`=Q_B1TgI%v!-to}QdkAamngR=Stc z$CLykKFqj5=EfszZZD--iBqmn%Af+N_NP`wMeu)_8(*pSdnxs4+@#*Y+R~oxc4PHj zik&uQgIr2y`ha;|N@CoxUjJ=$%cYd!8>>F}sK_eyQL568tVUapVr9I8~o?*86TrBeR!nmmP-9;R6G_tXUMv!=r^X3BO% zHpqf!g>0PRY;Lf{!<3}b-u=A9>3dC6`HRKqx_qv$ox~e1b7E4Z+-!Dbn9`osWYvc& ziHN54aHVg;zet2=axd+B!KZiLw7DnPj^RpE`ZLQLu9PbH6)eJ<0jx@jQnAPf9fBP+ zF?{ceV3K&k&TL2uW{>mlv7;&I{9D=T&y>2-{`Tz3XUZ#DR=qSrp%R_U{G*gY^h@@1 zlyV6xZKASGI{Xg1I8oWhpW=U^+~@n;NlMLPzpBCN+%>8TFD8F6DO8!oa|7(k zB&9L^ij{IJsHDnHgyE&0!v2A;J&3OQu8q4ncJ-t=XalO6o}SVFQ#Hn#3}gl zWaSs0)fA-+-*8PqM_9_PO+i&GXR&GcXwB-UL5IUYno3Hx)^7Z8R07oyUewRZe1?-E5kYRHWTc@bCpc@6^j^ zSsZS5`Xydr1~zG$Ql1uI-%nE-V%EGeO=&|XvMSTjR}$H{>6i`fu$9x5a?<&F>e1=S zu;BI7EG54&s&{ovC6kA-_p+3t{E(HU;E+{~t;tew+gMG#m!(vbn$LQLOUiX?XFYzE zH~9wtf3T_XPx_xb?~Izo8lFLZ$dep~AnaaVulpHr@>Br)%6YZLXTM^L`>$!RU-x+rsu} zlp4>|_haoh?!0fFd^6anLye)7ytQxfWi$POY4dBWsYdRPjbEq~4Q5!2XSf(tHY?_17q#Rd zcD2V&OHpl=CSu?Be7`dn^}g@-{qg;C=gyfq`?H;Ao5JJWtsSo96XfpGY1RgXFnk-f z0i9G2WcyYM2{JMUVlK0tyuaj^2eKX5O5RpUK8Y$VefV>=3Z7#g$q$W;EdG+OdyZ9R zn}BP!kABfYl}TphyK7%_XIhdp8nD5TZ*^gu4!c4LoLiA(>=_0ydq}D3rL-B z4f_E291j}J2h}oHpj{xx5y1Y5`|RYrAV18Q9p5BjkNYEU*?T$ou|Sk+={R{ERQ`_3nS4rOQ z)TT=EIU{2>rm=K^wYaxg7bC);&l(w*fC{Pf%K}h9fZRgsB{_=|o!vmGR|~EFWjGEQ z8E%lvvb_5Ma@qev+^5&;EV33U$Y1|o*vg`B7Fmm%Edyqm14V)C}MEV{GET2$ucfT}EVEVlaRb2soARAo_}#n!+c=D?r^0RXun z2LypriZd3`=!y#esVqA+qSeVr#*$ z4>RB|VeCdmjvJ0XRsnAK1Bl#jy>lK8!^( zv88xaE{hVESZjXv=DsD?f?l8A1k|`2_-Bc=QW>-OFOc+OKnSxOEt<_)01fUXcE4V4 zskI=~V;z_BJ;O_Gcriicz#phOyH*ytmRbYdJ^ke{K?TL$S+sX41RVG^E`^BDj5;oZ zWCw|TnYD)aw?F;7%o-%_^`|?_td)iDS&`-7%|d5tw8C1G%M&ZCXSkfQ(z-%`eQqVH zLRGm6CyvI{X%z&54a~X9x=09^jG%QRLx3MwXCtG4k+I*%nB<|Bu@ZK zr{(Ld8`YjL!o*i{JJe9z25T&&i?ti9wfTG58z9i(+IyolhF{Y+T9@!^%T3m%{JLb5 zbvnORO1FN`uY1z1&G=Q@Y(2rRS2kONab4~46Qrs{vTU(NyZbBup})3Uus@S%@)m0s zJioQYI)Y17TdhuB`_HY`;{58l&AJ=r;Dg(&g<)5a*^LbAj~-kJxC@8f*|cYubt2^D z$V_V;5i6OLY2Cp!%ew(W&`$5RwibUA>GW=#s&$&T$GS=ALJjxgELE5K@=E|s-D?dj z^!|%a=dR#ShbhQkfplQ6^@Yd%JTJ=JXPwJIYri!?y#Ah@+;4?N5(jQ z?y_|kKgV8y+JH-#SFQ2l^P9BgDkOBQ%I&Mx1irM_tk*vPVJ)>J`|>(w1b?Y_dCq?V zU;J9^1%xi(0L%T|T3)bELvj=D7L{Y-ieYgoVOap7j!iejEo4~$k<&AaCz$v zsLBQ^lxr;lC!XrLR!I;;42rx9;rtKHSz?v>zI762n;1;0r&^knXa+LKaz-PR3OCvDr#R+uHvQbXKzv!3c0I=t1=ju-e51YCl9zmvd53B3 zD{DW1s`qPaW2hiIzXmMcr$eu;Yq$>PjrDtB7rl66O%wbn<*l_P^!L}_0z?3S@1P0! zn&!N-61QN#2Z*Op=l8%>c*4B5M)~u7u*CPRbUwEL)NLTp&ih#Nm(M5h6@UL8Pz)19 zp7lr}{-S^_*;b0vT-SKKB|QfP5Bj0CR1aih`y5H(e$Yz<$-jiV)$^`#3MV|AKl%%KNDQU9Q zM<_sVWNEJ8&1NeS)T&{n-Rrs&ssg%r%-*5T19sYJ-+NnyV#G_m2PgQCxcv6Ta zC3?L_W-5-z&`59wl|7YqYEppr=?}%(L(0AeYT%S!ltR})J=}>bx>S+FiY{$LjK*KO zRLWz~W-ltY2HO3(RK}2kgpSnAkZOuAgXw!i3WWkO(~yb+pnfx?`k<0U9a0fahaA!n z3}b^sI?SDNyrf2A?nc_3VTL`IiH)0uH>-SLQT7_OGE=K3KhJc*NHQyI?9vV3Er&1r+N1Sut-Ou8*eX6y~@5 zQV6sk)ACDOlm#Z>bac+9Mg>s1f{iF3#T+-DF24u>LjJs1g#yBIrzlq#%zqUax7$S!;g!BS@;k z&CeyJbn)gqI$ToP3OmfVrKI9q2U1FsP=&21jqMeGpF<~tB^TF7m%--2PoOM%g~qh3 zR9J*+Eh$9m1wwH4~^IneJAVZi>H7W#_6%`2_9I6!4P|W}ip& zu(}k?-G;)Y(VX&yOYOzX@918*6ebP)`Ei~Lr=#E+fW)U1Q$q@bxYxIaR8Zgpt|^@m zO0g!j0NO$|8WVv@Uto(Oq^frD!bo;029?CEBj{N}X)s6EMpAR}Ndnv6NCKP3%$o4^ zg)dL6bV|HFj7~O{W`nb`Zq4|rHDvvoOOpg~=U{r!LONRH_1~}ZJO&0uK+HDJ&7Z&& z%DhGFLQ4r;x&k>{OT`40t!ym?SjE43(UFc)E0C;0U!iy))%r@BD_-cyE`24<5r9Mk zfBpQkrR9r2^Ox3hE}M zh%Y+PPu-*rkd|!SrH*_vyGv~a@!r=gvxl?a<7PeJj}fb}fsJ>9v}-+TViZR(4wU^(EhbBq3*P-#OPf8ecplfM zpLaPQvw4%H+a?xFl`3&4*g6#m%Iz}WOU+?vSHTdI z-dr>?z}QkDXwi~1DL>yzmL`>{kp=GIyeBvz0<~~Cv&!Ju7!~B7>wp|mE;Z!Svq;EP z1<<&Tn@Hga~0a;XNHn2?%p_;RS-f(@JEtTPd^Ss$oF@D`WTlzb{wJbVs`6B6c z!iWeX<2Xbs2sgC-2dRb_=Aef^NX3h|xn$vwEOi7}s!ynqapL(T{%XZJQkfX@m4re` zugb@JCcP?`5C!EysA#^x`F2(35z(chj@R=^-tOiKxve_x#_-I109_iNco1dGkxKCE z)j5)1Ag{2C2c0|rY!F}k^Lpl)EQs=xG>E@Fi2w??t|93!KeHQS5@bPcpmVu9a`&=g zt`zRep9}E?K5x$b^yyqFi??!co-~$U>-{Lrt-{}yjY*{tG-715@Yu^W%OB=~Vwgqp z{Ab+)YTe5t*_yO_H`8YV1cwuRDhLA(%1mli>`u(YJ6i>0#s`t4%L zpI>RQ)HNhM!0U_Jocp+DJ_i`a7dLebu9-nF;yYjZjm(!adqP$YW<4PY_QEC7D8r5# zZcEF!N(e!sbxS~$aiCZ#`Qs#BYAFaf#IvQ+5I&acOQlZy8nI03%de}Jf!YJFmP`G( z&+l?6%pCH?6;cR)EUpB%$FWXzl~{8?Wp=_nFjQZd zL1e%$^hT2c_M+S)3WilM=}scYq67foq*}kh(MXEr=dx8&2XVVEJy|7H;P_BtwKNBf zv&_}fGN2RdyiRH;2sXBQJtu_-7u_h~;5mcNY?OM41!qv$CM+;cKbxfLf_T%Q!|9-M zpxK+HHlh$l!?%EEG^7Pvq|&0Aj~(73jWe0kcGSvG3${aGJg%@C+c{@gMg~K1W9q}C zBiuf_L%Jn!lDJFCh9}{>UD9nqJS5Vs-BJd(U+fC&GxM_SIq0ryG;M4kR)RQlBF1SKOY4%61G}ePtwFlC7a0t5f00O}gwjN(*6~rf}X!|2DlQ=RSO9l0T z9#8X0aOs>`Uo!lMwDYTR`r!B&HBU#X0N9s zqTG~ktcN^Ect8_9=xFa72H zg3NXnks*Tp!Oj(xB|$yC*x}YIq!pV%e+S6Td1HYxPNj=zd!Rgx19>qSo^1=+tzz<4 zfzyW)a&vL-e7aLYuEX_tL2})&I`iGlfY=15m;(CaHSa+fMORw%43Nu!ana6~9y}RbB(~)u5YP3NDp{y2*1m#CMnPi`(MpX?Fk~#?%7~W=2oQow!eBPq_&%?TOXR z{EF`NlqU;oXm~HVgs_rPFMzoCz5}i64Gi1bfu8l29G(z3(Zu^IPDO@HdSfBiHo0YYNE0*WfgN9ZhcSNr%UP zRy-xoM7fC=){9ytf*QT0If-%|{|t11wnxPmbvZNLo%Jrq3tZ0q^e|Cwt#U2MH+D4U z#MqjTl{fGv-i?)$aAo7i$)g3~7kWKj?gO8b?n&}+;TQHx5;_39`Aw7?3pyWuPu8UCljJPn9<7^$PnK6<6-&~vDRQJ}$xmCS$Q`*v zp-+{Qgf}#Os+=IIy~&!4Ewjv|mdSF<{Q68ddaW`hod$;OV zy$gMMauMNl{K;(gcA6{-m5O|LlF*Eo`k?EaY4EGtDVftL^Qqoa$e{d<6;yGCTtUP< zyUdU~C?V!pJEqL0{WIhm;1aKA$ejxEk#ZL-RG1XB1}%LU_TZWFDkbRiD!~*zOWq`I z4WVbV*5ZwFbUaON2_|27wtP%HRF-bdmKSjn`GdTevz0mWCVaxXD-CY>aC33tGs3$*2`u6govFx2mV1cbnm_ec3Ve!`qDw}ET< zPxAp(2v%Dl$8i|=et}%i?I>~)#G~*|EHLqV|i`-i9Bi9zN)V5S)tDG+WW~b9z~)~=(_&(+q^mPB@9zHJ;7ga;DvrA2;dW(-9dbxmpx_tOMcSz1C3C*oaAzzrn@`k zNF=%`zf0aN?y*qrF0egt_~1<0DZcTbjhS)>_`O< zWmV|x{nq%x`8olk0yj(&oUcc?oId<-KIiLrm$M}Py3%a;HKGn;3&SxN zpUKCup<#Shd}CcHH~HzF>k87!@z+i3pA;A{1V*?gT@)ca?-k9g%Zo%vZF zjXAR>hh>C$wWaJM@+_}&Sl*myaAo(o(D^l`9F;4JIWK76QMnA>$~lTT_9WXe(2Hp5 zehe%mfmR%ozrj8gJPx5?5Vbolm*miX9GC~u@bn45GjyjX!Ch|B`jbGpE%a3u7%mq4 z+bnR7)pRyXu2-0kztZ#M*r1S{au@+OJZ6s>!uJ($a!NicFnV`NF2<_`o`#SL%sDMD zL+OLl;QlBra0W}jsJf?yz9S$( z&ka%LdL#1_$`K&2zheocxgkzA`+Oj#xdwWiSGN(BV%bSbVx zaD`lPWw(IajzP*q@#K$mJxCb{THUy$@=grt#Tu1TE(yYS6cDU@3u-wpSSbTZgW)#io^2KsMwy>|i-1P$-b(9xTU-aOZx(LrN>pVJvjWeudeKYB$Gc}SqfIb!j)#Q9$9NB9iT_;QbTDZ=*4DZ`6A5aLLxAh zQBxVjQw#+~C>i+*@MrMS<-^1~cusdCl%oGzo=E<+l?MOWRw50pt@!18#%KJWZ7is* z)DnZ+(v{jubupqh<*Ngr+D+B!D50XIE%mLV#KD{Ja2=(y!3{{plsqgZ*sXH~Rjv!* z&7*JXDpg?5SXEb92~WM)NF{(X!$_sEAijRecGTnW0-ITVEQX^Uc}6K=(COEV!g`*i zQBg`C@#tv!GYTuXgw{kWx8dJ6y@4`a44F-VG0JH80M3t5V({+G7-bFDb~IF0d%%4- zELK?~TH3SUV^I~9W@R&_7$WwLHpBP#@b5B5`-P>RcqxpLAcH?wpAbxBebub^2&n;3xB2jA^_P>#VO52 zVK6JwMQJB+5u&S-ZY1&TK>%yACCHT))}AVN1Kc>-kZ!z9P_-UP$s$?JOb?t;9Lggg zt9${&EC}=Dd+{Y*TNlFLSE*I%do(i{z?zIJC*f^^;<;}=u0!#z1OHW*vjg4eq4dR~ zHteZXf+NA`o=Ro$^;fj1r_vdFr}a|mfVs!^QYvyp?WK$YMS9jtL0s|QY)fCoE{Hj8 zXotJ8d}rg0hsL(x;H=>$4~wPm5G4W2Ln;LC-of!!ZC(igOtXF>;CXI zFCm}vcBCt%JpLkJ7r#c-F&CVO9uGoe6RF!^B?N44+F*dfblNmnDTlk?1}lXN&BVJ{ zAxy&pGge&kFO0iVvTLzK3`4>9?K0B2%QWT-3iHEzJ&ZU?$D9cF)i zW`8eTX+KctP$ddM6$wMJ*TZPlQ1myEjtm9%O`&H)0X5*Y!<52>C-ZL2NGr2f=so_r z`#vvsH$RyTABN#|pvA+KrsA%qbbpv~EAT?B0hM_6U!$RZ-tU8RDA(z!FeK*Z!m9Hk zJ^2PC6kK4qavc=718E7$9IhisP}2EnY=kmiywH#?jZjFa$p(#74vXlb%4k%Ao_e&B zD#nJ=+tEsU{_+^msWj%3sI(Ed5pS$AT0B&bZjDtIATDm=IORB8Sz^Zn$Pvq!q)g^| zfg}Ln-a2$AN$D8aqmDV&ZwCJNSaox(bE(G!kXDRsg3<@(Gj*cUC$LIwv(A?T{=1Id zth1leCMtEsixKSNL=bC)*S>Kott>)E)@&*kRk%uXl9je%W>t1CS?R*jt7!@-v_!U4 zWjd(EkEzNxLM+o<%6$)xKQpkkf|V_ur4&Vmg)(&D2jy?Xov)gsd?gC2m@rT2D+;w) z|M|*tL5#gY#zN3{E(R+dJjL_=^vg03$F3}Jx#BHyt;tHIlQ5oUtyDI0513Voug*`_ zTx2t%&bpj;srM=%gnbVExC#VxF_Tv-(*&U`(Hdp7P?^#EXov$MLJl%Rn6Uf2)_cMwR!AdrT-+Q}x4#JmKy zz$!d(lTt&B=tz4uDb)&Wb(kXybsmwNw_m#4(OaWPNmt6lWxaYj2oH!-Iw-^+bUhs_ zFqN8Y25M}k0h^Vn;#QrWZB`a>^Zids0GxMhw0#?R5jg&KWfDKQZdV$M7Zkd*9b68E z(G1WL@q$E`m{L!azarlq3R0EKp&mQ%;CD*fq0ESMS}`UdEN~?h`j2oJlrCk5kADGT zmf~Gwdtsu~X?T{^`k%?o`SOVud;MWS85sN~A9!4aYf1Mh~&`Ai)onUg8%-mmVq;9M>S$!0LK-M8glt zgWivn77lKUHNHbCBM3XlodqlPBaqPzBt2GUa|6g@9`N zc=i;W^)^+01~l>{8uv^oX802b6#QP@G^QiFXsZG+E9PNq#p#QOEt@-+T5K)ESGy?PVrwQmq4ySB zP42|!X=}%k)6*7*ckX%G3c}v+X|*9yP70NhY^LRHhGgT$P_|mK%@nlJSRhwsZT`D{ z1Vt;h?+Qkj2l?2~{Yj0_L7^$4=sjh0v6uzQ2 zsx6cYgqp2_2!8gpf!nDp)vz4^6QpK7wx=?8dP+$PFHMc}+YWP@Qowdlytsy4EMRM7 z;YPT^wz{SbuZYb{6zb8?0GkW?+V=srh5SSlXuEFXma}rUI|5i`uktpW_StlLRMFNA zqGsz*TdahDw++q0Ai8%GMF`-0@bnC}AGyt!;IM%dA;z+adv& zd#{bnA@EIXYir3v``g(DK~n5P``X)nLc*nC9c&Sz_^KyM|H_tSCWq=|L*x_=rd@0k zL}e}sU2R<@@448)tu0vJt~MAY%g<#?yV=qN1o~I)VOs^^^jZ&FeWbz*>}gw&f7`j| zJn&ckWTb-OU3Kf7^3GSV%qtZ6!;NJn@{z;feG#9W>YvkeetK<8~cVS$VvGSW7TTOmiW zaiC-K$6$F9>B1OW2ORK15^Z77p?6EP-R1B#*7gU?mlem^-h1FgQ(>a5nrA-lw*dy* zA$gLSONYB}jF@5@Di)lK1&=QXwi_oP4??z+pnI`XQi(MYF(uQt86>PUwzrR zRknv7RsKdzSIQ0i8qvolgHLka?n=w$1q~0T%;71t(XyMlBksfHe8HZsvuRcsB*dR= z2-y9bv8}c^T`W6~@*lMQB0A>Ly@LSURAxV9b4Wb!_k=CbBJ^jqPunt)aEiS;XPf7N zOmuAaC0kBmp6cU~ZLE1Tdu*%c0oqjOx$Ugbm>Dl@aheZzH^+H?stB>o`Ln4JtIx(; z?6EL*Fm_6^r%S?jY^-75CPOz_+1K990%>%%zkR0%4ob}e?L{SwWl(85e7a_{;lXyV zeBN_$bW0u=JheedtTf2;Z2ONyHSK|@u%o8^giD-IIpAJRYN0b{Rn$B_a7W-A1R8t(X{7V`+f0E6m1-BZzIN@C66)o8eVVzf>|D# z(F8x|Uxi#Lv1eJ+G4@CgK)|$dc83VN?cyYRJbWLR&qRB=UA$R|4!i7YarhZB&3;OR z#jEyAEX_O`HPc>6xI^n^+WkPm56`q06+qGdo@FoX!EO6=cYE@LbW7}O zJvakcZjVE%h_6@JgYovH74|otNUxr>&RzwQxEF2TXg?^vn!>)_WZ&Y+Wuk5NDCB<{ zw#{Bo6yJ}hZ5j400Q5f04vQg-3_I+dLBVr&*pCUqKH9R&zL!(#OgsDvGU@qldl><# zvi8{Lh~n!JY{x!(4M7;s9`Cn*D+D*0w>wg(w$lvyt|LdfH1jUzGjazp3mULkKZe!FO zue0qo4>7DX3(mFQ6!|LMw^#JwnZ+L23(EX3{K~#q+4o{@M=m zadZ0~72cIM>AHvv`1h%>hw7iN@Q(0KlK9V z@qZUqD|(29TCn^9>SKTclS`;SilR23tthE3^g!tDmu1wE*z8?pRQObe{Ya7J)H0%_ z8yiqg?cpiF-z8KXXTbtAtE#psP#!aPr3K>`hh9#~UC!Cv-_g)XYC(3Us_NkhP1c2) zYC{iXBJi)H1_%i(q7GI7!2C? zm+_B_+_$=_$Hbs+EWMjLMHC*g>OIvs&P!+aQfp!^XL_j*k%)4CZxyM*W7&efSU>LUnl#Yd{CNS2sBQaxl9Yp1dJacY(j;NJtZ{4u0Kkn*_fI!xe%`>-)Nc0E@U z=TMg<^~l$e|M60dPcQXZ$6vbmA5RN^dfLc*8qxFf4&G&a?4X?abQ>j2P>TqoXc52M zrQQ58m42I`hWHn60jUycP?8bJ39~r#V{IP2hD+Y0fD$cO@rmjQzH;}RYLXks&SQz{ zO;&Zjt}UjhH!Xzfo`D~X<9UzEa^QrW7pv_6@HC>H{DR2FBHC*(a zPq(J4fu+)+nJ`o9s<{i{24e~ZIM_nx<#Kw>haqi>E3M>wDmO!IBbJ}fCd^PzS+Ts$ z2~CY=Kaje{10$(3Uro0Nz1aQ5YHjnA2g}gmWY&L~x>3So-*qZz)>NvsUJU|XbzQF( z2GvhouQq`#=Gc0?+l8zf)cWv3YP>=1h~(2NHmD4yq_~ZkZxgz{Q7!7-52MNPUM~k1NNx9A!Y{eReK1>S?XRDN%!Txw0gff5PDOe1FBOD z>r3+vsAa{Q@96LWwRzxeESoFs3Vw~KbCY@KZj1Pe7!+55hPcxHM&y@T0pz#GL3IZ= zAs++v!2CrG z;>#Hd@z4-m$>Kb;RUYsM^pLb`R`KXh>`zTQZ51Z6%|2RpQRvLP3u^uFZ5TGzPiqdl zDLYkI>ueXt%q8OrxI;{7?UZ0$w}6LdQN0+g01GXn`3pi2Yg$(O-4on7BvhM;41=_{ zvbG6ZIjD*@Nm#}nSJCR}-2CySmLmR>$PRp|l@Ww@lv`hWVHFmBYL4DVq1)4|n?-Bf zxZJ#fhM2^n^lbyJJXA`n8)!wufW>sAfmY61dhw@Pa^1_X0hS?)smlPZi0o(Hg)XKu zv04#oAEON_l2z_eUX5vIxr{q0v<5_dw>CdH+m%*(G5r~%O%VE0kA_+oi|-=`umU&YSHFsHP!q@1& zfLT&u5qZUFMbt;+e1__|hv)s@2EjmPyq)0%0Axa#FxbFHBFxsTN*JqLk` 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 SyU01&_h=%!_tH`Aoa0}T^gGD_ diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index a5fb34f8..a85bdd03 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -4,10 +4,10 @@ android:installLocation="auto"> @@ -41,20 +41,20 @@ + android:largeHeap="true" + android:theme="@style/Theme.TMessages.Start"> + android:windowSoftInputMode="adjustPan"> @@ -95,6 +95,19 @@ + + + + + + + + + + + + + + android:theme="@style/Theme.TMessages.PopupNotification" + android:windowSoftInputMode="adjustResize|stateHidden"> @@ -116,8 +129,7 @@ - + @@ -125,8 +137,7 @@ android:resource="@xml/auth"/> - + diff --git a/TMessagesProj/src/main/java/org/telegram/PhoneFormat/PhoneFormat.java b/TMessagesProj/src/main/java/org/telegram/PhoneFormat/PhoneFormat.java index 512b962a..a6dbff0a 100644 --- a/TMessagesProj/src/main/java/org/telegram/PhoneFormat/PhoneFormat.java +++ b/TMessagesProj/src/main/java/org/telegram/PhoneFormat/PhoneFormat.java @@ -24,7 +24,7 @@ package org.telegram.PhoneFormat; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import java.io.ByteArrayOutputStream; import java.io.InputStream; diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java index 45167315..0aecf4b2 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLiteDatabase.java @@ -9,7 +9,7 @@ package org.telegram.SQLite; import org.telegram.messenger.FileLog; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; public class SQLiteDatabase { private final int sqliteHandle; diff --git a/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java index 9e8afe33..944f1d7a 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java @@ -20,6 +20,9 @@ import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Environment; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.util.StateSet; import android.view.Display; import android.view.Surface; @@ -35,12 +38,14 @@ import android.widget.TextView; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; -import org.telegram.ui.ApplicationLoader; -import org.telegram.ui.Views.NumberPicker; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.ui.Components.NumberPicker; +import org.telegram.ui.Components.TypefaceSpan; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Hashtable; public class AndroidUtilities { @@ -389,7 +394,7 @@ public class AndroidUtilities { encryptedChat.ttl = 60 * 60 * 24 * 7; } if (oldValue != encryptedChat.ttl) { - SendMessagesHelper.getInstance().sendTTLMessage(encryptedChat, null); + SecretChatHelper.getInstance().sendTTLMessage(encryptedChat, null); MessagesStorage.getInstance().updateEncryptedChatTTL(encryptedChat); } } @@ -502,4 +507,21 @@ public class AndroidUtilities { } } } + + public static Spannable replaceBold(String str) { + int start; + ArrayList bolds = new ArrayList(); + while ((start = str.indexOf("")) != -1) { + int end = str.indexOf("") - 3; + str = str.replaceFirst("", "").replaceFirst("", ""); + bolds.add(start); + bolds.add(end); + } + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(str); + for (int a = 0; a < bolds.size() / 2; a++) { + TypefaceSpan span = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + stringBuilder.setSpan(span, bolds.get(a * 2), bolds.get(a * 2 + 1), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + } + return stringBuilder; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/AppStartReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/AppStartReceiver.java index 5368465c..49bfe9f0 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/AppStartReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/AppStartReceiver.java @@ -12,7 +12,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; public class AppStartReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/ContactsController.java b/TMessagesProj/src/main/java/org/telegram/android/ContactsController.java index 8fe61f98..5135657e 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ContactsController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ContactsController.java @@ -31,7 +31,7 @@ import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import java.util.ArrayList; import java.util.Collections; diff --git a/TMessagesProj/src/main/java/org/telegram/android/Emoji.java b/TMessagesProj/src/main/java/org/telegram/android/Emoji.java index 4287ae6e..49745d6c 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/android/Emoji.java @@ -29,7 +29,7 @@ import android.widget.TextView; import org.telegram.messenger.FileLog; import org.telegram.messenger.Utilities; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; public class Emoji { private static HashMap rects = new HashMap(); diff --git a/TMessagesProj/src/main/java/org/telegram/android/GcmBroadcastReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/GcmBroadcastReceiver.java index 7b33e2c6..f0a133be 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/GcmBroadcastReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/GcmBroadcastReceiver.java @@ -16,7 +16,7 @@ import android.content.Intent; import org.json.JSONObject; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; public class GcmBroadcastReceiver extends BroadcastReceiver { diff --git a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java index b2030a68..f3d7be2d 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java @@ -31,7 +31,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import java.io.ByteArrayOutputStream; import java.io.File; diff --git a/TMessagesProj/src/main/java/org/telegram/android/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/android/LocaleController.java index ce0f2472..0aae84ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/LocaleController.java @@ -24,7 +24,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.Utilities; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import org.xmlpull.v1.XmlPullParser; import java.io.File; diff --git a/TMessagesProj/src/main/java/org/telegram/android/MediaController.java b/TMessagesProj/src/main/java/org/telegram/android/MediaController.java index b87fa176..b7b25b8c 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MediaController.java @@ -52,9 +52,9 @@ import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import org.telegram.ui.Cells.ChatMediaCell; -import org.telegram.ui.Views.GifDrawable; +import org.telegram.ui.Components.GifDrawable; import java.io.File; import java.io.FileInputStream; @@ -809,7 +809,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } if (send) { - SendMessagesHelper.getInstance().sendScreenshotMessage(lastSecretChat, lastSecretChatVisibleMessages, null); + SecretChatHelper.getInstance().sendScreenshotMessage(lastSecretChat, lastSecretChatVisibleMessages, null); } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java index d3cc3787..f3b155fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java @@ -25,7 +25,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.TLRPC; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; -import org.telegram.ui.Views.URLSpanNoUnderline; +import org.telegram.ui.Components.URLSpanNoUnderline; import java.util.AbstractMap; import java.util.ArrayList; @@ -452,6 +452,60 @@ public class MessageObject { return ""; } + private boolean containsUrls(String message) { + if (message == null || message.length() < 3 || message.length() > 1024 * 20) { + return false; + } + + boolean containsSomething = false; + + int length = message.length(); + + int digitsInRow = 0; + int schemeSequence = 0; + int dotSequence = 0; + + char lastChar = 0; + + for (int i = 0; i < length; i++) { + char c = message.charAt(i); + + if (c >= '0' && c <= '9') { + digitsInRow++; + if (digitsInRow >= 6) { + return true; + } + schemeSequence = 0; + dotSequence = 0; + } else if (c == ':') { + if (schemeSequence == 0) { + schemeSequence = 1; + } else { + schemeSequence = 0; + } + } else if (c == '/') { + if (schemeSequence == 2) { + return true; + } + if (schemeSequence == 1) { + schemeSequence++; + } else { + schemeSequence = 0; + } + } else if (c == '.') { + if (dotSequence == 0 && lastChar != ' ') { + dotSequence++; + } else { + dotSequence = 0; + } + } else if (c != ' ' && lastChar == '.' && dotSequence == 1) { + return true; + } + lastChar = c; + } + return false; + } + private void generateLayout() { if (type != 0 || messageOwner.to_id == null || messageText == null || messageText.length() == 0) { return; @@ -459,11 +513,11 @@ public class MessageObject { textLayoutBlocks = new ArrayList(); - if (messageText instanceof Spannable) { - if (messageOwner.message != null && messageOwner.message.contains(".") && (messageOwner.message.contains(".com") || messageOwner.message.contains("http") || messageOwner.message.contains(".ru") || messageOwner.message.contains(".org") || messageOwner.message.contains(".net"))) { - Linkify.addLinks((Spannable)messageText, Linkify.WEB_URLS); - } else if (messageText.length() < 100) { - Linkify.addLinks((Spannable)messageText, Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS); + if (messageText instanceof Spannable && containsUrls(messageOwner.message)) { + if (messageOwner.message.length() < 100) { + Linkify.addLinks((Spannable) messageText, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS); + } else { + Linkify.addLinks((Spannable) messageText, Linkify.WEB_URLS); } } @@ -576,10 +630,7 @@ public class MessageObject { } if (lineWidth > maxWidth + 100) { - int start = block.textLayout.getLineStart(n); - int end = block.textLayout.getLineEnd(n); - CharSequence text = block.textLayout.getText().subSequence(start, end); - continue; + lineWidth = maxWidth; } try { diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java index 21c5c230..c47932bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java @@ -9,32 +9,23 @@ package org.telegram.android; import android.app.Activity; -import android.app.AlertDialog; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.os.Build; import android.text.Html; import android.util.SparseArray; -import org.telegram.messenger.BuffersStorage; -import org.telegram.messenger.ByteBufferDesc; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.MessageKeyData; import org.telegram.messenger.R; import org.telegram.messenger.RPCRequest; -import org.telegram.messenger.TLClassStore; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; -import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -44,6 +35,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Semaphore; public class MessagesController implements NotificationCenter.NotificationCenterDelegate { + private ConcurrentHashMap chats = new ConcurrentHashMap(100, 1.0f, 2); private ConcurrentHashMap encryptedChats = new ConcurrentHashMap(10, 1.0f, 2); private ConcurrentHashMap users = new ConcurrentHashMap(100, 1.0f, 2); @@ -61,19 +53,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter public boolean loadingBlockedUsers = false; public ArrayList blockedUsers = new ArrayList(); - private HashMap acceptingChats = new HashMap(); private ArrayList updatesQueue = new ArrayList(); - private ArrayList pendingEncMessagesToDelete = new ArrayList(); private long updatesStartWaitTime = 0; - public ArrayList delayedEncryptedChatUpdates = new ArrayList(); - private boolean startingSecretChat = false; private ArrayList loadingFullUsers = new ArrayList(); private ArrayList loadedFullUsers = new ArrayList(); private ArrayList loadingFullChats = new ArrayList(); private ArrayList loadedFullChats = new ArrayList(); - private HashMap> secretHolesQueue = new HashMap>(); - private boolean gettingNewDeleteTask = false; private int currentDeletingTaskTime = 0; private ArrayList currentDeletingTaskMids = null; @@ -113,7 +99,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter public static final int UPDATE_MASK_USER_PHONE = 128; public static final int UPDATE_MASK_READ_DIALOG_MESSAGE = 256; public static final int UPDATE_MASK_SELECT_DIALOG = 512; - public static final int UPDATE_MASK_ALL = UPDATE_MASK_AVATAR | UPDATE_MASK_STATUS | UPDATE_MASK_NAME | UPDATE_MASK_CHAT_AVATAR | UPDATE_MASK_CHAT_NAME | UPDATE_MASK_CHAT_MEMBERS | UPDATE_MASK_USER_PRINT | UPDATE_MASK_USER_PHONE | UPDATE_MASK_READ_DIALOG_MESSAGE; + public static final int UPDATE_MASK_PHONE = 1024; + public static final int UPDATE_MASK_ALL = UPDATE_MASK_AVATAR | UPDATE_MASK_STATUS | UPDATE_MASK_NAME | UPDATE_MASK_CHAT_AVATAR | UPDATE_MASK_CHAT_NAME | UPDATE_MASK_CHAT_MEMBERS | UPDATE_MASK_USER_PRINT | UPDATE_MASK_USER_PHONE | UPDATE_MASK_READ_DIALOG_MESSAGE | UPDATE_MASK_PHONE; public static class PrintingUser { public long lastTime; @@ -307,11 +294,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter MediaController.getInstance().cleanup(); NotificationsController.getInstance().cleanup(); SendMessagesHelper.getInstance().cleanUp(); + SecretChatHelper.getInstance().cleanUp(); dialogs_dict.clear(); dialogs.clear(); dialogsServerOnly.clear(); - acceptingChats.clear(); users.clear(); chats.clear(); dialogMessage.clear(); @@ -321,15 +308,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter totalDialogsCount = 0; lastPrintingStringCount = 0; updatesQueue.clear(); - pendingEncMessagesToDelete.clear(); - delayedEncryptedChatUpdates.clear(); blockedUsers.clear(); sendingTypings.clear(); loadingFullUsers.clear(); loadedFullUsers.clear(); loadingFullUsers.clear(); loadedFullUsers.clear(); - secretHolesQueue.clear(); updatesStartWaitTime = 0; currentDeletingTaskTime = 0; @@ -346,7 +330,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter offlineSent = false; registeringForPush = false; uploadingAvatar = null; - startingSecretChat = false; statusRequest = 0; statusSettingState = 0; @@ -1038,7 +1021,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDeleted, messages); if (randoms != null && encryptedChat != null && !randoms.isEmpty()) { - SendMessagesHelper.getInstance().sendMessagesDeleteMessage(encryptedChat, randoms, null); + SecretChatHelper.getInstance().sendMessagesDeleteMessage(encryptedChat, randoms, null); } ArrayList toSend = new ArrayList(); @@ -1133,9 +1116,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } else { if (onlyHistory) { - SendMessagesHelper.getInstance().sendClearHistoryMessage(getEncryptedChat(high_id), null); + SecretChatHelper.getInstance().sendClearHistoryMessage(getEncryptedChat(high_id), null); } else { - declineSecretChat(high_id); + SecretChatHelper.getInstance().declineSecretChat(high_id); } } } @@ -1707,8 +1690,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter putChats(dialogsRes.chats, isCache); if (encChats != null) { for (TLRPC.EncryptedChat encryptedChat : encChats) { - if (encryptedChat instanceof TLRPC.TL_encryptedChat && AndroidUtilities.getMyLayerVersion(encryptedChat.layer) < SendMessagesHelper.CURRENT_SECRET_CHAT_LAYER) { - SendMessagesHelper.getInstance().sendNotifyLayerMessage(encryptedChat, null); + if (encryptedChat instanceof TLRPC.TL_encryptedChat && AndroidUtilities.getMyLayerVersion(encryptedChat.layer) < SecretChatHelper.CURRENT_SECRET_CHAT_LAYER) { + SecretChatHelper.getInstance().sendNotifyLayerMessage(encryptedChat, null); } putEncryptedChat(encryptedChat, true); } @@ -1789,7 +1772,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } ArrayList random_ids = new ArrayList(); random_ids.add(random_id); - SendMessagesHelper.getInstance().sendMessagesReadMessage(chat, random_ids, null); + SecretChatHelper.getInstance().sendMessagesReadMessage(chat, random_ids, null); int time = ConnectionsManager.getInstance().getCurrentTime(); MessagesStorage.getInstance().createTaskForSecretChat(chat.id, time, time, 0, random_ids); } @@ -1912,14 +1895,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - private void processPendingEncMessages() { - if (!pendingEncMessagesToDelete.isEmpty()) { - ArrayList arr = new ArrayList(pendingEncMessagesToDelete); - MessagesStorage.getInstance().markMessagesAsDeletedByRandoms(arr); - pendingEncMessagesToDelete.clear(); - } - } - public long createChat(String title, ArrayList selectedContacts, final TLRPC.InputFile uploadedAvatar, boolean isBroadcast) { if (isBroadcast) { TLRPC.TL_chat chat = new TLRPC.TL_chat(); @@ -2577,7 +2552,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (!res.new_messages.isEmpty() || !res.new_encrypted_messages.isEmpty()) { final HashMap> messages = new HashMap>(); for (TLRPC.EncryptedMessage encryptedMessage : res.new_encrypted_messages) { - ArrayList decryptedMessages = decryptMessage(encryptedMessage); + ArrayList decryptedMessages = SecretChatHelper.getInstance().decryptMessage(encryptedMessage); if (decryptedMessages != null && !decryptedMessages.isEmpty()) { for (TLRPC.Message message : decryptedMessages) { res.new_messages.add(message); @@ -2623,7 +2598,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter arr.add(obj); } - processPendingEncMessages(); + SecretChatHelper.getInstance().processPendingEncMessages(); AndroidUtilities.runOnUIThread(new Runnable() { @Override @@ -3085,6 +3060,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter interfaceUpdateMask |= UPDATE_MASK_AVATAR; MessagesStorage.getInstance().clearUserPhotos(update.user_id); updatesOnMainThread.add(update); + } else if (update instanceof TLRPC.TL_updateUserPhone) { + interfaceUpdateMask |= UPDATE_MASK_PHONE; + updatesOnMainThread.add(update); } else if (update instanceof TLRPC.TL_updateContactRegistered) { if (enableJoined && usersDict.containsKey(update.user_id)) { TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService(); @@ -3155,7 +3133,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter //DEPRECATED } else if (update instanceof TLRPC.TL_updateNewEncryptedMessage) { MessagesStorage.lastQtsValue = update.qts; - ArrayList decryptedMessages = decryptMessage(((TLRPC.TL_updateNewEncryptedMessage)update).message); + ArrayList decryptedMessages = SecretChatHelper.getInstance().decryptMessage(((TLRPC.TL_updateNewEncryptedMessage)update).message); if (decryptedMessages != null && !decryptedMessages.isEmpty()) { int cid = ((TLRPC.TL_updateNewEncryptedMessage)update).message.chat_id; long uid = ((long) cid) << 32; @@ -3208,84 +3186,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (update instanceof TLRPC.TL_updateDcOptions) { ConnectionsManager.getInstance().updateDcSettings(0); } else if (update instanceof TLRPC.TL_updateEncryption) { - final TLRPC.EncryptedChat newChat = update.chat; - long dialog_id = ((long)newChat.id) << 32; - TLRPC.EncryptedChat existingChat = getEncryptedChatDB(newChat.id); - - if (newChat instanceof TLRPC.TL_encryptedChatRequested && existingChat == null) { - int user_id = newChat.participant_id; - if (user_id == UserConfig.getClientUserId()) { - user_id = newChat.admin_id; - } - TLRPC.User user = getUser(user_id); - if (user == null) { - user = usersDict.get(user_id); - } - newChat.user_id = user_id; - final TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); - dialog.id = dialog_id; - dialog.unread_count = 0; - dialog.top_message = 0; - dialog.last_message_date = update.date; - - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - dialogs_dict.put(dialog.id, dialog); - dialogs.add(dialog); - dialogsServerOnly.clear(); - putEncryptedChat(newChat, false); - Collections.sort(dialogs, new Comparator() { - @Override - public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) { - if (tl_dialog.last_message_date == tl_dialog2.last_message_date) { - return 0; - } else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) { - return 1; - } else { - return -1; - } - } - }); - for (TLRPC.TL_dialog d : dialogs) { - int high_id = (int)(d.id >> 32); - if ((int)d.id != 0 && high_id != 1) { - dialogsServerOnly.add(d); - } - } - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - } - }); - MessagesStorage.getInstance().putEncryptedChat(newChat, user, dialog); - acceptSecretChat(newChat); - } else if (newChat instanceof TLRPC.TL_encryptedChat) { - if (existingChat != null && existingChat instanceof TLRPC.TL_encryptedChatWaiting && (existingChat.auth_key == null || existingChat.auth_key.length == 1)) { - newChat.a_or_b = existingChat.a_or_b; - newChat.user_id = existingChat.user_id; - processAcceptedSecretChat(newChat); - } else if (existingChat == null && startingSecretChat) { - delayedEncryptedChatUpdates.add(update); - } - } else { - final TLRPC.EncryptedChat exist = existingChat; - if (exist != null) { - newChat.user_id = exist.user_id; - newChat.auth_key = exist.auth_key; - newChat.ttl = exist.ttl; - newChat.seq_in = exist.seq_in; - newChat.seq_out = exist.seq_out; - } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (exist != null) { - putEncryptedChat(newChat, false); - } - MessagesStorage.getInstance().updateEncryptedChat(newChat); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); - } - }); - } + SecretChatHelper.getInstance().processUpdateEncryption((TLRPC.TL_updateEncryption) update, usersDict); } else if (update instanceof TLRPC.TL_updateUserBlocked) { final TLRPC.TL_updateUserBlocked finalUpdate = (TLRPC.TL_updateUserBlocked)update; if (finalUpdate.blocked) { @@ -3358,7 +3259,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter final int interfaceUpdateMaskFinal = interfaceUpdateMask; final boolean printChangedArg = printChanged; - processPendingEncMessages(); + SecretChatHelper.getInstance().processPendingEncMessages(); if (!contactsIds.isEmpty()) { ContactsController.getInstance().processContactsUpdates(contactsIds, usersDict); @@ -3393,9 +3294,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter ArrayList dbUsersStatus = new ArrayList(); SharedPreferences.Editor editor = null; for (TLRPC.Update update : updatesOnMainThread) { - TLRPC.User toDbUser = new TLRPC.User(); + final TLRPC.User toDbUser = new TLRPC.User(); toDbUser.id = update.user_id; - TLRPC.User currentUser = getUser(update.user_id); + final TLRPC.User currentUser = getUser(update.user_id); if (update instanceof TLRPC.TL_updatePrivacy) { if (update.key instanceof TLRPC.TL_privacyKeyStatusTimestamp) { ContactsController.getInstance().setPrivacyRules(update.rules); @@ -3431,6 +3332,18 @@ public class MessagesController implements NotificationCenter.NotificationCenter avatarsUpdate = true; toDbUser.photo = update.photo; dbUsers.add(toDbUser); + } else if (update instanceof TLRPC.TL_updateUserPhone) { + if (currentUser != null) { + currentUser.phone = update.phone; + Utilities.photoBookQueue.postRunnable(new Runnable() { + @Override + public void run() { + ContactsController.getInstance().addContactToPhoneBook(currentUser, true); + } + }); + } + toDbUser.phone = update.phone; + dbUsers.add(toDbUser); } else if (update instanceof TLRPC.TL_updateNotifySettings) { if (update.notify_settings instanceof TLRPC.TL_peerNotifySettings && update.peer instanceof TLRPC.TL_notifyPeer) { if (editor == null) { @@ -3688,724 +3601,4 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } } - - public TLRPC.Message processDecryptedObject(final TLRPC.EncryptedChat chat, final TLRPC.EncryptedFile file, int date, long random_id, TLObject object) { - if (object != null) { - int from_id = chat.admin_id; - if (from_id == UserConfig.getClientUserId()) { - from_id = chat.participant_id; - } - - if (object instanceof TLRPC.TL_decryptedMessage) { - TLRPC.TL_decryptedMessage decryptedMessage = (TLRPC.TL_decryptedMessage)object; - TLRPC.TL_message newMessage = null; - if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 17) { - newMessage = new TLRPC.TL_message_secret(); - newMessage.ttl = decryptedMessage.ttl; - } else { - newMessage = new TLRPC.TL_message(); - newMessage.ttl = chat.ttl; - } - newMessage.message = decryptedMessage.message; - newMessage.date = date; - newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); - UserConfig.saveConfig(false); - newMessage.from_id = from_id; - newMessage.to_id = new TLRPC.TL_peerUser(); - newMessage.random_id = random_id; - newMessage.to_id.user_id = UserConfig.getClientUserId(); - newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; - newMessage.dialog_id = ((long)chat.id) << 32; - if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) { - newMessage.media = new TLRPC.TL_messageMediaEmpty(); - } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaContact) { - newMessage.media = new TLRPC.TL_messageMediaContact(); - newMessage.media.last_name = decryptedMessage.media.last_name; - newMessage.media.first_name = decryptedMessage.media.first_name; - newMessage.media.phone_number = decryptedMessage.media.phone_number; - newMessage.media.user_id = decryptedMessage.media.user_id; - } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaGeoPoint) { - newMessage.media = new TLRPC.TL_messageMediaGeo(); - newMessage.media.geo = new TLRPC.TL_geoPoint(); - newMessage.media.geo.lat = decryptedMessage.media.lat; - newMessage.media.geo._long = decryptedMessage.media._long; - } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaPhoto) { - if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { - return null; - } - newMessage.media = new TLRPC.TL_messageMediaPhoto(); - newMessage.media.photo = new TLRPC.TL_photo(); - newMessage.media.photo.user_id = newMessage.from_id; - newMessage.media.photo.date = newMessage.date; - newMessage.media.photo.caption = ""; - newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty(); - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { - TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize(); - small.w = decryptedMessage.media.thumb_w; - small.h = decryptedMessage.media.thumb_h; - small.bytes = decryptedMessage.media.thumb; - small.type = "s"; - small.location = new TLRPC.TL_fileLocationUnavailable(); - newMessage.media.photo.sizes.add(small); - } - - TLRPC.TL_photoSize big = new TLRPC.TL_photoSize(); - big.w = decryptedMessage.media.w; - big.h = decryptedMessage.media.h; - big.type = "x"; - big.size = file.size; - big.location = new TLRPC.TL_fileEncryptedLocation(); - big.location.key = decryptedMessage.media.key; - big.location.iv = decryptedMessage.media.iv; - big.location.dc_id = file.dc_id; - big.location.volume_id = file.id; - big.location.secret = file.access_hash; - big.location.local_id = file.key_fingerprint; - newMessage.media.photo.sizes.add(big); - } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaVideo) { - if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { - return null; - } - newMessage.media = new TLRPC.TL_messageMediaVideo(); - newMessage.media.video = new TLRPC.TL_videoEncrypted(); - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { - newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize(); - newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb; - newMessage.media.video.thumb.w = decryptedMessage.media.thumb_w; - newMessage.media.video.thumb.h = decryptedMessage.media.thumb_h; - newMessage.media.video.thumb.type = "s"; - newMessage.media.video.thumb.location = new TLRPC.TL_fileLocationUnavailable(); - } else { - newMessage.media.video.thumb = new TLRPC.TL_photoSizeEmpty(); - newMessage.media.video.thumb.type = "s"; - } - newMessage.media.video.duration = decryptedMessage.media.duration; - newMessage.media.video.dc_id = file.dc_id; - newMessage.media.video.w = decryptedMessage.media.w; - newMessage.media.video.h = decryptedMessage.media.h; - newMessage.media.video.date = date; - newMessage.media.video.caption = ""; - newMessage.media.video.user_id = from_id; - newMessage.media.video.size = file.size; - newMessage.media.video.id = file.id; - newMessage.media.video.access_hash = file.access_hash; - newMessage.media.video.key = decryptedMessage.media.key; - newMessage.media.video.iv = decryptedMessage.media.iv; - newMessage.media.video.mime_type = decryptedMessage.media.mime_type; - if (newMessage.ttl != 0) { - newMessage.ttl = Math.max(newMessage.media.video.duration + 1, newMessage.ttl); - } - if (newMessage.media.video.mime_type == null) { - newMessage.media.video.mime_type = "video/mp4"; - } - } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaDocument) { - if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { - return null; - } - newMessage.media = new TLRPC.TL_messageMediaDocument(); - newMessage.media.document = new TLRPC.TL_documentEncrypted(); - newMessage.media.document.id = file.id; - newMessage.media.document.access_hash = file.access_hash; - newMessage.media.document.user_id = decryptedMessage.media.user_id; - newMessage.media.document.date = date; - newMessage.media.document.file_name = decryptedMessage.media.file_name; - newMessage.media.document.mime_type = decryptedMessage.media.mime_type; - newMessage.media.document.size = file.size; - newMessage.media.document.key = decryptedMessage.media.key; - newMessage.media.document.iv = decryptedMessage.media.iv; - if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { - newMessage.media.document.thumb = new TLRPC.TL_photoCachedSize(); - newMessage.media.document.thumb.bytes = decryptedMessage.media.thumb; - newMessage.media.document.thumb.w = decryptedMessage.media.thumb_w; - newMessage.media.document.thumb.h = decryptedMessage.media.thumb_h; - newMessage.media.document.thumb.type = "s"; - newMessage.media.document.thumb.location = new TLRPC.TL_fileLocationUnavailable(); - } else { - newMessage.media.document.thumb = new TLRPC.TL_photoSizeEmpty(); - newMessage.media.document.thumb.type = "s"; - } - newMessage.media.document.dc_id = file.dc_id; - } 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; - } - newMessage.media = new TLRPC.TL_messageMediaAudio(); - newMessage.media.audio = new TLRPC.TL_audioEncrypted(); - newMessage.media.audio.id = file.id; - newMessage.media.audio.access_hash = file.access_hash; - newMessage.media.audio.user_id = from_id; - newMessage.media.audio.date = date; - newMessage.media.audio.size = file.size; - newMessage.media.audio.key = decryptedMessage.media.key; - newMessage.media.audio.iv = decryptedMessage.media.iv; - newMessage.media.audio.dc_id = file.dc_id; - newMessage.media.audio.duration = decryptedMessage.media.duration; - newMessage.media.audio.mime_type = decryptedMessage.media.mime_type; - if (newMessage.ttl != 0) { - newMessage.ttl = Math.max(newMessage.media.audio.duration + 1, newMessage.ttl); - } - if (newMessage.media.audio.mime_type == null) { - newMessage.media.audio.mime_type = "audio/ogg"; - } - } else { - return null; - } - return newMessage; - } else if (object instanceof TLRPC.TL_decryptedMessageService) { - final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService)object; - if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL || serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) { - TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService(); - if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { - newMessage.action = new TLRPC.TL_messageEncryptedAction(); - if (serviceMessage.action.ttl_seconds < 0 || serviceMessage.action.ttl_seconds > 60 * 60 * 24 * 365) { - serviceMessage.action.ttl_seconds = 60 * 60 * 24 * 365; - } - chat.ttl = serviceMessage.action.ttl_seconds; - newMessage.action.encryptedAction = serviceMessage.action; - MessagesStorage.getInstance().updateEncryptedChatTTL(chat); - } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) { - newMessage.action = new TLRPC.TL_messageEncryptedAction(); - newMessage.action.encryptedAction = serviceMessage.action; - } - newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); - UserConfig.saveConfig(false); - newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; - newMessage.date = date; - newMessage.from_id = from_id; - newMessage.to_id = new TLRPC.TL_peerUser(); - newMessage.to_id.user_id = UserConfig.getClientUserId(); - newMessage.dialog_id = ((long)chat.id) << 32; - return newMessage; - } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionFlushHistory) { - final long did = ((long)chat.id) << 32; - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - TLRPC.TL_dialog dialog = dialogs_dict.get(did); - if (dialog != null) { - dialog.unread_count = 0; - dialogMessage.remove(dialog.top_message); - } - MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { - @Override - public void run() { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationsController.getInstance().processReadMessages(null, did, 0, Integer.MAX_VALUE, false); - HashMap dialogsToUpdate = new HashMap(); - dialogsToUpdate.put(did, 0); - NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); - } - }); - } - }); - MessagesStorage.getInstance().deleteDialog(did, true); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.removeAllMessagesFromDialog, did); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - } - }); - return null; - } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionDeleteMessages) { - if (!serviceMessage.action.random_ids.isEmpty()) { - pendingEncMessagesToDelete.addAll(serviceMessage.action.random_ids); - } - return null; - } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionReadMessages) { - if (!serviceMessage.action.random_ids.isEmpty()) { - MessagesStorage.getInstance().createTaskForSecretChat(chat.id, ConnectionsManager.getInstance().getCurrentTime(), ConnectionsManager.getInstance().getCurrentTime(), 1, serviceMessage.action.random_ids); - } - } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionNotifyLayer) { - int currentPeerLayer = AndroidUtilities.getPeerLayerVersion(chat.layer); - chat.layer = 0; - chat.layer = AndroidUtilities.setPeerLayerVersion(chat.layer, serviceMessage.action.layer); - MessagesStorage.getInstance().updateEncryptedChatLayer(chat); - if (currentPeerLayer < 17) { - SendMessagesHelper.getInstance().sendNotifyLayerMessage(chat, null); - } - } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionResend) { - - } else { - return null; - } - } else { - FileLog.e("tmessages", "unkown message " + object); - } - } else { - FileLog.e("tmessages", "unkown TLObject"); - } - return null; - } - - public void checkSecretHoles(TLRPC.EncryptedChat chat, ArrayList messages) { - ArrayList holes = secretHolesQueue.get(chat.id); - if (holes == null) { - return; - } - Collections.sort(holes, new Comparator() { - @Override - public int compare(TLRPC.TL_decryptedMessageHolder lhs, TLRPC.TL_decryptedMessageHolder rhs) { - if (lhs.layer.out_seq_no > rhs.layer.out_seq_no) { - return 1; - } else if (lhs.layer.out_seq_no < rhs.layer.out_seq_no) { - return -1; - } - return 0; - } - }); - - boolean update = false; - for (int a = 0; a < holes.size(); a++) { - TLRPC.TL_decryptedMessageHolder holder = holes.get(a); - if (holder.layer.out_seq_no == chat.seq_in || chat.seq_in == holder.layer.out_seq_no - 2) { - chat.seq_in = holder.layer.out_seq_no; - holes.remove(a); - a--; - update = true; - - TLRPC.Message message = processDecryptedObject(chat, holder.file, holder.date, holder.random_id, holder.layer.message); - if (message != null) { - messages.add(message); - } - } else { - break; - } - } - if (holes.isEmpty()) { - secretHolesQueue.remove(chat.id); - } - if (update) { - MessagesStorage.getInstance().updateEncryptedChatSeq(chat); - } - } - - public ArrayList decryptMessage(TLRPC.EncryptedMessage message) { - final TLRPC.EncryptedChat chat = getEncryptedChatDB(message.chat_id); - if (chat == null || chat instanceof TLRPC.TL_encryptedChatDiscarded) { - return null; - } - ByteBufferDesc is = BuffersStorage.getInstance().getFreeBuffer(message.bytes.length); - is.writeRaw(message.bytes); - is.position(0); - long fingerprint = is.readInt64(); - if (chat.key_fingerprint == fingerprint) { - byte[] messageKey = is.readData(16); - MessageKeyData keyData = Utilities.generateMessageKeyData(chat.auth_key, messageKey, false); - - Utilities.aesIgeEncryption(is.buffer, keyData.aesKey, keyData.aesIv, false, false, 24, is.limit() - 24); - - int len = is.readInt32(); - TLObject object = TLClassStore.Instance().TLdeserialize(is, is.readInt32()); - BuffersStorage.getInstance().reuseFreeBuffer(is); - if (object instanceof TLRPC.TL_decryptedMessageLayer) { - final TLRPC.TL_decryptedMessageLayer layer = (TLRPC.TL_decryptedMessageLayer)object; - if (chat.seq_in == 0 && chat.seq_out == 0) { - if (chat.admin_id == UserConfig.getClientUserId()) { - chat.seq_out = 1; - } else { - chat.seq_in = 1; - } - } - if (layer.out_seq_no < chat.seq_in) { - return null; - } - if (chat.seq_in != layer.out_seq_no && chat.seq_in != layer.out_seq_no - 2) { - ArrayList arr = secretHolesQueue.get(chat.id); - if (arr == null) { - arr = new ArrayList(); - secretHolesQueue.put(chat.id, arr); - } - if (arr.size() >= 10) { - secretHolesQueue.remove(chat.id); - 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.seq_in = chat.seq_in; - newChat.seq_out = chat.seq_out; - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - putEncryptedChat(newChat, false); - MessagesStorage.getInstance().updateEncryptedChat(newChat); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); - } - }); - declineSecretChat(chat.id); - return null; - } - - TLRPC.TL_decryptedMessageHolder holder = new TLRPC.TL_decryptedMessageHolder(); - holder.layer = layer; - holder.file = message.file; - holder.random_id = message.random_id; - holder.date = message.date; - arr.add(holder); - return null; - } - chat.seq_in = layer.out_seq_no; - MessagesStorage.getInstance().updateEncryptedChatSeq(chat); - object = layer.message; - } - ArrayList messages = new ArrayList(); - TLRPC.Message decryptedMessage = processDecryptedObject(chat, message.file, message.date, message.random_id, object); - if (decryptedMessage != null) { - messages.add(decryptedMessage); - } - checkSecretHoles(chat, messages); - return messages; - } else { - BuffersStorage.getInstance().reuseFreeBuffer(is); - FileLog.e("tmessages", "fingerprint mismatch"); - } - return null; - } - - public void processAcceptedSecretChat(final TLRPC.EncryptedChat encryptedChat) { - BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes); - BigInteger i_authKey = new BigInteger(1, encryptedChat.g_a_or_b); - - if (!Utilities.isGoodGaAndGb(i_authKey, p)) { - declineSecretChat(encryptedChat.id); - return; - } - - i_authKey = i_authKey.modPow(new BigInteger(1, encryptedChat.a_or_b), p); - - byte[] authKey = i_authKey.toByteArray(); - if (authKey.length > 256) { - byte[] correctedAuth = new byte[256]; - System.arraycopy(authKey, authKey.length - 256, correctedAuth, 0, 256); - authKey = correctedAuth; - } else if (authKey.length < 256) { - byte[] correctedAuth = new byte[256]; - System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length); - for (int a = 0; a < 256 - authKey.length; a++) { - authKey[a] = 0; - } - authKey = correctedAuth; - } - byte[] authKeyHash = Utilities.computeSHA1(authKey); - byte[] authKeyId = new byte[8]; - System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8); - long fingerprint = Utilities.bytesToLong(authKeyId); - if (encryptedChat.key_fingerprint == fingerprint) { - encryptedChat.auth_key = authKey; - encryptedChat.seq_in = 0; - encryptedChat.seq_out = 1; - MessagesStorage.getInstance().updateEncryptedChat(encryptedChat); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - putEncryptedChat(encryptedChat, false); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, encryptedChat); - SendMessagesHelper.getInstance().sendNotifyLayerMessage(encryptedChat, null); - } - }); - } else { - final TLRPC.TL_encryptedChatDiscarded newChat = new TLRPC.TL_encryptedChatDiscarded(); - newChat.id = encryptedChat.id; - newChat.user_id = encryptedChat.user_id; - newChat.auth_key = encryptedChat.auth_key; - newChat.seq_in = encryptedChat.seq_in; - newChat.seq_out = encryptedChat.seq_out; - MessagesStorage.getInstance().updateEncryptedChat(newChat); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - putEncryptedChat(newChat, false); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); - } - }); - declineSecretChat(encryptedChat.id); - } - } - - public void declineSecretChat(int chat_id) { - TLRPC.TL_messages_discardEncryption req = new TLRPC.TL_messages_discardEncryption(); - req.chat_id = chat_id; - ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(TLObject response, TLRPC.TL_error error) { - - } - }); - } - - public void acceptSecretChat(final TLRPC.EncryptedChat encryptedChat) { - if (acceptingChats.get(encryptedChat.id) != null) { - return; - } - acceptingChats.put(encryptedChat.id, encryptedChat); - TLRPC.TL_messages_getDhConfig req = new TLRPC.TL_messages_getDhConfig(); - req.random_length = 256; - req.version = MessagesStorage.lastSecretVersion; - ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(TLObject response, TLRPC.TL_error error) { - if (error == null) { - TLRPC.messages_DhConfig res = (TLRPC.messages_DhConfig) response; - if (response instanceof TLRPC.TL_messages_dhConfig) { - if (!Utilities.isGoodPrime(res.p, res.g)) { - acceptingChats.remove(encryptedChat.id); - declineSecretChat(encryptedChat.id); - return; - } - - MessagesStorage.secretPBytes = res.p; - MessagesStorage.secretG = res.g; - MessagesStorage.lastSecretVersion = res.version; - MessagesStorage.getInstance().saveSecretParams(MessagesStorage.lastSecretVersion, MessagesStorage.secretG, MessagesStorage.secretPBytes); - } - byte[] salt = new byte[256]; - for (int a = 0; a < 256; a++) { - salt[a] = (byte) ((byte) (Utilities.random.nextDouble() * 256) ^ res.random[a]); - } - encryptedChat.a_or_b = salt; - encryptedChat.seq_in = 1; - encryptedChat.seq_out = 0; - BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes); - BigInteger g_b = BigInteger.valueOf(MessagesStorage.secretG); - g_b = g_b.modPow(new BigInteger(1, salt), p); - BigInteger g_a = new BigInteger(1, encryptedChat.g_a); - - if (!Utilities.isGoodGaAndGb(g_a, p)) { - acceptingChats.remove(encryptedChat.id); - declineSecretChat(encryptedChat.id); - return; - } - - byte[] g_b_bytes = g_b.toByteArray(); - if (g_b_bytes.length > 256) { - byte[] correctedAuth = new byte[256]; - System.arraycopy(g_b_bytes, 1, correctedAuth, 0, 256); - g_b_bytes = correctedAuth; - } - - g_a = g_a.modPow(new BigInteger(1, salt), p); - - byte[] authKey = g_a.toByteArray(); - if (authKey.length > 256) { - byte[] correctedAuth = new byte[256]; - System.arraycopy(authKey, authKey.length - 256, correctedAuth, 0, 256); - authKey = correctedAuth; - } else if (authKey.length < 256) { - byte[] correctedAuth = new byte[256]; - System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length); - for (int a = 0; a < 256 - authKey.length; a++) { - authKey[a] = 0; - } - authKey = correctedAuth; - } - byte[] authKeyHash = Utilities.computeSHA1(authKey); - byte[] authKeyId = new byte[8]; - System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8); - encryptedChat.auth_key = authKey; - - TLRPC.TL_messages_acceptEncryption req2 = new TLRPC.TL_messages_acceptEncryption(); - req2.g_b = g_b_bytes; - req2.peer = new TLRPC.TL_inputEncryptedChat(); - req2.peer.chat_id = encryptedChat.id; - req2.peer.access_hash = encryptedChat.access_hash; - req2.key_fingerprint = Utilities.bytesToLong(authKeyId); - ConnectionsManager.getInstance().performRpc(req2, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(TLObject response, TLRPC.TL_error error) { - acceptingChats.remove(encryptedChat.id); - if (error == null) { - final TLRPC.EncryptedChat newChat = (TLRPC.EncryptedChat) response; - newChat.auth_key = encryptedChat.auth_key; - newChat.user_id = encryptedChat.user_id; - newChat.seq_in = encryptedChat.seq_in; - newChat.seq_out = encryptedChat.seq_out; - MessagesStorage.getInstance().updateEncryptedChat(newChat); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - putEncryptedChat(newChat, false); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); - SendMessagesHelper.getInstance().sendNotifyLayerMessage(newChat, null); - } - }); - } - } - }); - } else { - acceptingChats.remove(encryptedChat.id); - } - } - }); - } - - public void startSecretChat(final Context context, final TLRPC.User user) { - if (user == null) { - return; - } - startingSecretChat = true; - final ProgressDialog progressDialog = new ProgressDialog(context); - progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); - progressDialog.setCanceledOnTouchOutside(false); - progressDialog.setCancelable(false); - TLRPC.TL_messages_getDhConfig req = new TLRPC.TL_messages_getDhConfig(); - req.random_length = 256; - req.version = MessagesStorage.lastSecretVersion; - final long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(TLObject response, TLRPC.TL_error error) { - if (error == null) { - TLRPC.messages_DhConfig res = (TLRPC.messages_DhConfig) response; - if (response instanceof TLRPC.TL_messages_dhConfig) { - if (!Utilities.isGoodPrime(res.p, res.g)) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - try { - if (!((Activity) context).isFinishing()) { - progressDialog.dismiss(); - } - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - }); - return; - } - MessagesStorage.secretPBytes = res.p; - MessagesStorage.secretG = res.g; - MessagesStorage.lastSecretVersion = res.version; - MessagesStorage.getInstance().saveSecretParams(MessagesStorage.lastSecretVersion, MessagesStorage.secretG, MessagesStorage.secretPBytes); - } - final byte[] salt = new byte[256]; - for (int a = 0; a < 256; a++) { - salt[a] = (byte) ((byte) (Utilities.random.nextDouble() * 256) ^ res.random[a]); - } - - BigInteger i_g_a = BigInteger.valueOf(MessagesStorage.secretG); - i_g_a = i_g_a.modPow(new BigInteger(1, salt), new BigInteger(1, MessagesStorage.secretPBytes)); - byte[] g_a = i_g_a.toByteArray(); - if (g_a.length > 256) { - byte[] correctedAuth = new byte[256]; - System.arraycopy(g_a, 1, correctedAuth, 0, 256); - g_a = correctedAuth; - } - - TLRPC.TL_messages_requestEncryption req2 = new TLRPC.TL_messages_requestEncryption(); - req2.g_a = g_a; - req2.user_id = getInputUser(user); - req2.random_id = Utilities.random.nextInt(); - ConnectionsManager.getInstance().performRpc(req2, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(final TLObject response, TLRPC.TL_error error) { - if (error == null) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - startingSecretChat = false; - if (!((Activity) context).isFinishing()) { - try { - progressDialog.dismiss(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) response; - chat.user_id = chat.participant_id; - chat.seq_in = 0; - chat.seq_out = 1; - chat.a_or_b = salt; - putEncryptedChat(chat, false); - TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); - dialog.id = ((long) chat.id) << 32; - dialog.unread_count = 0; - dialog.top_message = 0; - dialog.last_message_date = ConnectionsManager.getInstance().getCurrentTime(); - dialogs_dict.put(dialog.id, dialog); - dialogs.add(dialog); - dialogsServerOnly.clear(); - Collections.sort(dialogs, new Comparator() { - @Override - public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) { - if (tl_dialog.last_message_date == tl_dialog2.last_message_date) { - return 0; - } else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) { - return 1; - } else { - return -1; - } - } - }); - for (TLRPC.TL_dialog d : dialogs) { - int high_id = (int)(d.id >> 32); - if ((int)d.id != 0 && high_id != 1) { - dialogsServerOnly.add(d); - } - } - MessagesStorage.getInstance().putEncryptedChat(chat, user, dialog); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatCreated, chat); - Utilities.stageQueue.postRunnable(new Runnable() { - @Override - public void run() { - if (!delayedEncryptedChatUpdates.isEmpty()) { - processUpdateArray(delayedEncryptedChatUpdates, null, null); - delayedEncryptedChatUpdates.clear(); - } - } - }); - } - }); - } else { - delayedEncryptedChatUpdates.clear(); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (!((Activity) context).isFinishing()) { - startingSecretChat = false; - try { - progressDialog.dismiss(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("CreateEncryptedChatError", R.string.CreateEncryptedChatError)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - builder.show().setCanceledOnTouchOutside(true); - } - } - }); - } - } - }, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors); - } else { - delayedEncryptedChatUpdates.clear(); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - startingSecretChat = false; - if (!((Activity) context).isFinishing()) { - try { - progressDialog.dismiss(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - } - }); - } - } - }, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors); - progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - ConnectionsManager.getInstance().cancelRpc(reqId, true); - try { - dialog.dismiss(); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - }); - progressDialog.show(); - } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java index 8a98a206..2199f5c4 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java @@ -28,7 +28,7 @@ import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import java.io.File; import java.util.ArrayList; @@ -104,7 +104,7 @@ public class MessagesStorage { database.executeFast("CREATE TABLE users(uid INTEGER PRIMARY KEY, name TEXT, status INTEGER, data BLOB)").stepThis().dispose(); database.executeFast("CREATE TABLE messages(mid INTEGER PRIMARY KEY, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER)").stepThis().dispose(); database.executeFast("CREATE TABLE chats(uid INTEGER PRIMARY KEY, name TEXT, data BLOB)").stepThis().dispose(); - database.executeFast("CREATE TABLE enc_chats(uid INTEGER PRIMARY KEY, user INTEGER, name TEXT, data BLOB, g BLOB, authkey BLOB, ttl INTEGER, layer INTEGER, seq_in INTEGER, seq_out INTEGER)").stepThis().dispose(); + database.executeFast("CREATE TABLE enc_chats(uid INTEGER PRIMARY KEY, user INTEGER, name TEXT, data BLOB, g BLOB, authkey BLOB, ttl INTEGER, layer INTEGER, seq_in INTEGER, seq_out INTEGER, use_count INTEGER, exchange_id INTEGER, key_date INTEGER, fprint INTEGER, fauthkey BLOB, khash BLOB)").stepThis().dispose(); database.executeFast("CREATE TABLE dialogs(did INTEGER PRIMARY KEY, date INTEGER, unread_count INTEGER, last_mid INTEGER)").stepThis().dispose(); database.executeFast("CREATE TABLE chat_settings(uid INTEGER PRIMARY KEY, participants BLOB)").stepThis().dispose(); database.executeFast("CREATE TABLE contacts(uid INTEGER PRIMARY KEY, mutual INTEGER)").stepThis().dispose(); @@ -156,7 +156,7 @@ public class MessagesStorage { database.executeFast("CREATE INDEX IF NOT EXISTS seq_idx_messages_seq ON messages_seq(seq_in, seq_out);").stepThis().dispose(); - database.executeFast("PRAGMA user_version = 7").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 10").stepThis().dispose(); } else { try { SQLiteCursor cursor = database.queryFinalized("SELECT seq, pts, date, qts, lsv, sg, pbytes FROM params WHERE id = 1"); @@ -188,7 +188,7 @@ public class MessagesStorage { } int version = database.executeInt("PRAGMA user_version"); - if (version < 9) { + if (version < 10) { updateDbToLastVersion(version); } } @@ -329,6 +329,16 @@ public class MessagesStorage { database.executeFast("PRAGMA user_version = 9").stepThis().dispose(); version = 9; }*/ + if ((version == 7 || version == 8 || version == 9) && version < 10) { + database.executeFast("ALTER TABLE enc_chats ADD COLUMN use_count INTEGER default 0").stepThis().dispose(); + database.executeFast("ALTER TABLE enc_chats ADD COLUMN exchange_id INTEGER default 0").stepThis().dispose(); + database.executeFast("ALTER TABLE enc_chats ADD COLUMN key_date INTEGER default 0").stepThis().dispose(); + database.executeFast("ALTER TABLE enc_chats ADD COLUMN fprint INTEGER default 0").stepThis().dispose(); + database.executeFast("ALTER TABLE enc_chats ADD COLUMN fauthkey BLOB default NULL").stepThis().dispose(); + database.executeFast("ALTER TABLE enc_chats ADD COLUMN khash BLOB default NULL").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 10").stepThis().dispose(); + version = 10; + } } catch (Exception e) { FileLog.e("tmessages", e); } @@ -1329,9 +1339,6 @@ public class MessagesStorage { StringBuilder uids = new StringBuilder(); while (cursor.next()) { int user_id = cursor.intValue(0); - if (user_id == UserConfig.getClientUserId()) { - continue; - } TLRPC.TL_contact contact = new TLRPC.TL_contact(); contact.user_id = user_id; contact.mutual = cursor.intValue(1) == 1; @@ -2008,10 +2015,11 @@ public class MessagesStorage { public void run() { SQLitePreparedStatement state = null; try { - state = database.executeFast("UPDATE enc_chats SET seq_in = ?, seq_out = ? WHERE uid = ?"); + state = database.executeFast("UPDATE enc_chats SET seq_in = ?, seq_out = ?, use_count = ? WHERE uid = ?"); state.bindInteger(1, chat.seq_in); state.bindInteger(2, chat.seq_out); - state.bindInteger(3, chat.id); + state.bindInteger(3, (int)chat.key_use_count_in << 16 | chat.key_use_count_out); + state.bindInteger(4, chat.id); state.step(); } catch (Exception e) { FileLog.e("tmessages", e); @@ -2081,10 +2089,18 @@ public class MessagesStorage { public void run() { SQLitePreparedStatement state = null; try { - state = database.executeFast("UPDATE enc_chats SET data = ?, g = ?, authkey = ?, ttl = ?, layer = ?, seq_in = ?, seq_out = ? WHERE uid = ?"); + if ((chat.key_hash == null || chat.key_hash.length != 16) && chat.auth_key != null) { + byte[] sha1 = Utilities.computeSHA1(chat.auth_key); + chat.key_hash = new byte[16]; + System.arraycopy(sha1, 0, chat.key_hash, 0, chat.key_hash.length); + } + + state = database.executeFast("UPDATE enc_chats SET data = ?, g = ?, authkey = ?, ttl = ?, layer = ?, seq_in = ?, seq_out = ?, use_count = ?, exchange_id = ?, key_date = ?, fprint = ?, fauthkey = ?, khash = ? WHERE uid = ?"); ByteBufferDesc data = buffersStorage.getFreeBuffer(chat.getObjectSize()); ByteBufferDesc data2 = buffersStorage.getFreeBuffer(chat.a_or_b != null ? chat.a_or_b.length : 1); ByteBufferDesc data3 = buffersStorage.getFreeBuffer(chat.auth_key != null ? chat.auth_key.length : 1); + ByteBufferDesc data4 = buffersStorage.getFreeBuffer(chat.future_auth_key != null ? chat.future_auth_key.length : 1); + ByteBufferDesc data5 = buffersStorage.getFreeBuffer(chat.key_hash != null ? chat.key_hash.length : 1); chat.serializeToStream(data); state.bindByteBuffer(1, data.buffer); if (chat.a_or_b != null) { @@ -2093,17 +2109,32 @@ public class MessagesStorage { if (chat.auth_key != null) { data3.writeRaw(chat.auth_key); } + if (chat.future_auth_key != null) { + data4.writeRaw(chat.future_auth_key); + } + if (chat.key_hash != null) { + data5.writeRaw(chat.key_hash); + } state.bindByteBuffer(2, data2.buffer); state.bindByteBuffer(3, data3.buffer); state.bindInteger(4, chat.ttl); state.bindInteger(5, chat.layer); state.bindInteger(6, chat.seq_in); state.bindInteger(7, chat.seq_out); - state.bindInteger(8, chat.id); + state.bindInteger(8, (int)chat.key_use_count_in << 16 | chat.key_use_count_out); + state.bindLong(9, chat.exchange_id); + state.bindInteger(10, chat.key_create_date); + state.bindLong(11, chat.future_key_fingerprint); + state.bindByteBuffer(12, data4.buffer); + state.bindByteBuffer(13, data5.buffer); + state.bindInteger(14, chat.id); + state.step(); buffersStorage.reuseFreeBuffer(data); buffersStorage.reuseFreeBuffer(data2); buffersStorage.reuseFreeBuffer(data3); + buffersStorage.reuseFreeBuffer(data4); + buffersStorage.reuseFreeBuffer(data5); } catch (Exception e) { FileLog.e("tmessages", e); } finally { @@ -2151,10 +2182,17 @@ public class MessagesStorage { @Override public void run() { try { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO enc_chats VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + if ((chat.key_hash == null || chat.key_hash.length != 16) && chat.auth_key != null) { + byte[] sha1 = Utilities.computeSHA1(chat.auth_key); + chat.key_hash = new byte[16]; + System.arraycopy(sha1, 0, chat.key_hash, 0, chat.key_hash.length); + } + SQLitePreparedStatement state = database.executeFast("REPLACE INTO enc_chats VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); ByteBufferDesc data = buffersStorage.getFreeBuffer(chat.getObjectSize()); ByteBufferDesc data2 = buffersStorage.getFreeBuffer(chat.a_or_b != null ? chat.a_or_b.length : 1); ByteBufferDesc data3 = buffersStorage.getFreeBuffer(chat.auth_key != null ? chat.auth_key.length : 1); + ByteBufferDesc data4 = buffersStorage.getFreeBuffer(chat.future_auth_key != null ? chat.future_auth_key.length : 1); + ByteBufferDesc data5 = buffersStorage.getFreeBuffer(chat.key_hash != null ? chat.key_hash.length : 1); chat.serializeToStream(data); state.bindInteger(1, chat.id); @@ -2167,17 +2205,32 @@ public class MessagesStorage { if (chat.auth_key != null) { data3.writeRaw(chat.auth_key); } + if (chat.future_auth_key != null) { + data4.writeRaw(chat.future_auth_key); + } + if (chat.key_hash != null) { + data5.writeRaw(chat.key_hash); + } state.bindByteBuffer(5, data2.buffer); state.bindByteBuffer(6, data3.buffer); state.bindInteger(7, chat.ttl); state.bindInteger(8, chat.layer); state.bindInteger(9, chat.seq_in); state.bindInteger(10, chat.seq_out); + state.bindInteger(11, (int)chat.key_use_count_in << 16 | chat.key_use_count_out); + state.bindLong(12, chat.exchange_id); + state.bindInteger(13, chat.key_create_date); + state.bindLong(14, chat.future_key_fingerprint); + state.bindByteBuffer(15, data4.buffer); + state.bindByteBuffer(16, data5.buffer); + state.step(); state.dispose(); buffersStorage.reuseFreeBuffer(data); buffersStorage.reuseFreeBuffer(data2); buffersStorage.reuseFreeBuffer(data3); + buffersStorage.reuseFreeBuffer(data4); + buffersStorage.reuseFreeBuffer(data5); if (dialog != null) { state = database.executeFast("REPLACE INTO dialogs(did, date, unread_count, last_mid) VALUES(?, ?, ?, ?)"); @@ -2317,8 +2370,8 @@ public class MessagesStorage { if (chatsToLoad == null || chatsToLoad.length() == 0 || result == null) { return; } - - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, user, g, authkey, ttl, layer, seq_in, seq_out FROM enc_chats WHERE uid IN(%s)", chatsToLoad)); + //use_count INTEGER, exchange_id INTEGER, key_date INTEGER, fprint INTEGER, fauthkey BLOB + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, user, g, authkey, ttl, layer, seq_in, seq_out, use_count, exchange_id, key_date, fprint, fauthkey, khash FROM enc_chats WHERE uid IN(%s)", chatsToLoad)); while (cursor.next()) { try { ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0)); @@ -2335,6 +2388,14 @@ public class MessagesStorage { chat.layer = cursor.intValue(5); chat.seq_in = cursor.intValue(6); chat.seq_out = cursor.intValue(7); + int use_count = cursor.intValue(8); + chat.key_use_count_in = (short)(use_count >> 16); + chat.key_use_count_out = (short)(use_count); + chat.exchange_id = cursor.longValue(9); + chat.key_create_date = cursor.intValue(10); + chat.future_key_fingerprint = cursor.longValue(11); + chat.future_auth_key = cursor.byteArrayValue(12); + chat.key_hash = cursor.byteArrayValue(13); result.add(chat); } } @@ -2994,6 +3055,8 @@ public class MessagesStorage { user.username = updateUser.username; } else if (updateUser.photo != null) { user.photo = updateUser.photo; + } else if (updateUser.phone != null) { + user.phone = updateUser.phone; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/NativeLoader.java b/TMessagesProj/src/main/java/org/telegram/android/NativeLoader.java index a4716d28..0aa1b69d 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NativeLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NativeLoader.java @@ -23,7 +23,7 @@ import java.util.zip.ZipFile; public class NativeLoader { - private final static int LIB_VERSION = 3; + private final static int LIB_VERSION = 4; 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/android/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java index 4d4840a6..a6c346e6 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java @@ -33,7 +33,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PopupNotificationActivity; diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationsService.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationsService.java index a790c798..91f90efb 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationsService.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationsService.java @@ -14,7 +14,7 @@ import android.content.SharedPreferences; import android.os.IBinder; import org.telegram.messenger.FileLog; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; public class NotificationsService extends Service { diff --git a/TMessagesProj/src/main/java/org/telegram/android/ScreenReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/ScreenReceiver.java index 7a357627..e6b6c757 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ScreenReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ScreenReceiver.java @@ -14,7 +14,7 @@ import android.content.Intent; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; public class ScreenReceiver extends BroadcastReceiver { @Override diff --git a/TMessagesProj/src/main/java/org/telegram/android/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/android/SecretChatHelper.java new file mode 100644 index 00000000..857a28c5 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/SecretChatHelper.java @@ -0,0 +1,1756 @@ +/* + * This is the source code of Telegram for Android v. 2.0.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. + */ + +package org.telegram.android; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; + +import org.telegram.messenger.BuffersStorage; +import org.telegram.messenger.ByteBufferDesc; +import org.telegram.messenger.ConnectionsManager; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.MessageKeyData; +import org.telegram.messenger.R; +import org.telegram.messenger.RPCRequest; +import org.telegram.messenger.TLClassStore; +import org.telegram.messenger.TLObject; +import org.telegram.messenger.TLRPC; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; + +import java.io.File; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; + +public class SecretChatHelper { + + public static final int CURRENT_SECRET_CHAT_LAYER = 20; + + private ArrayList sendingNotifyLayer = new ArrayList(); + private HashMap> secretHolesQueue = new HashMap>(); + private HashMap acceptingChats = new HashMap(); + public ArrayList delayedEncryptedChatUpdates = new ArrayList(); + private ArrayList pendingEncMessagesToDelete = new ArrayList(); + private boolean startingSecretChat = false; + + private static volatile SecretChatHelper Instance = null; + public static SecretChatHelper getInstance() { + SecretChatHelper localInstance = Instance; + if (localInstance == null) { + synchronized (SecretChatHelper.class) { + localInstance = Instance; + if (localInstance == null) { + Instance = localInstance = new SecretChatHelper(); + } + } + } + return localInstance; + } + + public void cleanUp() { + sendingNotifyLayer.clear(); + acceptingChats.clear(); + secretHolesQueue.clear(); + delayedEncryptedChatUpdates.clear(); + pendingEncMessagesToDelete.clear(); + + startingSecretChat = false; + } + + protected void processPendingEncMessages() { + if (!pendingEncMessagesToDelete.isEmpty()) { + ArrayList arr = new ArrayList(pendingEncMessagesToDelete); + MessagesStorage.getInstance().markMessagesAsDeletedByRandoms(arr); + pendingEncMessagesToDelete.clear(); + } + } + + private TLRPC.TL_messageService createServiceSecretMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.DecryptedMessageAction decryptedMessage) { + TLRPC.TL_messageService newMsg = new TLRPC.TL_messageService(); + + newMsg.action = new TLRPC.TL_messageEncryptedAction(); + newMsg.action.encryptedAction = decryptedMessage; + newMsg.local_id = newMsg.id = UserConfig.getNewMessageId(); + newMsg.from_id = UserConfig.getClientUserId(); + newMsg.flags = TLRPC.MESSAGE_FLAG_UNREAD | TLRPC.MESSAGE_FLAG_OUT; + newMsg.dialog_id = ((long)encryptedChat.id) << 32; + newMsg.to_id = new TLRPC.TL_peerUser(); + newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; + if (encryptedChat.participant_id == UserConfig.getClientUserId()) { + newMsg.to_id.user_id = encryptedChat.admin_id; + } else { + newMsg.to_id.user_id = encryptedChat.participant_id; + } + if (decryptedMessage instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || decryptedMessage instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { + newMsg.date = ConnectionsManager.getInstance().getCurrentTime(); + } else { + newMsg.date = 0; + } + newMsg.random_id = SendMessagesHelper.getInstance().getNextRandomId(); + UserConfig.saveConfig(false); + + ArrayList arr = new ArrayList(); + arr.add(newMsg); + MessagesStorage.getInstance().putMessages(arr, false, true, true, 0); + + return newMsg; + } + + public void sendMessagesReadMessage(TLRPC.EncryptedChat encryptedChat, ArrayList random_ids, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionReadMessages(); + reqSend.action.random_ids = random_ids; + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + protected void processUpdateEncryption(TLRPC.TL_updateEncryption update, ConcurrentHashMap usersDict) { + final TLRPC.EncryptedChat newChat = update.chat; + long dialog_id = ((long)newChat.id) << 32; + TLRPC.EncryptedChat existingChat = MessagesController.getInstance().getEncryptedChatDB(newChat.id); + + if (newChat instanceof TLRPC.TL_encryptedChatRequested && existingChat == null) { + int user_id = newChat.participant_id; + if (user_id == UserConfig.getClientUserId()) { + user_id = newChat.admin_id; + } + TLRPC.User user = MessagesController.getInstance().getUser(user_id); + if (user == null) { + user = usersDict.get(user_id); + } + newChat.user_id = user_id; + final TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); + dialog.id = dialog_id; + dialog.unread_count = 0; + dialog.top_message = 0; + dialog.last_message_date = update.date; + + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + MessagesController.getInstance().dialogs_dict.put(dialog.id, dialog); + MessagesController.getInstance().dialogs.add(dialog); + MessagesController.getInstance().putEncryptedChat(newChat, false); + Collections.sort(MessagesController.getInstance().dialogs, new Comparator() { + @Override + public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) { + if (tl_dialog.last_message_date == tl_dialog2.last_message_date) { + return 0; + } else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) { + return 1; + } else { + return -1; + } + } + }); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + } + }); + MessagesStorage.getInstance().putEncryptedChat(newChat, user, dialog); + SecretChatHelper.getInstance().acceptSecretChat(newChat); + } else if (newChat instanceof TLRPC.TL_encryptedChat) { + if (existingChat != null && existingChat instanceof TLRPC.TL_encryptedChatWaiting && (existingChat.auth_key == null || existingChat.auth_key.length == 1)) { + newChat.a_or_b = existingChat.a_or_b; + newChat.user_id = existingChat.user_id; + SecretChatHelper.getInstance().processAcceptedSecretChat(newChat); + } else if (existingChat == null && startingSecretChat) { + delayedEncryptedChatUpdates.add(update); + } + } else { + final TLRPC.EncryptedChat exist = existingChat; + if (exist != null) { + newChat.user_id = exist.user_id; + newChat.auth_key = exist.auth_key; + newChat.key_create_date = exist.key_create_date; + newChat.key_use_count_in = exist.key_use_count_in; + newChat.key_use_count_out = exist.key_use_count_out; + newChat.ttl = exist.ttl; + newChat.seq_in = exist.seq_in; + newChat.seq_out = exist.seq_out; + } + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (exist != null) { + MessagesController.getInstance().putEncryptedChat(newChat, false); + } + MessagesStorage.getInstance().updateEncryptedChat(newChat); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); + } + }); + } + } + + public void sendMessagesDeleteMessage(TLRPC.EncryptedChat encryptedChat, ArrayList random_ids, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionDeleteMessages(); + reqSend.action.random_ids = random_ids; + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendClearHistoryMessage(TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionFlushHistory(); + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendNotifyLayerMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + if (sendingNotifyLayer.contains(encryptedChat.id)) { + return; + } + sendingNotifyLayer.add(encryptedChat.id); + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionNotifyLayer(); + reqSend.action.layer = CURRENT_SECRET_CHAT_LAYER; + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendRequestKeyMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionRequestKey(); + reqSend.action.exchange_id = encryptedChat.exchange_id; + reqSend.action.g_a = encryptedChat.g_a; + + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendAcceptKeyMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionAcceptKey(); + reqSend.action.exchange_id = encryptedChat.exchange_id; + reqSend.action.key_fingerprint = encryptedChat.future_key_fingerprint; + reqSend.action.g_b = encryptedChat.g_a_or_b; + + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendCommitKeyMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionCommitKey(); + reqSend.action.exchange_id = encryptedChat.exchange_id; + reqSend.action.key_fingerprint = encryptedChat.future_key_fingerprint; + + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendAbortKeyMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage, long excange_id) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionAbortKey(); + reqSend.action.exchange_id = excange_id; + + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendNoopMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionNoop(); + message = createServiceSecretMessage(encryptedChat, reqSend.action); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendTTLMessage(TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionSetMessageTTL(); + reqSend.action.ttl_seconds = encryptedChat.ttl; + message = createServiceSecretMessage(encryptedChat, reqSend.action); + + MessageObject newMsgObj = new MessageObject(message, null); + newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; + ArrayList objArr = new ArrayList(); + objArr.add(newMsgObj); + MessagesController.getInstance().updateInterfaceWithMessages(message.dialog_id, objArr); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + public void sendScreenshotMessage(TLRPC.EncryptedChat encryptedChat, ArrayList random_ids, TLRPC.Message resendMessage) { + if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { + return; + } + + TLRPC.TL_decryptedMessageService reqSend = null; + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { + reqSend = new TLRPC.TL_decryptedMessageService(); + } else { + reqSend = new TLRPC.TL_decryptedMessageService_old(); + reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(reqSend.random_bytes); + } + + TLRPC.Message message = null; + + if (resendMessage != null) { + message = resendMessage; + reqSend.action = message.action.encryptedAction; + } else { + reqSend.action = new TLRPC.TL_decryptedMessageActionScreenshotMessages(); + reqSend.action.random_ids = random_ids; + message = createServiceSecretMessage(encryptedChat, reqSend.action); + + MessageObject newMsgObj = new MessageObject(message, null); + newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; + ArrayList objArr = new ArrayList(); + objArr.add(newMsgObj); + MessagesController.getInstance().updateInterfaceWithMessages(message.dialog_id, objArr); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + } + reqSend.random_id = message.random_id; + + performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); + } + + private void processSentMessage(TLRPC.Message newMsg, TLRPC.EncryptedFile file, TLRPC.DecryptedMessage decryptedMessage, String originalPath) { + if (file != null) { + if (newMsg.media instanceof TLRPC.TL_messageMediaPhoto && newMsg.media.photo != null) { + TLRPC.PhotoSize size = newMsg.media.photo.sizes.get(newMsg.media.photo.sizes.size() - 1); + String fileName = size.location.volume_id + "_" + size.location.local_id; + size.location = new TLRPC.TL_fileEncryptedLocation(); + size.location.key = decryptedMessage.media.key; + size.location.iv = decryptedMessage.media.iv; + size.location.dc_id = file.dc_id; + size.location.volume_id = file.id; + size.location.secret = file.access_hash; + size.location.local_id = file.key_fingerprint; + String fileName2 = size.location.volume_id + "_" + size.location.local_id; + File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); + File cacheFile2 = FileLoader.getPathToAttach(size); + cacheFile.renameTo(cacheFile2); + ImageLoader.getInstance().replaceImageInCache(fileName, fileName2); + ArrayList arr = new ArrayList(); + arr.add(newMsg); + MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); + + MessagesStorage.getInstance().putSentFile(originalPath, newMsg.media.photo, 3); + } else if (newMsg.media instanceof TLRPC.TL_messageMediaVideo && newMsg.media.video != null) { + TLRPC.Video video = newMsg.media.video; + newMsg.media.video = new TLRPC.TL_videoEncrypted(); + newMsg.media.video.duration = video.duration; + newMsg.media.video.thumb = video.thumb; + newMsg.media.video.dc_id = file.dc_id; + newMsg.media.video.w = video.w; + newMsg.media.video.h = video.h; + newMsg.media.video.date = video.date; + newMsg.media.video.caption = ""; + newMsg.media.video.user_id = video.user_id; + newMsg.media.video.size = file.size; + newMsg.media.video.id = file.id; + newMsg.media.video.access_hash = file.access_hash; + newMsg.media.video.key = decryptedMessage.media.key; + newMsg.media.video.iv = decryptedMessage.media.iv; + newMsg.media.video.mime_type = video.mime_type; + + if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { + File cacheFile = new File(newMsg.attachPath); + File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.video); + if (cacheFile.renameTo(cacheFile2)) { + newMsg.attachPath = ""; + } + } + + ArrayList arr = new ArrayList(); + arr.add(newMsg); + MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); + + MessagesStorage.getInstance().putSentFile(originalPath, newMsg.media.video, 5); + } else if (newMsg.media instanceof TLRPC.TL_messageMediaDocument && newMsg.media.document != null) { + TLRPC.Document document = newMsg.media.document; + newMsg.media.document = new TLRPC.TL_documentEncrypted(); + newMsg.media.document.id = file.id; + newMsg.media.document.access_hash = file.access_hash; + newMsg.media.document.user_id = document.user_id; + newMsg.media.document.date = document.date; + newMsg.media.document.file_name = document.file_name; + newMsg.media.document.mime_type = document.mime_type; + newMsg.media.document.size = file.size; + newMsg.media.document.key = decryptedMessage.media.key; + newMsg.media.document.iv = decryptedMessage.media.iv; + newMsg.media.document.thumb = document.thumb; + newMsg.media.document.dc_id = file.dc_id; + + if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { + File cacheFile = new File(newMsg.attachPath); + File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.document); + if (cacheFile.renameTo(cacheFile2)) { + newMsg.attachPath = ""; + } + } + + ArrayList arr = new ArrayList(); + arr.add(newMsg); + MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); + + MessagesStorage.getInstance().putSentFile(originalPath, newMsg.media.document, 4); + } else if (newMsg.media instanceof TLRPC.TL_messageMediaAudio && newMsg.media.audio != null) { + TLRPC.Audio audio = newMsg.media.audio; + newMsg.media.audio = new TLRPC.TL_audioEncrypted(); + newMsg.media.audio.id = file.id; + newMsg.media.audio.access_hash = file.access_hash; + newMsg.media.audio.user_id = audio.user_id; + newMsg.media.audio.date = audio.date; + newMsg.media.audio.duration = audio.duration; + newMsg.media.audio.size = file.size; + newMsg.media.audio.dc_id = file.dc_id; + newMsg.media.audio.key = decryptedMessage.media.key; + newMsg.media.audio.iv = decryptedMessage.media.iv; + newMsg.media.audio.mime_type = audio.mime_type; + + String fileName = audio.dc_id + "_" + audio.id + ".ogg"; + String fileName2 = newMsg.media.audio.dc_id + "_" + newMsg.media.audio.id + ".ogg"; + if (!fileName.equals(fileName2)) { + File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); + File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.audio); + if (cacheFile.renameTo(cacheFile2)) { + newMsg.attachPath = ""; + } + } + + ArrayList arr = new ArrayList(); + arr.add(newMsg); + MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); + } + } + } + + public static boolean isSecretVisibleMessage(TLRPC.Message message) { + return message.action instanceof TLRPC.TL_messageEncryptedAction && (message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL); + } + + public static boolean isSecretInvisibleMessage(TLRPC.Message message) { + return message.action instanceof TLRPC.TL_messageEncryptedAction && !(message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || message.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL); + } + + protected void performSendEncryptedRequest(final TLRPC.DecryptedMessage req, final TLRPC.Message newMsgObj, final TLRPC.EncryptedChat chat, final TLRPC.InputEncryptedFile encryptedFile, final String originalPath) { + if (req == null || chat.auth_key == null || chat instanceof TLRPC.TL_encryptedChatRequested || chat instanceof TLRPC.TL_encryptedChatWaiting) { + return; + } + Utilities.stageQueue.postRunnable(new Runnable() { + @Override + public void run() { + TLObject toEncryptObject = null; + if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 17) { + TLRPC.TL_decryptedMessageLayer layer = new TLRPC.TL_decryptedMessageLayer(); + layer.layer = AndroidUtilities.getPeerLayerVersion(chat.layer); + layer.message = req; + layer.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; + Utilities.random.nextBytes(layer.random_bytes); + toEncryptObject = layer; + + if (chat.seq_in == 0 && chat.seq_out == 0) { + if (chat.admin_id == UserConfig.getClientUserId()) { + chat.seq_out = 1; + } else { + chat.seq_in = 1; + } + } + + if (newMsgObj.seq_in == 0 && newMsgObj.seq_out == 0) { + layer.in_seq_no = chat.seq_in; + layer.out_seq_no = chat.seq_out; + chat.seq_out += 2; + if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 20) { + if (chat.key_create_date == 0) { + chat.key_create_date = ConnectionsManager.getInstance().getCurrentTime(); + } + chat.key_use_count_out++; + if ((chat.key_use_count_out >= 100 || chat.key_create_date < ConnectionsManager.getInstance().getCurrentTime() - 60 * 60 * 24 * 7) && chat.exchange_id == 0) { + requestNewSecretChatKey(chat); + } + } + MessagesStorage.getInstance().updateEncryptedChatSeq(chat); + if (newMsgObj != null) { + newMsgObj.seq_in = layer.in_seq_no; + newMsgObj.seq_out = layer.out_seq_no; + MessagesStorage.getInstance().setMessageSeq(newMsgObj.id, newMsgObj.seq_in, newMsgObj.seq_out); + } + } else { + layer.in_seq_no = newMsgObj.seq_in; + layer.out_seq_no = newMsgObj.seq_out; + } + } else { + toEncryptObject = req; + } + + int len = toEncryptObject.getObjectSize(); + ByteBufferDesc toEncrypt = BuffersStorage.getInstance().getFreeBuffer(4 + len); + toEncrypt.writeInt32(len); + toEncryptObject.serializeToStream(toEncrypt); + + byte[] messageKeyFull = Utilities.computeSHA1(toEncrypt.buffer); + byte[] messageKey = new byte[16]; + System.arraycopy(messageKeyFull, messageKeyFull.length - 16, messageKey, 0, 16); + + MessageKeyData keyData = Utilities.generateMessageKeyData(chat.auth_key, messageKey, false); + + len = toEncrypt.length(); + int extraLen = len % 16 != 0 ? 16 - len % 16 : 0; + ByteBufferDesc dataForEncryption = BuffersStorage.getInstance().getFreeBuffer(len + extraLen); + toEncrypt.position(0); + dataForEncryption.writeRaw(toEncrypt); + if (extraLen != 0) { + byte[] b = new byte[extraLen]; + Utilities.random.nextBytes(b); + dataForEncryption.writeRaw(b); + } + BuffersStorage.getInstance().reuseFreeBuffer(toEncrypt); + + Utilities.aesIgeEncryption(dataForEncryption.buffer, keyData.aesKey, keyData.aesIv, true, false, 0, dataForEncryption.limit()); + + ByteBufferDesc data = BuffersStorage.getInstance().getFreeBuffer(8 + messageKey.length + dataForEncryption.length()); + dataForEncryption.position(0); + data.writeInt64(chat.key_fingerprint); + data.writeRaw(messageKey); + data.writeRaw(dataForEncryption); + BuffersStorage.getInstance().reuseFreeBuffer(dataForEncryption); + data.position(0); + + TLObject reqToSend = null; + + if (encryptedFile == null) { + if (req instanceof TLRPC.TL_decryptedMessageService) { + TLRPC.TL_messages_sendEncryptedService req2 = new TLRPC.TL_messages_sendEncryptedService(); + req2.data = data; + req2.random_id = req.random_id; + req2.peer = new TLRPC.TL_inputEncryptedChat(); + req2.peer.chat_id = chat.id; + req2.peer.access_hash = chat.access_hash; + reqToSend = req2; + } else { + TLRPC.TL_messages_sendEncrypted req2 = new TLRPC.TL_messages_sendEncrypted(); + req2.data = data; + req2.random_id = req.random_id; + req2.peer = new TLRPC.TL_inputEncryptedChat(); + req2.peer.chat_id = chat.id; + req2.peer.access_hash = chat.access_hash; + reqToSend = req2; + } + } else { + TLRPC.TL_messages_sendEncryptedFile req2 = new TLRPC.TL_messages_sendEncryptedFile(); + req2.data = data; + req2.random_id = req.random_id; + req2.peer = new TLRPC.TL_inputEncryptedChat(); + req2.peer.chat_id = chat.id; + req2.peer.access_hash = chat.access_hash; + req2.file = encryptedFile; + reqToSend = req2; + } + ConnectionsManager.getInstance().performRpc(reqToSend, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + if (error == null) { + if (req.action instanceof TLRPC.TL_decryptedMessageActionNotifyLayer) { + TLRPC.EncryptedChat currentChat = MessagesController.getInstance().getEncryptedChat(chat.id); + sendingNotifyLayer.remove((Integer)currentChat.id); + currentChat.layer = AndroidUtilities.setMyLayerVersion(currentChat.layer, CURRENT_SECRET_CHAT_LAYER); + MessagesStorage.getInstance().updateEncryptedChatLayer(currentChat); + } + } + if (newMsgObj != null) { + if (error == null) { + final String attachPath = newMsgObj.attachPath; + final TLRPC.messages_SentEncryptedMessage res = (TLRPC.messages_SentEncryptedMessage) response; + if (isSecretVisibleMessage(newMsgObj)) { + newMsgObj.date = res.date; + } + if (res.file instanceof TLRPC.TL_encryptedFile) { + processSentMessage(newMsgObj, res.file, req, originalPath); + } + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + if (isSecretInvisibleMessage(newMsgObj)) { + res.date = 0; + } + MessagesStorage.getInstance().updateMessageStateAndId(newMsgObj.random_id, newMsgObj.id, newMsgObj.id, res.date, false); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj); + SendMessagesHelper.getInstance().processSentMessage(newMsgObj.id); + if (newMsgObj.media instanceof TLRPC.TL_messageMediaVideo) { + SendMessagesHelper.getInstance().stopVideoService(attachPath); + } + } + }); + } + }); + } else { + MessagesStorage.getInstance().markMessageAsSendError(newMsgObj.id); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.id); + SendMessagesHelper.getInstance().processSentMessage(newMsgObj.id); + if (newMsgObj.media instanceof TLRPC.TL_messageMediaVideo) { + SendMessagesHelper.getInstance().stopVideoService(newMsgObj.attachPath); + } + } + }); + } + } + } + }); + } + }); + } + + public TLRPC.Message processDecryptedObject(final TLRPC.EncryptedChat chat, final TLRPC.EncryptedFile file, int date, long random_id, TLObject object, boolean new_key_used) { + if (object != null) { + int from_id = chat.admin_id; + if (from_id == UserConfig.getClientUserId()) { + from_id = chat.participant_id; + } + + if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 20 && chat.exchange_id == 0 && chat.future_key_fingerprint == 0 && chat.key_use_count_in >= 120) { + requestNewSecretChatKey(chat); + } + + if (chat.exchange_id == 0 && chat.future_key_fingerprint != 0 && !new_key_used) { + chat.future_auth_key = new byte[256]; + chat.future_key_fingerprint = 0; + MessagesStorage.getInstance().updateEncryptedChat(chat); + } else if (chat.exchange_id != 0 && new_key_used) { + chat.key_fingerprint = chat.future_key_fingerprint; + chat.auth_key = chat.future_auth_key; + chat.key_create_date = ConnectionsManager.getInstance().getCurrentTime(); + chat.future_auth_key = new byte[256]; + chat.future_key_fingerprint = 0; + chat.key_use_count_in = 0; + chat.key_use_count_out = 0; + chat.exchange_id = 0; + + MessagesStorage.getInstance().updateEncryptedChat(chat); + } + + if (object instanceof TLRPC.TL_decryptedMessage) { + TLRPC.TL_decryptedMessage decryptedMessage = (TLRPC.TL_decryptedMessage)object; + TLRPC.TL_message newMessage = null; + if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 17) { + newMessage = new TLRPC.TL_message_secret(); + newMessage.ttl = decryptedMessage.ttl; + } else { + newMessage = new TLRPC.TL_message(); + newMessage.ttl = chat.ttl; + } + newMessage.message = decryptedMessage.message; + newMessage.date = date; + newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); + UserConfig.saveConfig(false); + newMessage.from_id = from_id; + newMessage.to_id = new TLRPC.TL_peerUser(); + newMessage.random_id = random_id; + newMessage.to_id.user_id = UserConfig.getClientUserId(); + newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; + newMessage.dialog_id = ((long)chat.id) << 32; + if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) { + newMessage.media = new TLRPC.TL_messageMediaEmpty(); + } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaContact) { + newMessage.media = new TLRPC.TL_messageMediaContact(); + newMessage.media.last_name = decryptedMessage.media.last_name; + newMessage.media.first_name = decryptedMessage.media.first_name; + newMessage.media.phone_number = decryptedMessage.media.phone_number; + newMessage.media.user_id = decryptedMessage.media.user_id; + } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaGeoPoint) { + newMessage.media = new TLRPC.TL_messageMediaGeo(); + newMessage.media.geo = new TLRPC.TL_geoPoint(); + newMessage.media.geo.lat = decryptedMessage.media.lat; + newMessage.media.geo._long = decryptedMessage.media._long; + } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaPhoto) { + if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { + return null; + } + newMessage.media = new TLRPC.TL_messageMediaPhoto(); + newMessage.media.photo = new TLRPC.TL_photo(); + newMessage.media.photo.user_id = newMessage.from_id; + newMessage.media.photo.date = newMessage.date; + newMessage.media.photo.caption = ""; + newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty(); + if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { + TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize(); + small.w = decryptedMessage.media.thumb_w; + small.h = decryptedMessage.media.thumb_h; + small.bytes = decryptedMessage.media.thumb; + small.type = "s"; + small.location = new TLRPC.TL_fileLocationUnavailable(); + newMessage.media.photo.sizes.add(small); + } + + TLRPC.TL_photoSize big = new TLRPC.TL_photoSize(); + big.w = decryptedMessage.media.w; + big.h = decryptedMessage.media.h; + big.type = "x"; + big.size = file.size; + big.location = new TLRPC.TL_fileEncryptedLocation(); + big.location.key = decryptedMessage.media.key; + big.location.iv = decryptedMessage.media.iv; + big.location.dc_id = file.dc_id; + big.location.volume_id = file.id; + big.location.secret = file.access_hash; + big.location.local_id = file.key_fingerprint; + newMessage.media.photo.sizes.add(big); + } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaVideo) { + if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { + return null; + } + newMessage.media = new TLRPC.TL_messageMediaVideo(); + newMessage.media.video = new TLRPC.TL_videoEncrypted(); + if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { + newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize(); + newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb; + newMessage.media.video.thumb.w = decryptedMessage.media.thumb_w; + newMessage.media.video.thumb.h = decryptedMessage.media.thumb_h; + newMessage.media.video.thumb.type = "s"; + newMessage.media.video.thumb.location = new TLRPC.TL_fileLocationUnavailable(); + } else { + newMessage.media.video.thumb = new TLRPC.TL_photoSizeEmpty(); + newMessage.media.video.thumb.type = "s"; + } + newMessage.media.video.duration = decryptedMessage.media.duration; + newMessage.media.video.dc_id = file.dc_id; + newMessage.media.video.w = decryptedMessage.media.w; + newMessage.media.video.h = decryptedMessage.media.h; + newMessage.media.video.date = date; + newMessage.media.video.caption = ""; + newMessage.media.video.user_id = from_id; + newMessage.media.video.size = file.size; + newMessage.media.video.id = file.id; + newMessage.media.video.access_hash = file.access_hash; + newMessage.media.video.key = decryptedMessage.media.key; + newMessage.media.video.iv = decryptedMessage.media.iv; + newMessage.media.video.mime_type = decryptedMessage.media.mime_type; + if (newMessage.ttl != 0) { + newMessage.ttl = Math.max(newMessage.media.video.duration + 1, newMessage.ttl); + } + if (newMessage.media.video.mime_type == null) { + newMessage.media.video.mime_type = "video/mp4"; + } + } else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaDocument) { + if (decryptedMessage.media.key == null || decryptedMessage.media.key.length != 32 || decryptedMessage.media.iv == null || decryptedMessage.media.iv.length != 32) { + return null; + } + newMessage.media = new TLRPC.TL_messageMediaDocument(); + newMessage.media.document = new TLRPC.TL_documentEncrypted(); + newMessage.media.document.id = file.id; + newMessage.media.document.access_hash = file.access_hash; + newMessage.media.document.user_id = decryptedMessage.media.user_id; + newMessage.media.document.date = date; + newMessage.media.document.file_name = decryptedMessage.media.file_name; + newMessage.media.document.mime_type = decryptedMessage.media.mime_type; + newMessage.media.document.size = file.size; + newMessage.media.document.key = decryptedMessage.media.key; + newMessage.media.document.iv = decryptedMessage.media.iv; + if (decryptedMessage.media.thumb.length != 0 && decryptedMessage.media.thumb.length <= 6000 && decryptedMessage.media.thumb_w <= 100 && decryptedMessage.media.thumb_h <= 100) { + newMessage.media.document.thumb = new TLRPC.TL_photoCachedSize(); + newMessage.media.document.thumb.bytes = decryptedMessage.media.thumb; + newMessage.media.document.thumb.w = decryptedMessage.media.thumb_w; + newMessage.media.document.thumb.h = decryptedMessage.media.thumb_h; + newMessage.media.document.thumb.type = "s"; + newMessage.media.document.thumb.location = new TLRPC.TL_fileLocationUnavailable(); + } else { + newMessage.media.document.thumb = new TLRPC.TL_photoSizeEmpty(); + newMessage.media.document.thumb.type = "s"; + } + newMessage.media.document.dc_id = file.dc_id; + } 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; + } + newMessage.media = new TLRPC.TL_messageMediaAudio(); + newMessage.media.audio = new TLRPC.TL_audioEncrypted(); + newMessage.media.audio.id = file.id; + newMessage.media.audio.access_hash = file.access_hash; + newMessage.media.audio.user_id = from_id; + newMessage.media.audio.date = date; + newMessage.media.audio.size = file.size; + newMessage.media.audio.key = decryptedMessage.media.key; + newMessage.media.audio.iv = decryptedMessage.media.iv; + newMessage.media.audio.dc_id = file.dc_id; + newMessage.media.audio.duration = decryptedMessage.media.duration; + newMessage.media.audio.mime_type = decryptedMessage.media.mime_type; + if (newMessage.ttl != 0) { + newMessage.ttl = Math.max(newMessage.media.audio.duration + 1, newMessage.ttl); + } + if (newMessage.media.audio.mime_type == null) { + newMessage.media.audio.mime_type = "audio/ogg"; + } + } else { + return null; + } + return newMessage; + } else if (object instanceof TLRPC.TL_decryptedMessageService) { + final TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService)object; + if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL || serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) { + TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService(); + if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { + newMessage.action = new TLRPC.TL_messageEncryptedAction(); + if (serviceMessage.action.ttl_seconds < 0 || serviceMessage.action.ttl_seconds > 60 * 60 * 24 * 365) { + serviceMessage.action.ttl_seconds = 60 * 60 * 24 * 365; + } + chat.ttl = serviceMessage.action.ttl_seconds; + newMessage.action.encryptedAction = serviceMessage.action; + MessagesStorage.getInstance().updateEncryptedChatTTL(chat); + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) { + newMessage.action = new TLRPC.TL_messageEncryptedAction(); + newMessage.action.encryptedAction = serviceMessage.action; + } + newMessage.local_id = newMessage.id = UserConfig.getNewMessageId(); + UserConfig.saveConfig(false); + newMessage.flags = TLRPC.MESSAGE_FLAG_UNREAD; + newMessage.date = date; + newMessage.from_id = from_id; + newMessage.to_id = new TLRPC.TL_peerUser(); + newMessage.to_id.user_id = UserConfig.getClientUserId(); + newMessage.dialog_id = ((long)chat.id) << 32; + return newMessage; + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionFlushHistory) { + final long did = ((long)chat.id) << 32; + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + TLRPC.TL_dialog dialog = MessagesController.getInstance().dialogs_dict.get(did); + if (dialog != null) { + dialog.unread_count = 0; + MessagesController.getInstance().dialogMessage.remove(dialog.top_message); + } + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationsController.getInstance().processReadMessages(null, did, 0, Integer.MAX_VALUE, false); + HashMap dialogsToUpdate = new HashMap(); + dialogsToUpdate.put(did, 0); + NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); + } + }); + } + }); + MessagesStorage.getInstance().deleteDialog(did, true); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.removeAllMessagesFromDialog, did); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + } + }); + return null; + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionDeleteMessages) { + if (!serviceMessage.action.random_ids.isEmpty()) { + pendingEncMessagesToDelete.addAll(serviceMessage.action.random_ids); + } + return null; + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionReadMessages) { + if (!serviceMessage.action.random_ids.isEmpty()) { + MessagesStorage.getInstance().createTaskForSecretChat(chat.id, ConnectionsManager.getInstance().getCurrentTime(), ConnectionsManager.getInstance().getCurrentTime(), 1, serviceMessage.action.random_ids); + } + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionNotifyLayer) { + int currentPeerLayer = AndroidUtilities.getPeerLayerVersion(chat.layer); + chat.layer = 0; + chat.layer = AndroidUtilities.setPeerLayerVersion(chat.layer, serviceMessage.action.layer); + MessagesStorage.getInstance().updateEncryptedChatLayer(chat); + if (currentPeerLayer < CURRENT_SECRET_CHAT_LAYER) { + sendNotifyLayerMessage(chat, null); + } + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionRequestKey) { + if (chat.exchange_id != 0) { + if (chat.exchange_id > serviceMessage.action.exchange_id) { + FileLog.e("tmessages", "we already have request key with higher exchange_id"); + return null; + } else { + sendAbortKeyMessage(chat, null, chat.exchange_id); + } + } + + byte[] salt = new byte[256]; + for (int a = 0; a < 256; a++) { + salt[a] = (byte) (Utilities.random.nextDouble() * 256); + } + + BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes); + BigInteger g_b = BigInteger.valueOf(MessagesStorage.secretG); + g_b = g_b.modPow(new BigInteger(1, salt), p); + BigInteger g_a = new BigInteger(1, serviceMessage.action.g_a); + + if (!Utilities.isGoodGaAndGb(g_a, p)) { + sendAbortKeyMessage(chat, null, serviceMessage.action.exchange_id); + return null; + } + + byte[] g_b_bytes = g_b.toByteArray(); + if (g_b_bytes.length > 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(g_b_bytes, 1, correctedAuth, 0, 256); + g_b_bytes = correctedAuth; + } + + g_a = g_a.modPow(new BigInteger(1, salt), p); + + byte[] authKey = g_a.toByteArray(); + if (authKey.length > 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(authKey, authKey.length - 256, correctedAuth, 0, 256); + authKey = correctedAuth; + } else if (authKey.length < 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length); + for (int a = 0; a < 256 - authKey.length; a++) { + authKey[a] = 0; + } + authKey = correctedAuth; + } + byte[] authKeyHash = Utilities.computeSHA1(authKey); + byte[] authKeyId = new byte[8]; + System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8); + + chat.exchange_id = serviceMessage.action.exchange_id; + chat.future_auth_key = authKey; + chat.future_key_fingerprint = Utilities.bytesToLong(authKeyId); + chat.g_a_or_b = g_b_bytes; + + MessagesStorage.getInstance().updateEncryptedChat(chat); + + sendAcceptKeyMessage(chat, null); + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionAcceptKey) { + if (chat.exchange_id == serviceMessage.action.exchange_id) { + + BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes); + BigInteger i_authKey = new BigInteger(1, serviceMessage.action.g_b); + + if (!Utilities.isGoodGaAndGb(i_authKey, p)) { + chat.future_auth_key = new byte[256]; + chat.future_key_fingerprint = 0; + chat.exchange_id = 0; + MessagesStorage.getInstance().updateEncryptedChat(chat); + + sendAbortKeyMessage(chat, null, serviceMessage.action.exchange_id); + return null; + } + + i_authKey = i_authKey.modPow(new BigInteger(1, chat.a_or_b), p); + + byte[] authKey = i_authKey.toByteArray(); + if (authKey.length > 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(authKey, authKey.length - 256, correctedAuth, 0, 256); + authKey = correctedAuth; + } else if (authKey.length < 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length); + for (int a = 0; a < 256 - authKey.length; a++) { + authKey[a] = 0; + } + authKey = correctedAuth; + } + byte[] authKeyHash = Utilities.computeSHA1(authKey); + byte[] authKeyId = new byte[8]; + System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8); + long fingerprint = Utilities.bytesToLong(authKeyId); + if (serviceMessage.action.key_fingerprint == fingerprint) { + chat.future_auth_key = authKey; + chat.future_key_fingerprint = fingerprint; + + MessagesStorage.getInstance().updateEncryptedChat(chat); + } else { + chat.future_auth_key = new byte[256]; + chat.future_key_fingerprint = 0; + chat.exchange_id = 0; + MessagesStorage.getInstance().updateEncryptedChat(chat); + sendAbortKeyMessage(chat, null, serviceMessage.action.exchange_id); + } + + sendCommitKeyMessage(chat, null); + } else { + chat.future_auth_key = new byte[256]; + chat.future_key_fingerprint = 0; + chat.exchange_id = 0; + MessagesStorage.getInstance().updateEncryptedChat(chat); + sendAbortKeyMessage(chat, null, serviceMessage.action.exchange_id); + } + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionCommitKey) { + if (chat.exchange_id == serviceMessage.action.exchange_id && chat.future_key_fingerprint == serviceMessage.action.key_fingerprint) { + long old_fingerpring = chat.key_fingerprint; + byte[] old_key = chat.auth_key; + chat.key_fingerprint = chat.future_key_fingerprint; + chat.auth_key = chat.future_auth_key; + chat.key_create_date = ConnectionsManager.getInstance().getCurrentTime(); + chat.future_auth_key = old_key; + chat.future_key_fingerprint = old_fingerpring; + chat.key_use_count_in = 0; + chat.key_use_count_out = 0; + chat.exchange_id = 0; + + MessagesStorage.getInstance().updateEncryptedChat(chat); + + sendNoopMessage(chat, null); + } else { + chat.future_auth_key = new byte[256]; + chat.future_key_fingerprint = 0; + chat.exchange_id = 0; + MessagesStorage.getInstance().updateEncryptedChat(chat); + sendAbortKeyMessage(chat, null, serviceMessage.action.exchange_id); + } + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionAbortKey) { + if (chat.exchange_id == serviceMessage.action.exchange_id) { + chat.future_auth_key = new byte[256]; + chat.future_key_fingerprint = 0; + chat.exchange_id = 0; + MessagesStorage.getInstance().updateEncryptedChat(chat); + } + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionNoop) { + //do nothing + } else if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionResend) { + + } else { + return null; + } + } else { + FileLog.e("tmessages", "unknown message " + object); + } + } else { + FileLog.e("tmessages", "unknown TLObject"); + } + return null; + } + + public void checkSecretHoles(TLRPC.EncryptedChat chat, ArrayList messages) { + ArrayList holes = secretHolesQueue.get(chat.id); + if (holes == null) { + return; + } + Collections.sort(holes, new Comparator() { + @Override + public int compare(TLRPC.TL_decryptedMessageHolder lhs, TLRPC.TL_decryptedMessageHolder rhs) { + if (lhs.layer.out_seq_no > rhs.layer.out_seq_no) { + return 1; + } else if (lhs.layer.out_seq_no < rhs.layer.out_seq_no) { + return -1; + } + return 0; + } + }); + + boolean update = false; + for (int a = 0; a < holes.size(); a++) { + TLRPC.TL_decryptedMessageHolder holder = holes.get(a); + if (holder.layer.out_seq_no == chat.seq_in || chat.seq_in == holder.layer.out_seq_no - 2) { + chat.seq_in = holder.layer.out_seq_no; + holes.remove(a); + a--; + update = true; + + TLRPC.Message message = processDecryptedObject(chat, holder.file, holder.date, holder.random_id, holder.layer.message, holder.new_key_used); + if (message != null) { + messages.add(message); + } + } else { + break; + } + } + if (holes.isEmpty()) { + secretHolesQueue.remove(chat.id); + } + if (update) { + MessagesStorage.getInstance().updateEncryptedChatSeq(chat); + } + } + + protected ArrayList decryptMessage(TLRPC.EncryptedMessage message) { + final TLRPC.EncryptedChat chat = MessagesController.getInstance().getEncryptedChatDB(message.chat_id); + if (chat == null || chat instanceof TLRPC.TL_encryptedChatDiscarded) { + return null; + } + ByteBufferDesc is = BuffersStorage.getInstance().getFreeBuffer(message.bytes.length); + is.writeRaw(message.bytes); + is.position(0); + long fingerprint = is.readInt64(); + byte[] keyToDecrypt = null; + boolean new_key_used = false; + if (chat.key_fingerprint == fingerprint) { + keyToDecrypt = chat.auth_key; + } else if (chat.future_key_fingerprint != 0 && chat.future_key_fingerprint == fingerprint) { + keyToDecrypt = chat.future_auth_key; + new_key_used = true; + } + + if (keyToDecrypt != null) { + byte[] messageKey = is.readData(16); + MessageKeyData keyData = Utilities.generateMessageKeyData(keyToDecrypt, messageKey, false); + + Utilities.aesIgeEncryption(is.buffer, keyData.aesKey, keyData.aesIv, false, false, 24, is.limit() - 24); + + int len = is.readInt32(); + TLObject object = TLClassStore.Instance().TLdeserialize(is, is.readInt32()); + BuffersStorage.getInstance().reuseFreeBuffer(is); + if (!new_key_used && AndroidUtilities.getPeerLayerVersion(chat.layer) >= 20) { + chat.key_use_count_in++; + } + if (object instanceof TLRPC.TL_decryptedMessageLayer) { + final TLRPC.TL_decryptedMessageLayer layer = (TLRPC.TL_decryptedMessageLayer)object; + if (chat.seq_in == 0 && chat.seq_out == 0) { + if (chat.admin_id == UserConfig.getClientUserId()) { + chat.seq_out = 1; + } else { + chat.seq_in = 1; + } + } + if (layer.out_seq_no < chat.seq_in) { + return null; + } + if (chat.seq_in != layer.out_seq_no && chat.seq_in != layer.out_seq_no - 2) { + ArrayList arr = secretHolesQueue.get(chat.id); + if (arr == null) { + arr = new ArrayList(); + secretHolesQueue.put(chat.id, arr); + } + if (arr.size() >= 10) { + secretHolesQueue.remove(chat.id); + 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; + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + MessagesController.getInstance().putEncryptedChat(newChat, false); + MessagesStorage.getInstance().updateEncryptedChat(newChat); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); + } + }); + declineSecretChat(chat.id); + return null; + } + + TLRPC.TL_decryptedMessageHolder holder = new TLRPC.TL_decryptedMessageHolder(); + holder.layer = layer; + holder.file = message.file; + holder.random_id = message.random_id; + holder.date = message.date; + holder.new_key_used = new_key_used; + arr.add(holder); + return null; + } + chat.seq_in = layer.out_seq_no; + MessagesStorage.getInstance().updateEncryptedChatSeq(chat); + object = layer.message; + } + ArrayList messages = new ArrayList(); + TLRPC.Message decryptedMessage = processDecryptedObject(chat, message.file, message.date, message.random_id, object, new_key_used); + if (decryptedMessage != null) { + messages.add(decryptedMessage); + } + checkSecretHoles(chat, messages); + return messages; + } else { + BuffersStorage.getInstance().reuseFreeBuffer(is); + FileLog.e("tmessages", "fingerprint mismatch " + fingerprint); + } + return null; + } + + public void requestNewSecretChatKey(final TLRPC.EncryptedChat encryptedChat) { + if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) < 20) { + return; + } + final byte[] salt = new byte[256]; + for (int a = 0; a < 256; a++) { + salt[a] = (byte) (Utilities.random.nextDouble() * 256); + } + + BigInteger i_g_a = BigInteger.valueOf(MessagesStorage.secretG); + i_g_a = i_g_a.modPow(new BigInteger(1, salt), new BigInteger(1, MessagesStorage.secretPBytes)); + byte[] g_a = i_g_a.toByteArray(); + if (g_a.length > 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(g_a, 1, correctedAuth, 0, 256); + g_a = correctedAuth; + } + + encryptedChat.exchange_id = SendMessagesHelper.getInstance().getNextRandomId(); + encryptedChat.a_or_b = salt; + encryptedChat.g_a = g_a; + + MessagesStorage.getInstance().updateEncryptedChat(encryptedChat); + + sendRequestKeyMessage(encryptedChat, null); + } + + public void processAcceptedSecretChat(final TLRPC.EncryptedChat encryptedChat) { + BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes); + BigInteger i_authKey = new BigInteger(1, encryptedChat.g_a_or_b); + + if (!Utilities.isGoodGaAndGb(i_authKey, p)) { + declineSecretChat(encryptedChat.id); + return; + } + + i_authKey = i_authKey.modPow(new BigInteger(1, encryptedChat.a_or_b), p); + + byte[] authKey = i_authKey.toByteArray(); + if (authKey.length > 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(authKey, authKey.length - 256, correctedAuth, 0, 256); + authKey = correctedAuth; + } else if (authKey.length < 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length); + for (int a = 0; a < 256 - authKey.length; a++) { + authKey[a] = 0; + } + authKey = correctedAuth; + } + byte[] authKeyHash = Utilities.computeSHA1(authKey); + byte[] authKeyId = new byte[8]; + System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8); + long fingerprint = Utilities.bytesToLong(authKeyId); + if (encryptedChat.key_fingerprint == fingerprint) { + encryptedChat.auth_key = authKey; + encryptedChat.key_create_date = ConnectionsManager.getInstance().getCurrentTime(); + encryptedChat.seq_in = 0; + encryptedChat.seq_out = 1; + MessagesStorage.getInstance().updateEncryptedChat(encryptedChat); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + MessagesController.getInstance().putEncryptedChat(encryptedChat, false); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, encryptedChat); + sendNotifyLayerMessage(encryptedChat, null); + } + }); + } else { + final TLRPC.TL_encryptedChatDiscarded newChat = new TLRPC.TL_encryptedChatDiscarded(); + newChat.id = encryptedChat.id; + newChat.user_id = encryptedChat.user_id; + newChat.auth_key = encryptedChat.auth_key; + newChat.key_create_date = encryptedChat.key_create_date; + newChat.key_use_count_in = encryptedChat.key_use_count_in; + newChat.key_use_count_out = encryptedChat.key_use_count_out; + newChat.seq_in = encryptedChat.seq_in; + newChat.seq_out = encryptedChat.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(encryptedChat.id); + } + } + + public void declineSecretChat(int chat_id) { + TLRPC.TL_messages_discardEncryption req = new TLRPC.TL_messages_discardEncryption(); + req.chat_id = chat_id; + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + + } + }); + } + + public void acceptSecretChat(final TLRPC.EncryptedChat encryptedChat) { + if (acceptingChats.get(encryptedChat.id) != null) { + return; + } + acceptingChats.put(encryptedChat.id, encryptedChat); + TLRPC.TL_messages_getDhConfig req = new TLRPC.TL_messages_getDhConfig(); + req.random_length = 256; + req.version = MessagesStorage.lastSecretVersion; + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + if (error == null) { + TLRPC.messages_DhConfig res = (TLRPC.messages_DhConfig) response; + if (response instanceof TLRPC.TL_messages_dhConfig) { + if (!Utilities.isGoodPrime(res.p, res.g)) { + acceptingChats.remove(encryptedChat.id); + declineSecretChat(encryptedChat.id); + return; + } + + MessagesStorage.secretPBytes = res.p; + MessagesStorage.secretG = res.g; + MessagesStorage.lastSecretVersion = res.version; + MessagesStorage.getInstance().saveSecretParams(MessagesStorage.lastSecretVersion, MessagesStorage.secretG, MessagesStorage.secretPBytes); + } + byte[] salt = new byte[256]; + for (int a = 0; a < 256; a++) { + salt[a] = (byte) ((byte) (Utilities.random.nextDouble() * 256) ^ res.random[a]); + } + encryptedChat.a_or_b = salt; + encryptedChat.seq_in = 1; + encryptedChat.seq_out = 0; + BigInteger p = new BigInteger(1, MessagesStorage.secretPBytes); + BigInteger g_b = BigInteger.valueOf(MessagesStorage.secretG); + g_b = g_b.modPow(new BigInteger(1, salt), p); + BigInteger g_a = new BigInteger(1, encryptedChat.g_a); + + if (!Utilities.isGoodGaAndGb(g_a, p)) { + acceptingChats.remove(encryptedChat.id); + declineSecretChat(encryptedChat.id); + return; + } + + byte[] g_b_bytes = g_b.toByteArray(); + if (g_b_bytes.length > 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(g_b_bytes, 1, correctedAuth, 0, 256); + g_b_bytes = correctedAuth; + } + + g_a = g_a.modPow(new BigInteger(1, salt), p); + + byte[] authKey = g_a.toByteArray(); + if (authKey.length > 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(authKey, authKey.length - 256, correctedAuth, 0, 256); + authKey = correctedAuth; + } else if (authKey.length < 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length); + for (int a = 0; a < 256 - authKey.length; a++) { + authKey[a] = 0; + } + authKey = correctedAuth; + } + byte[] authKeyHash = Utilities.computeSHA1(authKey); + byte[] authKeyId = new byte[8]; + System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8); + encryptedChat.auth_key = authKey; + encryptedChat.key_create_date = ConnectionsManager.getInstance().getCurrentTime(); + + TLRPC.TL_messages_acceptEncryption req2 = new TLRPC.TL_messages_acceptEncryption(); + req2.g_b = g_b_bytes; + req2.peer = new TLRPC.TL_inputEncryptedChat(); + req2.peer.chat_id = encryptedChat.id; + req2.peer.access_hash = encryptedChat.access_hash; + req2.key_fingerprint = Utilities.bytesToLong(authKeyId); + ConnectionsManager.getInstance().performRpc(req2, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + acceptingChats.remove(encryptedChat.id); + if (error == null) { + final TLRPC.EncryptedChat newChat = (TLRPC.EncryptedChat) response; + newChat.auth_key = encryptedChat.auth_key; + newChat.user_id = encryptedChat.user_id; + newChat.seq_in = encryptedChat.seq_in; + newChat.seq_out = encryptedChat.seq_out; + newChat.key_create_date = encryptedChat.key_create_date; + newChat.key_use_count_in = encryptedChat.key_use_count_in; + newChat.key_use_count_out = encryptedChat.key_use_count_out; + MessagesStorage.getInstance().updateEncryptedChat(newChat); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + MessagesController.getInstance().putEncryptedChat(newChat, false); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatUpdated, newChat); + sendNotifyLayerMessage(newChat, null); + } + }); + } + } + }); + } else { + acceptingChats.remove(encryptedChat.id); + } + } + }); + } + + public void startSecretChat(final Context context, final TLRPC.User user) { + if (user == null) { + return; + } + startingSecretChat = true; + final ProgressDialog progressDialog = new ProgressDialog(context); + progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.setCancelable(false); + TLRPC.TL_messages_getDhConfig req = new TLRPC.TL_messages_getDhConfig(); + req.random_length = 256; + req.version = MessagesStorage.lastSecretVersion; + final long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + if (error == null) { + TLRPC.messages_DhConfig res = (TLRPC.messages_DhConfig) response; + if (response instanceof TLRPC.TL_messages_dhConfig) { + if (!Utilities.isGoodPrime(res.p, res.g)) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + if (!((Activity) context).isFinishing()) { + progressDialog.dismiss(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + return; + } + MessagesStorage.secretPBytes = res.p; + MessagesStorage.secretG = res.g; + MessagesStorage.lastSecretVersion = res.version; + MessagesStorage.getInstance().saveSecretParams(MessagesStorage.lastSecretVersion, MessagesStorage.secretG, MessagesStorage.secretPBytes); + } + final byte[] salt = new byte[256]; + for (int a = 0; a < 256; a++) { + salt[a] = (byte) ((byte) (Utilities.random.nextDouble() * 256) ^ res.random[a]); + } + + BigInteger i_g_a = BigInteger.valueOf(MessagesStorage.secretG); + i_g_a = i_g_a.modPow(new BigInteger(1, salt), new BigInteger(1, MessagesStorage.secretPBytes)); + byte[] g_a = i_g_a.toByteArray(); + if (g_a.length > 256) { + byte[] correctedAuth = new byte[256]; + System.arraycopy(g_a, 1, correctedAuth, 0, 256); + g_a = correctedAuth; + } + + TLRPC.TL_messages_requestEncryption req2 = new TLRPC.TL_messages_requestEncryption(); + req2.g_a = g_a; + req2.user_id = MessagesController.getInputUser(user); + req2.random_id = Utilities.random.nextInt(); + ConnectionsManager.getInstance().performRpc(req2, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(final TLObject response, TLRPC.TL_error error) { + if (error == null) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + startingSecretChat = false; + if (!((Activity) context).isFinishing()) { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) response; + chat.user_id = chat.participant_id; + chat.seq_in = 0; + chat.seq_out = 1; + chat.a_or_b = salt; + MessagesController.getInstance().putEncryptedChat(chat, false); + TLRPC.TL_dialog dialog = new TLRPC.TL_dialog(); + dialog.id = ((long) chat.id) << 32; + dialog.unread_count = 0; + dialog.top_message = 0; + dialog.last_message_date = ConnectionsManager.getInstance().getCurrentTime(); + MessagesController.getInstance().dialogs_dict.put(dialog.id, dialog); + MessagesController.getInstance().dialogs.add(dialog); + Collections.sort(MessagesController.getInstance().dialogs, new Comparator() { + @Override + public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) { + if (tl_dialog.last_message_date == tl_dialog2.last_message_date) { + return 0; + } else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) { + return 1; + } else { + return -1; + } + } + }); + MessagesStorage.getInstance().putEncryptedChat(chat, user, dialog); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.encryptedChatCreated, chat); + Utilities.stageQueue.postRunnable(new Runnable() { + @Override + public void run() { + if (!delayedEncryptedChatUpdates.isEmpty()) { + MessagesController.getInstance().processUpdateArray(delayedEncryptedChatUpdates, null, null); + delayedEncryptedChatUpdates.clear(); + } + } + }); + } + }); + } else { + delayedEncryptedChatUpdates.clear(); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (!((Activity) context).isFinishing()) { + startingSecretChat = false; + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("CreateEncryptedChatError", R.string.CreateEncryptedChatError)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + builder.show().setCanceledOnTouchOutside(true); + } + } + }); + } + } + }, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors); + } else { + delayedEncryptedChatUpdates.clear(); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + startingSecretChat = false; + if (!((Activity) context).isFinishing()) { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } + }); + } + } + }, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors); + progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ConnectionsManager.getInstance().cancelRpc(reqId, true); + try { + dialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + progressDialog.show(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java index 8b9f37d8..e5771710 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java @@ -18,19 +18,16 @@ import android.provider.MediaStore; import android.webkit.MimeTypeMap; import android.widget.Toast; -import org.telegram.messenger.BuffersStorage; -import org.telegram.messenger.ByteBufferDesc; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.MessageKeyData; import org.telegram.messenger.R; import org.telegram.messenger.RPCRequest; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import java.io.File; import java.util.ArrayList; @@ -38,12 +35,9 @@ import java.util.HashMap; public class SendMessagesHelper implements NotificationCenter.NotificationCenterDelegate { - public static final int CURRENT_SECRET_CHAT_LAYER = 17; - private TLRPC.ChatParticipants currentChatInfo = null; private HashMap> delayedMessages = new HashMap>(); private HashMap unsentMessages = new HashMap(); - private ArrayList sendingNotifyLayer = new ArrayList(); private class DelayedMessage { public TLObject sendRequest; @@ -82,7 +76,6 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter public void cleanUp() { delayedMessages.clear(); - sendingNotifyLayer.clear(); unsentMessages.clear(); currentChatInfo = null; } @@ -149,7 +142,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } else if (encryptedFile != null && message.sendEncryptedRequest != null) { message.sendEncryptedRequest.media.key = encryptedFile.key; message.sendEncryptedRequest.media.iv = encryptedFile.iv; - performSendEncryptedRequest(message.sendEncryptedRequest, message.obj.messageOwner, message.encryptedChat, encryptedFile, message.originalPath); + SecretChatHelper.getInstance().performSendEncryptedRequest(message.sendEncryptedRequest, message.obj.messageOwner, message.encryptedChat, encryptedFile, message.originalPath); arr.remove(a); a--; } @@ -301,17 +294,17 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter return false; } if (messageObject.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { - sendTTLMessage(encryptedChat, messageObject.messageOwner); + SecretChatHelper.getInstance().sendTTLMessage(encryptedChat, messageObject.messageOwner); } else if (messageObject.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionDeleteMessages) { - sendMessagesDeleteMessage(encryptedChat, null, messageObject.messageOwner); + SecretChatHelper.getInstance().sendMessagesDeleteMessage(encryptedChat, null, messageObject.messageOwner); } else if (messageObject.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionFlushHistory) { - sendClearHistoryMessage(encryptedChat, messageObject.messageOwner); + SecretChatHelper.getInstance().sendClearHistoryMessage(encryptedChat, messageObject.messageOwner); } else if (messageObject.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionNotifyLayer) { - sendNotifyLayerMessage(encryptedChat, messageObject.messageOwner); + SecretChatHelper.getInstance().sendNotifyLayerMessage(encryptedChat, messageObject.messageOwner); } else if (messageObject.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionReadMessages) { - sendMessagesReadMessage(encryptedChat, null, messageObject.messageOwner); + SecretChatHelper.getInstance().sendMessagesReadMessage(encryptedChat, null, messageObject.messageOwner); } else if (messageObject.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages) { - sendScreenshotMessage(encryptedChat, null, messageObject.messageOwner); + SecretChatHelper.getInstance().sendScreenshotMessage(encryptedChat, null, messageObject.messageOwner); } else if (messageObject.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionTyping) { } else if (messageObject.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionResend) { @@ -326,7 +319,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter return true; } - public void processSentMessage(int id) { + protected void processSentMessage(int id) { int prevSize = unsentMessages.size(); unsentMessages.remove(id); if (prevSize != 0 && unsentMessages.size() == 0) { @@ -677,7 +670,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter reqSend.random_id = newMsg.random_id; reqSend.message = message; reqSend.media = new TLRPC.TL_decryptedMessageMediaEmpty(); - performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null); + SecretChatHelper.getInstance().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null); } } else if (type >= 1 && type <= 3 || type >= 5 && type <= 8) { if (encryptedChat == null) { @@ -838,7 +831,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter reqSend.media = new TLRPC.TL_decryptedMessageMediaGeoPoint(); reqSend.media.lat = lat; reqSend.media._long = lon; - performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null); + SecretChatHelper.getInstance().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null); } else if (type == 2) { TLRPC.PhotoSize small = photo.sizes.get(0); TLRPC.PhotoSize big = photo.sizes.get(photo.sizes.size() - 1); @@ -864,7 +857,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter encryptedFile.access_hash = big.location.secret; reqSend.media.key = big.location.key; reqSend.media.iv = big.location.iv; - performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, encryptedFile, null); + SecretChatHelper.getInstance().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, encryptedFile, null); } } else if (type == 3) { if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { @@ -895,7 +888,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter encryptedFile.access_hash = video.access_hash; reqSend.media.key = video.key; reqSend.media.iv = video.iv; - performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, encryptedFile, null); + SecretChatHelper.getInstance().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, encryptedFile, null); } } else if (type == 6) { reqSend.media = new TLRPC.TL_decryptedMessageMediaContact(); @@ -903,7 +896,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter reqSend.media.first_name = user.first_name; reqSend.media.last_name = user.last_name; reqSend.media.user_id = user.id; - performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null); + SecretChatHelper.getInstance().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, null, null); } else if (type == 7) { reqSend.media = new TLRPC.TL_decryptedMessageMediaDocument(); reqSend.media.size = document.size; @@ -933,7 +926,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter encryptedFile.access_hash = document.access_hash; reqSend.media.key = document.key; reqSend.media.iv = document.iv; - performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, encryptedFile, null); + SecretChatHelper.getInstance().performSendEncryptedRequest(reqSend, newMsgObj.messageOwner, encryptedChat, encryptedFile, null); } } else if (type == 8) { if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { @@ -1065,7 +1058,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } - private void stopVideoService(final String path) { + protected void stopVideoService(final String path) { MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { @Override public void run() { @@ -1098,7 +1091,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage) response; sentMessages.add(res.message); newMsgObj.id = res.message.id; - processSentMessage(newMsgObj, res.message, null, null, originalPath); + processSentMessage(newMsgObj, res.message, originalPath); MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.message.date); } else if (response instanceof TLRPC.messages_StatedMessages) { TLRPC.messages_StatedMessages res = (TLRPC.messages_StatedMessages) response; @@ -1108,7 +1101,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (!isBroadcast) { newMsgObj.id = message.id; } - processSentMessage(newMsgObj, message, null, null, originalPath); + processSentMessage(newMsgObj, message, originalPath); } MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, -1); } @@ -1175,621 +1168,125 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter }), true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassCanCompress, ConnectionsManager.DEFAULT_DATACENTER_ID); } - private void performSendEncryptedRequest(final TLRPC.DecryptedMessage req, final TLRPC.Message newMsgObj, final TLRPC.EncryptedChat chat, final TLRPC.InputEncryptedFile encryptedFile, final String originalPath) { - if (req == null || chat.auth_key == null || chat instanceof TLRPC.TL_encryptedChatRequested || chat instanceof TLRPC.TL_encryptedChatWaiting) { + private void processSentMessage(TLRPC.Message newMsg, TLRPC.Message sentMessage, String originalPath) { + if (sentMessage == null) { return; } - Utilities.stageQueue.postRunnable(new Runnable() { - @Override - public void run() { - TLObject toEncryptObject = null; - if (AndroidUtilities.getPeerLayerVersion(chat.layer) >= 17) { - TLRPC.TL_decryptedMessageLayer layer = new TLRPC.TL_decryptedMessageLayer(); - layer.layer = CURRENT_SECRET_CHAT_LAYER; - layer.message = req; - layer.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; - Utilities.random.nextBytes(layer.random_bytes); - toEncryptObject = layer; + if (sentMessage.media instanceof TLRPC.TL_messageMediaPhoto && sentMessage.media.photo != null && newMsg.media instanceof TLRPC.TL_messageMediaPhoto && newMsg.media.photo != null) { + MessagesStorage.getInstance().putSentFile(originalPath, sentMessage.media.photo, 0); - if (chat.seq_in == 0 && chat.seq_out == 0) { - if (chat.admin_id == UserConfig.getClientUserId()) { - chat.seq_out = 1; - } else { - chat.seq_in = 1; - } - } - - if (newMsgObj.seq_in == 0 && newMsgObj.seq_out == 0) { - layer.in_seq_no = chat.seq_in; - layer.out_seq_no = chat.seq_out; - chat.seq_out += 2; - MessagesStorage.getInstance().updateEncryptedChatSeq(chat); - if (newMsgObj != null) { - newMsgObj.seq_in = layer.in_seq_no; - newMsgObj.seq_out = layer.out_seq_no; - MessagesStorage.getInstance().setMessageSeq(newMsgObj.id, newMsgObj.seq_in, newMsgObj.seq_out); - } - } else { - layer.in_seq_no = newMsgObj.seq_in; - layer.out_seq_no = newMsgObj.seq_out; - } - } else { - toEncryptObject = req; + for (TLRPC.PhotoSize size : sentMessage.media.photo.sizes) { + if (size instanceof TLRPC.TL_photoSizeEmpty) { + continue; } - - int len = toEncryptObject.getObjectSize(); - ByteBufferDesc toEncrypt = BuffersStorage.getInstance().getFreeBuffer(4 + len); - toEncrypt.writeInt32(len); - toEncryptObject.serializeToStream(toEncrypt); - - byte[] messageKeyFull = Utilities.computeSHA1(toEncrypt.buffer); - byte[] messageKey = new byte[16]; - System.arraycopy(messageKeyFull, messageKeyFull.length - 16, messageKey, 0, 16); - - MessageKeyData keyData = Utilities.generateMessageKeyData(chat.auth_key, messageKey, false); - - len = toEncrypt.length(); - int extraLen = len % 16 != 0 ? 16 - len % 16 : 0; - ByteBufferDesc dataForEncryption = BuffersStorage.getInstance().getFreeBuffer(len + extraLen); - toEncrypt.position(0); - dataForEncryption.writeRaw(toEncrypt); - if (extraLen != 0) { - byte[] b = new byte[extraLen]; - Utilities.random.nextBytes(b); - dataForEncryption.writeRaw(b); - } - BuffersStorage.getInstance().reuseFreeBuffer(toEncrypt); - - Utilities.aesIgeEncryption(dataForEncryption.buffer, keyData.aesKey, keyData.aesIv, true, false, 0, dataForEncryption.limit()); - - ByteBufferDesc data = BuffersStorage.getInstance().getFreeBuffer(8 + messageKey.length + dataForEncryption.length()); - dataForEncryption.position(0); - data.writeInt64(chat.key_fingerprint); - data.writeRaw(messageKey); - data.writeRaw(dataForEncryption); - BuffersStorage.getInstance().reuseFreeBuffer(dataForEncryption); - data.position(0); - - TLObject reqToSend = null; - - if (encryptedFile == null) { - if (req instanceof TLRPC.TL_decryptedMessageService) { - TLRPC.TL_messages_sendEncryptedService req2 = new TLRPC.TL_messages_sendEncryptedService(); - req2.data = data; - req2.random_id = req.random_id; - req2.peer = new TLRPC.TL_inputEncryptedChat(); - req2.peer.chat_id = chat.id; - req2.peer.access_hash = chat.access_hash; - reqToSend = req2; - } else { - TLRPC.TL_messages_sendEncrypted req2 = new TLRPC.TL_messages_sendEncrypted(); - req2.data = data; - req2.random_id = req.random_id; - req2.peer = new TLRPC.TL_inputEncryptedChat(); - req2.peer.chat_id = chat.id; - req2.peer.access_hash = chat.access_hash; - reqToSend = req2; - } - } else { - TLRPC.TL_messages_sendEncryptedFile req2 = new TLRPC.TL_messages_sendEncryptedFile(); - req2.data = data; - req2.random_id = req.random_id; - req2.peer = new TLRPC.TL_inputEncryptedChat(); - req2.peer.chat_id = chat.id; - req2.peer.access_hash = chat.access_hash; - req2.file = encryptedFile; - reqToSend = req2; - } - ConnectionsManager.getInstance().performRpc(reqToSend, new RPCRequest.RPCRequestDelegate() { - @Override - public void run(TLObject response, TLRPC.TL_error error) { - if (error == null) { - if (req.action instanceof TLRPC.TL_decryptedMessageActionNotifyLayer) { - TLRPC.EncryptedChat currentChat = MessagesController.getInstance().getEncryptedChat(chat.id); - sendingNotifyLayer.remove((Integer)currentChat.id); - currentChat.layer = AndroidUtilities.setMyLayerVersion(currentChat.layer, CURRENT_SECRET_CHAT_LAYER); - MessagesStorage.getInstance().updateEncryptedChatLayer(currentChat); - } - } - if (newMsgObj != null) { - if (error == null) { - final String attachPath = newMsgObj.attachPath; - final TLRPC.messages_SentEncryptedMessage res = (TLRPC.messages_SentEncryptedMessage) response; - if (newMsgObj.action instanceof TLRPC.TL_messageEncryptedAction) { - if (newMsgObj.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || newMsgObj.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { - newMsgObj.date = res.date; - } - } - if (res.file instanceof TLRPC.TL_encryptedFile) { - processSentMessage(newMsgObj, null, res.file, req, originalPath); - } - MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { - @Override - public void run() { - if (newMsgObj.action instanceof TLRPC.TL_messageEncryptedAction) { - if (!(newMsgObj.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || newMsgObj.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL)) { - res.date = 0; - } - } - MessagesStorage.getInstance().updateMessageStateAndId(newMsgObj.random_id, newMsgObj.id, newMsgObj.id, res.date, false); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj); - processSentMessage(newMsgObj.id); - if (newMsgObj.media instanceof TLRPC.TL_messageMediaVideo) { - stopVideoService(attachPath); - } - } - }); - } - }); - } else { - MessagesStorage.getInstance().markMessageAsSendError(newMsgObj.id); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.id); - processSentMessage(newMsgObj.id); - if (newMsgObj.media instanceof TLRPC.TL_messageMediaVideo) { - stopVideoService(newMsgObj.attachPath); - } - } - }); - } - } - } - }); - } - }); - } - - private void processSentMessage(TLRPC.Message newMsg, TLRPC.Message sentMessage, TLRPC.EncryptedFile file, TLRPC.DecryptedMessage decryptedMessage, String originalPath) { - if (sentMessage != null) { - if (sentMessage.media instanceof TLRPC.TL_messageMediaPhoto && sentMessage.media.photo != null && newMsg.media instanceof TLRPC.TL_messageMediaPhoto && newMsg.media.photo != null) { - MessagesStorage.getInstance().putSentFile(originalPath, sentMessage.media.photo, 0); - - for (TLRPC.PhotoSize size : sentMessage.media.photo.sizes) { - if (size instanceof TLRPC.TL_photoSizeEmpty) { - continue; - } - for (TLRPC.PhotoSize size2 : newMsg.media.photo.sizes) { - if (size.type.equals(size2.type)) { - String fileName = size2.location.volume_id + "_" + size2.location.local_id; - String fileName2 = size.location.volume_id + "_" + size.location.local_id; - if (fileName.equals(fileName2)) { - break; - } - File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); - File cacheFile2 = null; - if (sentMessage.media.photo.sizes.size() == 1 || size.w > 80 || size.h > 80) { - cacheFile2 = FileLoader.getPathToAttach(size); - } else { - cacheFile2 = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); - } - cacheFile.renameTo(cacheFile2); - ImageLoader.getInstance().replaceImageInCache(fileName, fileName2); - size2.location = size.location; + for (TLRPC.PhotoSize size2 : newMsg.media.photo.sizes) { + if (size.type.equals(size2.type)) { + String fileName = size2.location.volume_id + "_" + size2.location.local_id; + String fileName2 = size.location.volume_id + "_" + size.location.local_id; + if (fileName.equals(fileName2)) { break; } - } - } - sentMessage.message = newMsg.message; - sentMessage.attachPath = newMsg.attachPath; - newMsg.media.photo.id = sentMessage.media.photo.id; - newMsg.media.photo.access_hash = sentMessage.media.photo.access_hash; - } else if (sentMessage.media instanceof TLRPC.TL_messageMediaVideo && sentMessage.media.video != null && newMsg.media instanceof TLRPC.TL_messageMediaVideo && newMsg.media.video != null) { - MessagesStorage.getInstance().putSentFile(originalPath, sentMessage.media.video, 2); - - TLRPC.PhotoSize size2 = newMsg.media.video.thumb; - TLRPC.PhotoSize size = sentMessage.media.video.thumb; - if (size2.location != 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)) { File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); - File cacheFile2 = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); + File cacheFile2 = null; + if (sentMessage.media.photo.sizes.size() == 1 || size.w > 80 || size.h > 80) { + cacheFile2 = FileLoader.getPathToAttach(size); + } else { + cacheFile2 = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); + } cacheFile.renameTo(cacheFile2); ImageLoader.getInstance().replaceImageInCache(fileName, fileName2); size2.location = size.location; + break; } } + } + sentMessage.message = newMsg.message; + sentMessage.attachPath = newMsg.attachPath; + newMsg.media.photo.id = sentMessage.media.photo.id; + newMsg.media.photo.access_hash = sentMessage.media.photo.access_hash; + } else if (sentMessage.media instanceof TLRPC.TL_messageMediaVideo && sentMessage.media.video != null && newMsg.media instanceof TLRPC.TL_messageMediaVideo && newMsg.media.video != null) { + MessagesStorage.getInstance().putSentFile(originalPath, sentMessage.media.video, 2); - sentMessage.message = newMsg.message; - newMsg.media.video.dc_id = sentMessage.media.video.dc_id; - newMsg.media.video.id = sentMessage.media.video.id; - newMsg.media.video.access_hash = sentMessage.media.video.access_hash; + TLRPC.PhotoSize size2 = newMsg.media.video.thumb; + TLRPC.PhotoSize size = sentMessage.media.video.thumb; + if (size2.location != 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)) { + File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); + File cacheFile2 = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); + cacheFile.renameTo(cacheFile2); + ImageLoader.getInstance().replaceImageInCache(fileName, fileName2); + size2.location = size.location; + } + } - if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { - File cacheFile = new File(newMsg.attachPath); - File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.video); - if (!cacheFile.renameTo(cacheFile2)) { - sentMessage.attachPath = newMsg.attachPath; - } - } else { + sentMessage.message = newMsg.message; + newMsg.media.video.dc_id = sentMessage.media.video.dc_id; + newMsg.media.video.id = sentMessage.media.video.id; + newMsg.media.video.access_hash = sentMessage.media.video.access_hash; + + if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { + File cacheFile = new File(newMsg.attachPath); + File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.video); + if (!cacheFile.renameTo(cacheFile2)) { sentMessage.attachPath = newMsg.attachPath; } - } else if (sentMessage.media instanceof TLRPC.TL_messageMediaDocument && sentMessage.media.document != null && newMsg.media instanceof TLRPC.TL_messageMediaDocument && newMsg.media.document != null) { - MessagesStorage.getInstance().putSentFile(originalPath, sentMessage.media.document, 1); + } else { + sentMessage.attachPath = newMsg.attachPath; + } + } else if (sentMessage.media instanceof TLRPC.TL_messageMediaDocument && sentMessage.media.document != null && newMsg.media instanceof TLRPC.TL_messageMediaDocument && newMsg.media.document != null) { + MessagesStorage.getInstance().putSentFile(originalPath, sentMessage.media.document, 1); - TLRPC.PhotoSize size2 = newMsg.media.document.thumb; - TLRPC.PhotoSize size = sentMessage.media.document.thumb; - if (size2.location != 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)) { - File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); - File cacheFile2 = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); - cacheFile.renameTo(cacheFile2); - ImageLoader.getInstance().replaceImageInCache(fileName, fileName2); - size2.location = size.location; - } + TLRPC.PhotoSize size2 = newMsg.media.document.thumb; + TLRPC.PhotoSize size = sentMessage.media.document.thumb; + if (size2.location != 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)) { + File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); + File cacheFile2 = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); + cacheFile.renameTo(cacheFile2); + ImageLoader.getInstance().replaceImageInCache(fileName, fileName2); + size2.location = size.location; } + } - newMsg.media.document.dc_id = sentMessage.media.document.dc_id; - newMsg.media.document.id = sentMessage.media.document.id; - newMsg.media.document.access_hash = sentMessage.media.document.access_hash; + newMsg.media.document.dc_id = sentMessage.media.document.dc_id; + newMsg.media.document.id = sentMessage.media.document.id; + newMsg.media.document.access_hash = sentMessage.media.document.access_hash; - if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { - File cacheFile = new File(newMsg.attachPath); - File cacheFile2 = FileLoader.getPathToAttach(sentMessage.media.document); - if (!cacheFile.renameTo(cacheFile2)) { - sentMessage.attachPath = newMsg.attachPath; - sentMessage.message = newMsg.message; - } else { - newMsg.attachPath = ""; - } - } else { + if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { + File cacheFile = new File(newMsg.attachPath); + File cacheFile2 = FileLoader.getPathToAttach(sentMessage.media.document); + if (!cacheFile.renameTo(cacheFile2)) { sentMessage.attachPath = newMsg.attachPath; sentMessage.message = newMsg.message; + } else { + newMsg.attachPath = ""; } - } else if (sentMessage.media instanceof TLRPC.TL_messageMediaAudio && sentMessage.media.audio != null && newMsg.media instanceof TLRPC.TL_messageMediaAudio && newMsg.media.audio != null) { + } else { + sentMessage.attachPath = newMsg.attachPath; sentMessage.message = newMsg.message; + } + } else if (sentMessage.media instanceof TLRPC.TL_messageMediaAudio && sentMessage.media.audio != null && newMsg.media instanceof TLRPC.TL_messageMediaAudio && newMsg.media.audio != null) { + sentMessage.message = newMsg.message; - String fileName = newMsg.media.audio.dc_id + "_" + newMsg.media.audio.id + ".ogg"; - newMsg.media.audio.dc_id = sentMessage.media.audio.dc_id; - newMsg.media.audio.id = sentMessage.media.audio.id; - newMsg.media.audio.access_hash = sentMessage.media.audio.access_hash; - String fileName2 = sentMessage.media.audio.dc_id + "_" + sentMessage.media.audio.id + ".ogg"; - if (!fileName.equals(fileName2)) { - File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); - File cacheFile2 = FileLoader.getPathToAttach(sentMessage.media.audio); - if (!cacheFile.renameTo(cacheFile2)) { - sentMessage.attachPath = newMsg.attachPath; - } + String fileName = newMsg.media.audio.dc_id + "_" + newMsg.media.audio.id + ".ogg"; + newMsg.media.audio.dc_id = sentMessage.media.audio.dc_id; + newMsg.media.audio.id = sentMessage.media.audio.id; + newMsg.media.audio.access_hash = sentMessage.media.audio.access_hash; + String fileName2 = sentMessage.media.audio.dc_id + "_" + sentMessage.media.audio.id + ".ogg"; + if (!fileName.equals(fileName2)) { + File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); + File cacheFile2 = FileLoader.getPathToAttach(sentMessage.media.audio); + if (!cacheFile.renameTo(cacheFile2)) { + sentMessage.attachPath = newMsg.attachPath; } } - } else if (file != null) { - if (newMsg.media instanceof TLRPC.TL_messageMediaPhoto && newMsg.media.photo != null) { - TLRPC.PhotoSize size = newMsg.media.photo.sizes.get(newMsg.media.photo.sizes.size() - 1); - String fileName = size.location.volume_id + "_" + size.location.local_id; - size.location = new TLRPC.TL_fileEncryptedLocation(); - size.location.key = decryptedMessage.media.key; - size.location.iv = decryptedMessage.media.iv; - size.location.dc_id = file.dc_id; - size.location.volume_id = file.id; - size.location.secret = file.access_hash; - size.location.local_id = file.key_fingerprint; - String fileName2 = size.location.volume_id + "_" + size.location.local_id; - File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); - File cacheFile2 = FileLoader.getPathToAttach(size); - cacheFile.renameTo(cacheFile2); - ImageLoader.getInstance().replaceImageInCache(fileName, fileName2); - ArrayList arr = new ArrayList(); - arr.add(newMsg); - MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); - - MessagesStorage.getInstance().putSentFile(originalPath, newMsg.media.photo, 3); - } else if (newMsg.media instanceof TLRPC.TL_messageMediaVideo && newMsg.media.video != null) { - TLRPC.Video video = newMsg.media.video; - newMsg.media.video = new TLRPC.TL_videoEncrypted(); - newMsg.media.video.duration = video.duration; - newMsg.media.video.thumb = video.thumb; - newMsg.media.video.dc_id = file.dc_id; - newMsg.media.video.w = video.w; - newMsg.media.video.h = video.h; - newMsg.media.video.date = video.date; - newMsg.media.video.caption = ""; - newMsg.media.video.user_id = video.user_id; - newMsg.media.video.size = file.size; - newMsg.media.video.id = file.id; - newMsg.media.video.access_hash = file.access_hash; - newMsg.media.video.key = decryptedMessage.media.key; - newMsg.media.video.iv = decryptedMessage.media.iv; - newMsg.media.video.mime_type = video.mime_type; - - if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { - File cacheFile = new File(newMsg.attachPath); - File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.video); - if (cacheFile.renameTo(cacheFile2)) { - newMsg.attachPath = ""; - } - } - - ArrayList arr = new ArrayList(); - arr.add(newMsg); - MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); - - MessagesStorage.getInstance().putSentFile(originalPath, newMsg.media.video, 5); - } else if (newMsg.media instanceof TLRPC.TL_messageMediaDocument && newMsg.media.document != null) { - TLRPC.Document document = newMsg.media.document; - newMsg.media.document = new TLRPC.TL_documentEncrypted(); - newMsg.media.document.id = file.id; - newMsg.media.document.access_hash = file.access_hash; - newMsg.media.document.user_id = document.user_id; - newMsg.media.document.date = document.date; - newMsg.media.document.file_name = document.file_name; - newMsg.media.document.mime_type = document.mime_type; - newMsg.media.document.size = file.size; - newMsg.media.document.key = decryptedMessage.media.key; - newMsg.media.document.iv = decryptedMessage.media.iv; - newMsg.media.document.thumb = document.thumb; - newMsg.media.document.dc_id = file.dc_id; - - if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { - File cacheFile = new File(newMsg.attachPath); - File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.document); - if (cacheFile.renameTo(cacheFile2)) { - newMsg.attachPath = ""; - } - } - - ArrayList arr = new ArrayList(); - arr.add(newMsg); - MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); - - MessagesStorage.getInstance().putSentFile(originalPath, newMsg.media.document, 4); - } else if (newMsg.media instanceof TLRPC.TL_messageMediaAudio && newMsg.media.audio != null) { - TLRPC.Audio audio = newMsg.media.audio; - newMsg.media.audio = new TLRPC.TL_audioEncrypted(); - newMsg.media.audio.id = file.id; - newMsg.media.audio.access_hash = file.access_hash; - newMsg.media.audio.user_id = audio.user_id; - newMsg.media.audio.date = audio.date; - newMsg.media.audio.duration = audio.duration; - newMsg.media.audio.size = file.size; - newMsg.media.audio.dc_id = file.dc_id; - newMsg.media.audio.key = decryptedMessage.media.key; - newMsg.media.audio.iv = decryptedMessage.media.iv; - newMsg.media.audio.mime_type = audio.mime_type; - - String fileName = audio.dc_id + "_" + audio.id + ".ogg"; - String fileName2 = newMsg.media.audio.dc_id + "_" + newMsg.media.audio.id + ".ogg"; - if (!fileName.equals(fileName2)) { - File cacheFile = new File(FileLoader.getInstance().getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); - File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.audio); - if (cacheFile.renameTo(cacheFile2)) { - newMsg.attachPath = ""; - } - } - - ArrayList arr = new ArrayList(); - arr.add(newMsg); - MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); - } } } - private TLRPC.TL_messageService createServiceSecretMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.DecryptedMessageAction decryptedMessage) { - TLRPC.TL_messageService newMsg = new TLRPC.TL_messageService(); - - newMsg.action = new TLRPC.TL_messageEncryptedAction(); - newMsg.action.encryptedAction = decryptedMessage; - newMsg.local_id = newMsg.id = UserConfig.getNewMessageId(); - newMsg.from_id = UserConfig.getClientUserId(); - newMsg.flags = TLRPC.MESSAGE_FLAG_UNREAD | TLRPC.MESSAGE_FLAG_OUT; - newMsg.dialog_id = ((long)encryptedChat.id) << 32; - newMsg.to_id = new TLRPC.TL_peerUser(); - newMsg.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; - if (encryptedChat.participant_id == UserConfig.getClientUserId()) { - newMsg.to_id.user_id = encryptedChat.admin_id; - } else { - newMsg.to_id.user_id = encryptedChat.participant_id; - } - if (decryptedMessage instanceof TLRPC.TL_decryptedMessageActionScreenshotMessages || decryptedMessage instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) { - newMsg.date = ConnectionsManager.getInstance().getCurrentTime(); - } else { - newMsg.date = 0; - } - newMsg.random_id = getNextRandomId(); - UserConfig.saveConfig(false); - - ArrayList arr = new ArrayList(); - arr.add(newMsg); - MessagesStorage.getInstance().putMessages(arr, false, true, true, 0); - - return newMsg; - } - - public void sendMessagesReadMessage(TLRPC.EncryptedChat encryptedChat, ArrayList random_ids, TLRPC.Message resendMessage) { - if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { - return; - } - TLRPC.TL_decryptedMessageService reqSend = null; - if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - reqSend = new TLRPC.TL_decryptedMessageService(); - } else { - reqSend = new TLRPC.TL_decryptedMessageService_old(); - reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; - Utilities.random.nextBytes(reqSend.random_bytes); - } - - TLRPC.Message message = null; - - if (resendMessage != null) { - message = resendMessage; - reqSend.action = message.action.encryptedAction; - } else { - reqSend.action = new TLRPC.TL_decryptedMessageActionReadMessages(); - reqSend.action.random_ids = random_ids; - message = createServiceSecretMessage(encryptedChat, reqSend.action); - } - reqSend.random_id = message.random_id; - - performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); - } - - public void sendMessagesDeleteMessage(TLRPC.EncryptedChat encryptedChat, ArrayList random_ids, TLRPC.Message resendMessage) { - if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { - return; - } - TLRPC.TL_decryptedMessageService reqSend = null; - if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - reqSend = new TLRPC.TL_decryptedMessageService(); - } else { - reqSend = new TLRPC.TL_decryptedMessageService_old(); - reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; - Utilities.random.nextBytes(reqSend.random_bytes); - } - - TLRPC.Message message = null; - - if (resendMessage != null) { - message = resendMessage; - reqSend.action = message.action.encryptedAction; - } else { - reqSend.action = new TLRPC.TL_decryptedMessageActionDeleteMessages(); - reqSend.action.random_ids = random_ids; - message = createServiceSecretMessage(encryptedChat, reqSend.action); - } - reqSend.random_id = message.random_id; - - performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); - } - - public void sendClearHistoryMessage(TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { - if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { - return; - } - TLRPC.TL_decryptedMessageService reqSend = null; - if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - reqSend = new TLRPC.TL_decryptedMessageService(); - } else { - reqSend = new TLRPC.TL_decryptedMessageService_old(); - reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; - Utilities.random.nextBytes(reqSend.random_bytes); - } - - TLRPC.Message message = null; - - if (resendMessage != null) { - message = resendMessage; - reqSend.action = message.action.encryptedAction; - } else { - reqSend.action = new TLRPC.TL_decryptedMessageActionFlushHistory(); - message = createServiceSecretMessage(encryptedChat, reqSend.action); - } - reqSend.random_id = message.random_id; - - performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); - } - - public void sendNotifyLayerMessage(final TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { - if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { - return; - } - if (sendingNotifyLayer.contains(encryptedChat.id)) { - return; - } - sendingNotifyLayer.add(encryptedChat.id); - TLRPC.TL_decryptedMessageService reqSend = null; - if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - reqSend = new TLRPC.TL_decryptedMessageService(); - } else { - reqSend = new TLRPC.TL_decryptedMessageService_old(); - reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; - Utilities.random.nextBytes(reqSend.random_bytes); - } - - TLRPC.Message message = null; - - if (resendMessage != null) { - message = resendMessage; - reqSend.action = message.action.encryptedAction; - } else { - reqSend.action = new TLRPC.TL_decryptedMessageActionNotifyLayer(); - reqSend.action.layer = CURRENT_SECRET_CHAT_LAYER; - message = createServiceSecretMessage(encryptedChat, reqSend.action); - } - reqSend.random_id = message.random_id; - - performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); - } - - public void sendTTLMessage(TLRPC.EncryptedChat encryptedChat, TLRPC.Message resendMessage) { - if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { - return; - } - - TLRPC.TL_decryptedMessageService reqSend = null; - if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - reqSend = new TLRPC.TL_decryptedMessageService(); - } else { - reqSend = new TLRPC.TL_decryptedMessageService_old(); - reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; - Utilities.random.nextBytes(reqSend.random_bytes); - } - - TLRPC.Message message = null; - - if (resendMessage != null) { - message = resendMessage; - reqSend.action = message.action.encryptedAction; - } else { - reqSend.action = new TLRPC.TL_decryptedMessageActionSetMessageTTL(); - reqSend.action.ttl_seconds = encryptedChat.ttl; - message = createServiceSecretMessage(encryptedChat, reqSend.action); - - MessageObject newMsgObj = new MessageObject(message, null); - newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; - ArrayList objArr = new ArrayList(); - objArr.add(newMsgObj); - MessagesController.getInstance().updateInterfaceWithMessages(message.dialog_id, objArr); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - } - reqSend.random_id = message.random_id; - - performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); - } - - public void sendScreenshotMessage(TLRPC.EncryptedChat encryptedChat, ArrayList random_ids, TLRPC.Message resendMessage) { - if (!(encryptedChat instanceof TLRPC.TL_encryptedChat)) { - return; - } - - TLRPC.TL_decryptedMessageService reqSend = null; - if (AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { - reqSend = new TLRPC.TL_decryptedMessageService(); - } else { - reqSend = new TLRPC.TL_decryptedMessageService_old(); - reqSend.random_bytes = new byte[Math.max(1, (int) Math.ceil(Utilities.random.nextDouble() * 16))]; - Utilities.random.nextBytes(reqSend.random_bytes); - } - - TLRPC.Message message = null; - - if (resendMessage != null) { - message = resendMessage; - reqSend.action = message.action.encryptedAction; - } else { - reqSend.action = new TLRPC.TL_decryptedMessageActionScreenshotMessages(); - reqSend.action.random_ids = random_ids; - message = createServiceSecretMessage(encryptedChat, reqSend.action); - - MessageObject newMsgObj = new MessageObject(message, null); - newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; - ArrayList objArr = new ArrayList(); - objArr.add(newMsgObj); - MessagesController.getInstance().updateInterfaceWithMessages(message.dialog_id, objArr); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - } - reqSend.random_id = message.random_id; - - performSendEncryptedRequest(reqSend, message, encryptedChat, null, null); - } - private void putToDelayedMessages(String location, DelayedMessage message) { ArrayList arrayList = delayedMessages.get(location); if (arrayList == null) { @@ -1799,7 +1296,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter arrayList.add(message); } - private long getNextRandomId() { + protected long getNextRandomId() { long val = 0; while (val == 0) { val = Utilities.random.nextLong(); diff --git a/TMessagesProj/src/main/java/org/telegram/android/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/android/VideoEncodingService.java index e057c682..734fbf20 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/android/VideoEncodingService.java @@ -16,7 +16,7 @@ import android.support.v4.app.NotificationManagerCompat; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; public class VideoEncodingService extends Service implements NotificationCenter.NotificationCenterDelegate { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java similarity index 97% rename from TMessagesProj/src/main/java/org/telegram/ui/ApplicationLoader.java rename to TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 54cc2472..b788712c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui; +package org.telegram.messenger; import android.app.AlarmManager; import android.app.Application; @@ -34,15 +34,10 @@ import org.telegram.android.ContactsController; import org.telegram.android.MediaController; import org.telegram.android.NotificationsService; import org.telegram.android.SendMessagesHelper; -import org.telegram.messenger.BuildVars; -import org.telegram.messenger.ConnectionsManager; -import org.telegram.messenger.FileLog; import org.telegram.android.LocaleController; import org.telegram.android.MessagesController; import org.telegram.android.NativeLoader; import org.telegram.android.ScreenReceiver; -import org.telegram.messenger.UserConfig; -import org.telegram.messenger.Utilities; import java.util.concurrent.atomic.AtomicInteger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java index dc720179..ed620901 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java @@ -21,7 +21,6 @@ import org.telegram.android.ContactsController; import org.telegram.android.LocaleController; import org.telegram.android.MessagesController; import org.telegram.android.NotificationCenter; -import org.telegram.ui.ApplicationLoader; import java.io.File; import java.util.ArrayList; @@ -418,7 +417,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. pushSessionId = Utilities.random.nextLong(); } if (currentDatacenterId == 0) { - currentDatacenterId = 1; + currentDatacenterId = 2; } saveSession(); } @@ -432,12 +431,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. if (isTestBackend == 0) { Datacenter datacenter = new Datacenter(); datacenter.datacenterId = 1; - datacenter.addAddressAndPort("173.240.5.1", 443); + datacenter.addAddressAndPort("149.154.175.50", 443); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 2; - datacenter.addAddressAndPort("149.154.167.50", 443); + datacenter.addAddressAndPort("149.154.167.51", 443); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); @@ -447,7 +446,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. datacenter = new Datacenter(); datacenter.datacenterId = 4; - datacenter.addAddressAndPort("149.154.167.90", 443); + datacenter.addAddressAndPort("149.154.167.91", 443); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); @@ -473,7 +472,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. } else if (datacenters.size() == 1) { Datacenter datacenter = new Datacenter(); datacenter.datacenterId = 2; - datacenter.addAddressAndPort("149.154.167.50", 443); + datacenter.addAddressAndPort("149.154.167.51", 443); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); @@ -483,12 +482,12 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. datacenter = new Datacenter(); datacenter.datacenterId = 4; - datacenter.addAddressAndPort("31.210.235.12", 443); + datacenter.addAddressAndPort("149.154.167.91", 443); datacenters.put(datacenter.datacenterId, datacenter); datacenter = new Datacenter(); datacenter.datacenterId = 5; - datacenter.addAddressAndPort("116.51.22.2", 443); + datacenter.addAddressAndPort("149.154.171.5", 443); datacenters.put(datacenter.datacenterId, datacenter); } } @@ -1113,13 +1112,13 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. request.retryCount++; - if ((request.flags & RPCRequest.RPCRequestClassDownloadMedia) != 0) { + if (!request.salt && (request.flags & RPCRequest.RPCRequestClassDownloadMedia) != 0) { int retryMax = 10; if ((request.flags & RPCRequest.RPCRequestClassForceDownload) == 0) { if (request.wait) { retryMax = 1; } else { - retryMax = 3; + retryMax = 6; } } if (request.retryCount >= retryMax) { @@ -2244,6 +2243,8 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. } if (request.respondsToMessageId(resultMid)) { request.retryCount = 0; + request.salt = true; + break; } } } @@ -2568,7 +2569,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. if (message == null) { FileLog.e("tmessages", "***** Error parsing message: " + constructor); } else { - FileLog.e("tmessages", "received object " + message); + FileLog.d("tmessages", "received object " + message); processMessage(message, messageId, messageSeqNo, messageServerSalt, connection, 0, 0); connection.addProcessedMessageId(messageId); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Datacenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/Datacenter.java index 4c191412..36823ed7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Datacenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Datacenter.java @@ -11,8 +11,6 @@ package org.telegram.messenger; import android.content.Context; import android.content.SharedPreferences; -import org.telegram.ui.ApplicationLoader; - import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index 6ac2cbc9..ceee714f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -12,7 +12,6 @@ import android.net.Uri; import android.util.Log; import org.telegram.android.time.FastDateFormat; -import org.telegram.ui.ApplicationLoader; import java.io.File; import java.io.FileOutputStream; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index 96e6c7d6..157103be 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -11,8 +11,6 @@ package org.telegram.messenger; import android.app.Activity; import android.content.SharedPreferences; -import org.telegram.ui.ApplicationLoader; - import java.io.File; import java.io.FileInputStream; import java.math.BigInteger; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/RPCRequest.java b/TMessagesProj/src/main/java/org/telegram/messenger/RPCRequest.java index 84fa468c..4e7454e0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/RPCRequest.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/RPCRequest.java @@ -37,6 +37,7 @@ public class RPCRequest { int serverFailureCount; int flags; boolean wait = false; + boolean salt = false; protected int retryCount = 0; protected int lastResendTime = 0; protected boolean completed = false; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java index 9a5bfdc6..0247b881 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java @@ -359,6 +359,13 @@ public class TLClassStore { classStore.put(TLRPC.TL_inputPhotoCrop.constructor, TLRPC.TL_inputPhotoCrop.class); classStore.put(TLRPC.TL_messages_dialogs.constructor, TLRPC.TL_messages_dialogs.class); classStore.put(TLRPC.TL_messages_dialogsSlice.constructor, TLRPC.TL_messages_dialogsSlice.class); + classStore.put(TLRPC.TL_account_sentChangePhoneCode.constructor, TLRPC.TL_account_sentChangePhoneCode.class); + classStore.put(TLRPC.TL_updateUserPhone.constructor, TLRPC.TL_updateUserPhone.class); + classStore.put(TLRPC.TL_decryptedMessageActionRequestKey.constructor, TLRPC.TL_decryptedMessageActionRequestKey.class); + classStore.put(TLRPC.TL_decryptedMessageActionAcceptKey.constructor, TLRPC.TL_decryptedMessageActionAcceptKey.class); + classStore.put(TLRPC.TL_decryptedMessageActionCommitKey.constructor, TLRPC.TL_decryptedMessageActionCommitKey.class); + classStore.put(TLRPC.TL_decryptedMessageActionAbortKey.constructor, TLRPC.TL_decryptedMessageActionAbortKey.class); + classStore.put(TLRPC.TL_decryptedMessageActionNoop.constructor, TLRPC.TL_decryptedMessageActionNoop.class); classStore.put(TLRPC.TL_msg_container.constructor, TLRPC.TL_msg_container.class); classStore.put(TLRPC.TL_fileEncryptedLocation.constructor, TLRPC.TL_fileEncryptedLocation.class); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java index b00dd153..21310e0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java @@ -3675,6 +3675,7 @@ public class TLRPC { public long random_id; public ArrayList dc_options = new ArrayList(); public ChatParticipants participants; + public String phone; public TL_privacyKeyStatusTimestamp key; public ArrayList rules = new ArrayList(); public EncryptedChat chat; @@ -4009,6 +4010,22 @@ public class TLRPC { } } + public static class TL_updateUserPhone extends Update { + public static int constructor = 0x12b9417b; + + + public void readParams(AbsSerializedData stream) { + user_id = stream.readInt32(); + phone = stream.readString(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(user_id); + stream.writeString(phone); + } + } + public static class TL_updatePrivacy extends Update { public static int constructor = 0xee3b272a; @@ -4329,10 +4346,14 @@ public class TLRPC { public static class DecryptedMessageAction extends TLObject { public int start_seq_no; public int end_seq_no; - public int layer; public int ttl_seconds; + public int layer; public ArrayList random_ids = new ArrayList(); + public long exchange_id; + public long key_fingerprint; + public byte[] g_b; public SendMessageAction action; + public byte[] g_a; } public static class TL_decryptedMessageActionSetMessageTTL extends DecryptedMessageAction { @@ -4356,6 +4377,24 @@ public class TLRPC { } } + public static class TL_decryptedMessageActionAcceptKey extends DecryptedMessageAction { + public static int constructor = 0x6fe1735b; + + + public void readParams(AbsSerializedData stream) { + exchange_id = stream.readInt64(); + g_b = stream.readByteArray(); + key_fingerprint = stream.readInt64(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(exchange_id); + stream.writeByteArray(g_b); + stream.writeInt64(key_fingerprint); + } + } + public static class TL_decryptedMessageActionResend extends DecryptedMessageAction { public static int constructor = 0x511110b0; @@ -4409,6 +4448,22 @@ public class TLRPC { } } + public static class TL_decryptedMessageActionRequestKey extends DecryptedMessageAction { + public static int constructor = 0xf3c9611b; + + + public void readParams(AbsSerializedData stream) { + exchange_id = stream.readInt64(); + g_a = stream.readByteArray(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(exchange_id); + stream.writeByteArray(g_a); + } + } + public static class TL_decryptedMessageActionTyping extends DecryptedMessageAction { public static int constructor = 0xccb27641; @@ -5019,6 +5074,69 @@ public class TLRPC { } } + public static class TL_contacts_resolveUsername extends TLObject { + public static int constructor = 0xbf0131c; + + public String username; + + public Class responseClass () { + return User.class; + } + + public void readParams(AbsSerializedData stream) { + username = stream.readString(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(username); + } + } + + public static class TL_account_sendChangePhoneCode extends TLObject { + public static int constructor = 0xa407a8f4; + + public String phone_number; + + public Class responseClass () { + return TL_account_sentChangePhoneCode.class; + } + + public void readParams(AbsSerializedData stream) { + phone_number = stream.readString(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(phone_number); + } + } + + public static class TL_account_changePhone extends TLObject { + public static int constructor = 0x70c32edb; + + public String phone_number; + public String phone_code_hash; + public String phone_code; + + public Class responseClass () { + return User.class; + } + + public void readParams(AbsSerializedData stream) { + phone_number = stream.readString(); + phone_code_hash = stream.readString(); + phone_code = stream.readString(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(phone_number); + stream.writeString(phone_code_hash); + stream.writeString(phone_code); + } + } + public static class InputAudio extends TLObject { public long id; public long access_hash; @@ -5900,6 +6018,24 @@ public class TLRPC { } } + public static class TL_account_sentChangePhoneCode extends TLObject { + public static int constructor = 0xa4f58c4c; + + public String phone_code_hash; + public int send_call_timeout; + + public void readParams(AbsSerializedData stream) { + phone_code_hash = stream.readString(); + send_call_timeout = stream.readInt32(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(phone_code_hash); + stream.writeInt32(send_call_timeout); + } + } + public static class InputFile extends TLObject { public long id; public int parts; @@ -8819,6 +8955,7 @@ public class TLRPC { public int date; public TL_decryptedMessageLayer layer; public EncryptedFile file; + public boolean new_key_used; public void readParams(AbsSerializedData stream) { random_id = stream.readInt64(); @@ -8827,6 +8964,7 @@ public class TLRPC { if (stream.readBool()) { file = (EncryptedFile) TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); } + new_key_used = stream.readBool(); } public void serializeToStream(AbsSerializedData stream) { @@ -8838,6 +8976,7 @@ public class TLRPC { if (file != null) { file.serializeToStream(stream); } + stream.writeBool(new_key_used); } } @@ -9990,6 +10129,13 @@ public class TLRPC { public int layer; public int seq_in; public int seq_out; + public byte[] key_hash; + public short key_use_count_in; + public short key_use_count_out; + public long exchange_id; + public int key_create_date; + public long future_key_fingerprint; + public byte[] future_auth_key; } public static class FileLocation extends TLObject { @@ -10290,7 +10436,7 @@ public class TLRPC { public static class invokeWithLayer extends TLObject { public static int constructor = 0xda9b0d0d; - public int layer = 19; + public int layer = 20; public TLObject query; public void serializeToStream(AbsSerializedData stream) { @@ -10406,6 +10552,45 @@ public class TLRPC { } } + public static class TL_decryptedMessageActionCommitKey extends DecryptedMessageAction { + public static int constructor = 0xec2e0b9b; + + + public void readParams(AbsSerializedData stream) { + exchange_id = stream.readInt64(); + key_fingerprint = stream.readInt64(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(exchange_id); + stream.writeInt64(key_fingerprint); + } + } + + public static class TL_decryptedMessageActionAbortKey extends DecryptedMessageAction { + public static int constructor = 0xdd05ec6b; + + + public void readParams(AbsSerializedData stream) { + exchange_id = stream.readInt64(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(exchange_id); + } + } + + public static class TL_decryptedMessageActionNoop extends DecryptedMessageAction { + public static int constructor = 0xa82fdd63; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_decryptedMessageActionScreenshotMessages extends DecryptedMessageAction { public static int constructor = 0x8ac1f475; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index f27723f5..6ec36580 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -13,7 +13,6 @@ import android.content.SharedPreferences; import android.util.Base64; import org.telegram.android.MessagesStorage; -import org.telegram.ui.ApplicationLoader; import java.io.File; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index 9eedf862..f7e44667 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -28,8 +28,6 @@ import net.hockeyapp.android.CrashManager; import net.hockeyapp.android.CrashManagerListener; import net.hockeyapp.android.UpdateManager; -import org.telegram.ui.ApplicationLoader; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; 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 f417a566..fc29f1ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -55,6 +55,7 @@ public class ActionBarMenuItem extends ImageView { private Runnable showMenuRunnable; private boolean showFromBottom; private int menuHeight = AndroidUtilities.dp(16); + private boolean needOffset = Build.VERSION.SDK_INT >= 21; public ActionBarMenuItem(Context context, ActionBarMenu menu, int background) { super(context); @@ -135,6 +136,10 @@ public class ActionBarMenuItem extends ImageView { showFromBottom = value; } + public void setNeedOffset(boolean value) { + needOffset = Build.VERSION.SDK_INT >= 21 && value; + } + public TextView addSubItem(int id, String text, int icon) { if (popupLayout == null) { rect = new Rect(); @@ -247,29 +252,33 @@ public class ActionBarMenuItem extends ImageView { popupWindow.setFocusable(true); if (popupLayout.getMeasuredWidth() == 0) { if (showFromBottom) { - popupWindow.showAsDropDown(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth() + AndroidUtilities.dp(14), getBottomOffsetY()); - popupWindow.update(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth() + AndroidUtilities.dp(14), getBottomOffsetY(), -1, -1); + popupWindow.showAsDropDown(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth() + AndroidUtilities.dp(14), getOffsetY()); + popupWindow.update(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth() + AndroidUtilities.dp(14), getOffsetY(), -1, -1); } else { - popupWindow.showAsDropDown(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), -getMeasuredHeight()); - popupWindow.update(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), -getMeasuredHeight(), -1, -1); + popupWindow.showAsDropDown(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY()); + popupWindow.update(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY(), -1, -1); } } else { if (showFromBottom) { - popupWindow.showAsDropDown(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth() + AndroidUtilities.dp(14), getBottomOffsetY()); + popupWindow.showAsDropDown(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth() + AndroidUtilities.dp(14), getOffsetY()); } else { - popupWindow.showAsDropDown(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), -getMeasuredHeight()); + popupWindow.showAsDropDown(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY()); } } } - private int getBottomOffsetY() { - getLocationOnScreen(location); - int diff = location[1] - AndroidUtilities.statusBarHeight + getMeasuredHeight() - menuHeight; - int y = AndroidUtilities.dp(8) - menuHeight; - if (diff < 0) { - y -= diff; + private int getOffsetY() { + if (showFromBottom) { + getLocationOnScreen(location); + int diff = location[1] - AndroidUtilities.statusBarHeight + getMeasuredHeight() - menuHeight; + int y = AndroidUtilities.dp(8) - menuHeight; + if (diff < 0) { + y -= diff; + } + return y - (needOffset ? AndroidUtilities.statusBarHeight : 0); + } else { + return -getMeasuredHeight() - (needOffset ? AndroidUtilities.statusBarHeight : 0); } - return y; } public boolean toggleSearch() { @@ -415,9 +424,9 @@ public class ActionBarMenuItem extends ImageView { super.onLayout(changed, left, top, right, bottom); if (popupWindow != null && popupWindow.isShowing()) { if (showFromBottom) { - popupWindow.update(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth() + AndroidUtilities.dp(14), getBottomOffsetY(), -1, -1); + popupWindow.update(this, -popupLayout.getMeasuredWidth() + getMeasuredWidth() + AndroidUtilities.dp(14), getOffsetY(), -1, -1); } else { - popupWindow.update(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), -getMeasuredHeight(), -1, -1); + popupWindow.update(this, parentMenu.parentActionBar.getMeasuredWidth() - popupLayout.getMeasuredWidth() - getLeft() - parentMenu.getLeft(), getOffsetY(), -1, -1); } } } 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 c6f960c0..e67c9c64 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -11,10 +11,12 @@ package org.telegram.ui.ActionBar; import android.content.Context; +import android.os.Build; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.View; import android.view.ViewTreeObserver; +import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.PopupWindow; @@ -23,6 +25,7 @@ import org.telegram.messenger.FileLog; import java.lang.reflect.Field; public class ActionBarPopupWindow extends PopupWindow { + private static final Field superListenerField; static { Field f = null; @@ -132,6 +135,15 @@ public class ActionBarPopupWindow extends PopupWindow { mSuperScrollListener = null; } } + if (Build.VERSION.SDK_INT >= 21) { + try { + Field field = PopupWindow.class.getDeclaredField("mWindowLayoutType"); + field.setAccessible(true); + field.set(this, WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + } catch (Exception e) { + /* ignored */ + } + } } private void unregisterListener() { 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 e14b1025..1c607dd5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java @@ -34,7 +34,7 @@ public class DrawerLayoutContainer extends FrameLayout { private static final int MIN_DRAWER_MARGIN = 64; - private View drawerLayout; + private ViewGroup drawerLayout; private ActionBarLayout parentActionBarLayout; private boolean maybeStartTracking = false; @@ -55,7 +55,7 @@ public class DrawerLayoutContainer extends FrameLayout { private Drawable shadowLeft; private boolean allowOpenDrawer; - private int drawerPosition = 0; + private float drawerPosition = 0; private boolean drawerOpened = false; public DrawerLayoutContainer(Context context) { @@ -125,7 +125,7 @@ public class DrawerLayoutContainer extends FrameLayout { requestLayout(); } - public void setDrawerLayout(View layout) { + public void setDrawerLayout(ViewGroup layout) { drawerLayout = layout; addView(drawerLayout); if (Build.VERSION.SDK_INT >= 21) { @@ -133,11 +133,11 @@ public class DrawerLayoutContainer extends FrameLayout { } } - public void moveDrawerByX(int dx) { + public void moveDrawerByX(float dx) { setDrawerPosition(drawerPosition + dx); } - public void setDrawerPosition(int value) { + public void setDrawerPosition(float value) { drawerPosition = value; if (drawerPosition > drawerLayout.getMeasuredWidth()) { drawerPosition = drawerLayout.getMeasuredWidth(); @@ -150,10 +150,10 @@ public class DrawerLayoutContainer extends FrameLayout { if (drawerLayout.getVisibility() != newVisibility) { drawerLayout.setVisibility(newVisibility); } - setScrimOpacity((float)drawerPosition / (float)drawerLayout.getMeasuredWidth()); + setScrimOpacity(drawerPosition / (float)drawerLayout.getMeasuredWidth()); } - public int getDrawerPosition() { + public float getDrawerPosition() { return drawerPosition; } @@ -171,7 +171,7 @@ public class DrawerLayoutContainer extends FrameLayout { cancelCurrentAnimation(); AnimatorSetProxy animatorSet = new AnimatorSetProxy(); animatorSet.playTogether( - ObjectAnimatorProxy.ofInt(this, "drawerPosition", drawerLayout.getMeasuredWidth()) + ObjectAnimatorProxy.ofFloat(this, "drawerPosition", drawerLayout.getMeasuredWidth()) ); animatorSet.setInterpolator(new DecelerateInterpolator()); if (fast) { @@ -198,7 +198,7 @@ public class DrawerLayoutContainer extends FrameLayout { cancelCurrentAnimation(); AnimatorSetProxy animatorSet = new AnimatorSetProxy(); animatorSet.playTogether( - ObjectAnimatorProxy.ofInt(this, "drawerPosition", 0) + ObjectAnimatorProxy.ofFloat(this, "drawerPosition", 0) ); animatorSet.setInterpolator(new DecelerateInterpolator()); if (fast) { @@ -291,12 +291,13 @@ public class DrawerLayoutContainer extends FrameLayout { if (velocityTracker == null) { velocityTracker = VelocityTracker.obtain(); } - int dx = (int) (ev.getX() - startedTrackingX); - int dy = Math.abs((int) ev.getY() - startedTrackingY); + float dx = (int) (ev.getX() - startedTrackingX); + float dy = Math.abs((int) ev.getY() - startedTrackingY); velocityTracker.addMovement(ev); - if (maybeStartTracking && !startedTracking && Math.abs(dx) / 3 > Math.abs(dy) && (dx < 0 || dx > 0 && dx > AndroidUtilities.dp(10))) { + if (maybeStartTracking && !startedTracking && (dx > 0 && dx / 3.0f > Math.abs(dy) || dx < 0 && Math.abs(dx) >= Math.abs(dy) && Math.abs(dx) >= AndroidUtilities.dp(10))) { prepareForDrawerOpen(ev); startedTrackingX = (int) ev.getX(); + requestDisallowInterceptTouchEvent(true); } else if (startedTracking) { if (!beginTrackingSent) { if (((Activity)getContext()).getCurrentFocus() != null) { @@ -312,10 +313,10 @@ public class DrawerLayoutContainer extends FrameLayout { velocityTracker = VelocityTracker.obtain(); } velocityTracker.computeCurrentVelocity(1000); - if (!startedTracking) { + /*if (!startedTracking) { float velX = velocityTracker.getXVelocity(); float velY = velocityTracker.getYVelocity(); - if (Math.abs(velX) >= 1500 && Math.abs(velX) > Math.abs(velY)) { + if (Math.abs(velX) >= 3500 && Math.abs(velX) > Math.abs(velY)) { prepareForDrawerOpen(ev); if (!beginTrackingSent) { if (((Activity)getContext()).getCurrentFocus() != null) { @@ -324,15 +325,15 @@ public class DrawerLayoutContainer extends FrameLayout { beginTrackingSent = true; } } - } + }*/ if (startedTracking || drawerPosition != 0 && drawerPosition != drawerLayout.getMeasuredWidth()) { float velX = velocityTracker.getXVelocity(); float velY = velocityTracker.getYVelocity(); - boolean backAnimation = drawerPosition < drawerLayout.getMeasuredWidth() / 2.0f && (velX < 1500 || Math.abs(velX) < Math.abs(velY)) || velX < 0 && Math.abs(velX) >= 1500; + boolean backAnimation = drawerPosition < drawerLayout.getMeasuredWidth() / 2.0f && (velX < 3500 || Math.abs(velX) < Math.abs(velY)) || velX < 0 && Math.abs(velX) >= 3500; if (!backAnimation) { - openDrawer(!drawerOpened && Math.abs(velX) >= 1500); + openDrawer(!drawerOpened && Math.abs(velX) >= 3500); } else { - closeDrawer(drawerOpened && Math.abs(velX) >= 1500); + closeDrawer(drawerOpened && Math.abs(velX) >= 3500); } startedTracking = false; } else { @@ -357,7 +358,9 @@ public class DrawerLayoutContainer extends FrameLayout { @Override public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { - onTouchEvent(null); + if (maybeStartTracking && !startedTracking) { + onTouchEvent(null); + } super.requestDisallowInterceptTouchEvent(disallowIntercept); } @@ -378,7 +381,7 @@ public class DrawerLayoutContainer extends FrameLayout { if (drawerLayout != child) { child.layout(lp.leftMargin, lp.topMargin, lp.leftMargin + child.getMeasuredWidth(), lp.topMargin + child.getMeasuredHeight()); } else { - child.layout(-child.getMeasuredWidth() + drawerPosition, lp.topMargin, drawerPosition, lp.topMargin + child.getMeasuredHeight()); + child.layout(-child.getMeasuredWidth() + (int)drawerPosition, lp.topMargin, (int)drawerPosition, lp.topMargin + child.getMeasuredHeight()); } } inLayout = false; @@ -462,9 +465,9 @@ public class DrawerLayoutContainer extends FrameLayout { 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((float) drawerPosition / AndroidUtilities.dp(20), 1.0f)); + final float alpha = Math.max(0, Math.min(drawerPosition / AndroidUtilities.dp(20), 1.0f)); if (alpha != 0) { - shadowLeft.setBounds(drawerPosition, child.getTop(), drawerPosition + shadowLeft.getIntrinsicWidth(), child.getBottom()); + shadowLeft.setBounds((int)drawerPosition, child.getTop(), (int)drawerPosition + shadowLeft.getIntrinsicWidth(), child.getBottom()); shadowLeft.setAlpha((int) (0xff * alpha)); shadowLeft.draw(canvas); } 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 389d17b8..9c7010c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountryAdapter.java @@ -15,7 +15,7 @@ import android.view.ViewGroup; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.messenger.FileLog; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import org.telegram.ui.Cells.DividerCell; import org.telegram.ui.Cells.LetterSectionCell; import org.telegram.ui.Cells.TextSettingsCell; 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 79c194fd..c5c2ca11 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -10,6 +10,7 @@ package org.telegram.ui.Adapters; import android.content.Context; import android.text.Html; +import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; @@ -36,10 +37,15 @@ import org.telegram.ui.Cells.LoadingCell; import org.telegram.ui.Cells.ProfileSearchCell; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Locale; import java.util.Timer; import java.util.TimerTask; public class DialogsSearchAdapter extends BaseContactsSearchAdapter { + private Context mContext; private Timer searchTimer; private ArrayList searchResult = new ArrayList(); @@ -54,6 +60,12 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { private String lastMessagesSearchString; private int lastSearchId = 0; + private class DialogSearchResult { + public TLObject object; + public int date; + public CharSequence name; + } + public static interface MessagesActivitySearchAdapterDelegate { public abstract void searchStateChanged(boolean searching); } @@ -143,19 +155,211 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { @Override public void run() { try { - FileLog.e("tmessages", "trigger search"); - ArrayList encUsers = new ArrayList(); String q = query.trim().toLowerCase(); if (q.length() == 0) { lastSearchId = -1; updateSearchResults(new ArrayList(), new ArrayList(), new ArrayList(), lastSearchId); return; } + + ArrayList usersToLoad = new ArrayList(); + ArrayList chatsToLoad = new ArrayList(); + ArrayList encryptedToLoad = new ArrayList(); + ArrayList encUsers = new ArrayList(); + int resultCount = 0; + + HashMap dialogsResult = new HashMap(); + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT did, date FROM dialogs ORDER BY date DESC LIMIT 200")); + while (cursor.next()) { + long id = cursor.longValue(0); + DialogSearchResult dialogSearchResult = new DialogSearchResult(); + dialogSearchResult.date = cursor.intValue(1); + dialogsResult.put(id, dialogSearchResult); + + int lower_id = (int)id; + int high_id = (int)(id >> 32); + if (lower_id != 0) { + if (high_id == 1) { + if (!serverOnly && !chatsToLoad.contains(lower_id)) { + chatsToLoad.add(lower_id); + } + } 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 if (!serverOnly) { + if (!encryptedToLoad.contains(high_id)) { + encryptedToLoad.add(high_id); + } + } + } + cursor.dispose(); + + if (!usersToLoad.isEmpty()) { + cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, status, name FROM users WHERE uid IN(%s)", TextUtils.join(",", usersToLoad))); + while (cursor.next()) { + String name = cursor.stringValue(2); + String username = null; + int usernamePos = name.lastIndexOf(";;;"); + if (usernamePos != -1) { + username = name.substring(usernamePos + 3); + } + int found = 0; + if (name.startsWith(q) || name.contains(" " + q)) { + found = 1; + } else if (username != null && username.startsWith(q)) { + found = 2; + } + if (found != 0) { + ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); + if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { + TLRPC.User user = (TLRPC.User) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); + if (user.id != UserConfig.getClientUserId()) { + DialogSearchResult dialogSearchResult = dialogsResult.get((long)user.id); + if (user.status != null) { + user.status.expires = cursor.intValue(1); + } + if (found == 1) { + dialogSearchResult.name = Utilities.generateSearchName(user.first_name, user.last_name, q); + } else { + dialogSearchResult.name = Utilities.generateSearchName("@" + user.username, null, "@" + q); + } + dialogSearchResult.object = user; + resultCount++; + } + } + MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); + } + } + cursor.dispose(); + } + + if (!chatsToLoad.isEmpty()) { + cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, name FROM chats WHERE uid IN(%s)", TextUtils.join(",", chatsToLoad))); + while (cursor.next()) { + String name = cursor.stringValue(1); + String[] args = name.split(" "); + if (name.startsWith(q) || name.contains(" " + q)) { + ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); + if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { + TLRPC.Chat chat = (TLRPC.Chat) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); + long dialog_id; + if (chat.id > 0) { + dialog_id = -chat.id; + } else { + dialog_id = AndroidUtilities.makeBroadcastId(chat.id); + } + DialogSearchResult dialogSearchResult = dialogsResult.get(dialog_id); + dialogSearchResult.name = Utilities.generateSearchName(chat.title, null, q); + dialogSearchResult.object = chat; + resultCount++; + } + MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); + } + } + cursor.dispose(); + } + + if (!encryptedToLoad.isEmpty()) { + cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT q.data, u.name, q.user, q.g, q.authkey, q.ttl, u.data, u.status, q.layer, q.seq_in, q.seq_out, q.use_count, q.exchange_id, q.key_date, q.fprint, q.fauthkey, q.khash FROM enc_chats as q INNER JOIN users as u ON q.user = u.uid WHERE q.uid IN(%s)", TextUtils.join(",", encryptedToLoad))); + while (cursor.next()) { + String name = cursor.stringValue(1); + + String username = null; + int usernamePos = name.lastIndexOf(";;;"); + if (usernamePos != -1) { + username = name.substring(usernamePos + 2); + } + int found = 0; + if (name.startsWith(q) || name.contains(" " + q)) { + found = 1; + } else if (username != null && username.startsWith(q)) { + found = 2; + } + + if (found != 0) { + ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); + ByteBufferDesc data2 = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(6)); + if (data != null && cursor.byteBufferValue(0, data.buffer) != 0 && cursor.byteBufferValue(6, data2.buffer) != 0) { + TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); + DialogSearchResult dialogSearchResult = dialogsResult.get((long)chat.id << 32); + + chat.user_id = cursor.intValue(2); + chat.a_or_b = cursor.byteArrayValue(3); + chat.auth_key = cursor.byteArrayValue(4); + chat.ttl = cursor.intValue(5); + chat.layer = cursor.intValue(8); + chat.seq_in = cursor.intValue(9); + chat.seq_out = cursor.intValue(10); + int use_count = cursor.intValue(11); + chat.key_use_count_in = (short)(use_count >> 16); + chat.key_use_count_out = (short)(use_count); + chat.exchange_id = cursor.longValue(12); + chat.key_create_date = cursor.intValue(13); + chat.future_key_fingerprint = cursor.longValue(14); + chat.future_auth_key = cursor.byteArrayValue(15); + chat.key_hash = cursor.byteArrayValue(16); + + TLRPC.User user = (TLRPC.User)TLClassStore.Instance().TLdeserialize(data2, data2.readInt32()); + if (user.status != null) { + user.status.expires = cursor.intValue(7); + } + if (found == 1) { + dialogSearchResult.name = Html.fromHtml("" + ContactsController.formatName(user.first_name, user.last_name) + ""); + } else { + dialogSearchResult.name = Utilities.generateSearchName("@" + user.username, null, "@" + q); + } + dialogSearchResult.object = chat; + encUsers.add(user); + resultCount++; + } + MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); + MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data2); + } + } + cursor.dispose(); + } + + ArrayList searchResults = new ArrayList(resultCount); + for (DialogSearchResult dialogSearchResult : dialogsResult.values()) { + if (dialogSearchResult.object != null && dialogSearchResult.name != null) { + searchResults.add(dialogSearchResult); + } + } + + Collections.sort(searchResults, new Comparator() { + @Override + public int compare(DialogSearchResult lhs, DialogSearchResult rhs) { + if (lhs.date < rhs.date) { + return 1; + } else if (lhs.date > rhs.date) { + return -1; + } + return 0; + } + }); + ArrayList resultArray = new ArrayList(); ArrayList resultArrayNames = new ArrayList(); - SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT u.data, u.status, u.name FROM users as u INNER JOIN contacts as c ON u.uid = c.uid"); + for (DialogSearchResult dialogSearchResult : searchResults) { + resultArray.add(dialogSearchResult.object); + resultArrayNames.add(dialogSearchResult.name); + } + + cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT u.data, u.status, u.name, u.uid FROM users as u INNER JOIN contacts as c ON u.uid = c.uid"); while (cursor.next()) { + int uid = cursor.intValue(3); + if (dialogsResult.containsKey((long)uid)) { + continue; + } String name = cursor.stringValue(2); String username = null; int usernamePos = name.lastIndexOf(";;;"); @@ -189,73 +393,6 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { } cursor.dispose(); - if (!serverOnly) { - cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT q.data, u.name, q.user, q.g, q.authkey, q.ttl, u.data, u.status, q.layer, q.seq_in, q.seq_out FROM enc_chats as q INNER JOIN dialogs as d ON (q.uid << 32) = d.did INNER JOIN users as u ON q.user = u.uid"); - while (cursor.next()) { - String name = cursor.stringValue(1); - - String username = null; - int usernamePos = name.lastIndexOf(";;;"); - if (usernamePos != -1) { - username = name.substring(usernamePos + 2); - } - int found = 0; - if (name.startsWith(q) || name.contains(" " + q)) { - found = 1; - } else if (username != null && username.startsWith(q)) { - found = 2; - } - - if (found != 0) { - ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); - ByteBufferDesc data2 = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(6)); - if (data != null && cursor.byteBufferValue(0, data.buffer) != 0 && cursor.byteBufferValue(6, data2.buffer) != 0) { - TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); - chat.user_id = cursor.intValue(2); - chat.a_or_b = cursor.byteArrayValue(3); - chat.auth_key = cursor.byteArrayValue(4); - chat.ttl = cursor.intValue(5); - chat.layer = cursor.intValue(8); - chat.seq_in = cursor.intValue(9); - chat.seq_out = cursor.intValue(10); - - TLRPC.User user = (TLRPC.User)TLClassStore.Instance().TLdeserialize(data2, data2.readInt32()); - if (user.status != null) { - user.status.expires = cursor.intValue(7); - } - if (found == 1) { - resultArrayNames.add(Html.fromHtml("" + ContactsController.formatName(user.first_name, user.last_name) + "")); - } else { - resultArrayNames.add(Utilities.generateSearchName("@" + user.username, null, "@" + q)); - } - resultArray.add(chat); - encUsers.add(user); - } - MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); - MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data2); - } - } - cursor.dispose(); - } - - cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT data, name FROM chats"); - while (cursor.next()) { - String name = cursor.stringValue(1); - String[] args = name.split(" "); - if (name.startsWith(q) || name.contains(" " + q)) { - ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); - if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { - TLRPC.Chat chat = (TLRPC.Chat) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); - if (serverOnly && chat.id < 0) { - continue; - } - resultArrayNames.add(Utilities.generateSearchName(chat.title, null, q)); - resultArray.add(chat); - } - MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); - } - } - cursor.dispose(); updateSearchResults(resultArray, resultArrayNames, encUsers, searchId); } catch (Exception e) { FileLog.e("tmessages", e); 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 c7e20f19..c0764d16 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -31,7 +31,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.ui.PhotoViewer; -import org.telegram.ui.Views.AvatarDrawable; +import org.telegram.ui.Components.AvatarDrawable; public class ChatActionCell extends BaseCell { 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 9ab00e61..f01d20b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java @@ -25,9 +25,9 @@ import org.telegram.android.MessagesController; import org.telegram.messenger.R; import org.telegram.android.MessageObject; import org.telegram.android.ImageReceiver; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.ProgressView; -import org.telegram.ui.Views.SeekBar; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.ProgressView; +import org.telegram.ui.Components.SeekBar; import java.io.File; 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 0440eb25..c2e1376a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java @@ -28,7 +28,7 @@ import org.telegram.android.MessagesController; import org.telegram.messenger.R; import org.telegram.android.MessageObject; import org.telegram.android.ImageReceiver; -import org.telegram.ui.Views.AvatarDrawable; +import org.telegram.ui.Components.AvatarDrawable; public class ChatBaseCell extends BaseCell { @@ -482,7 +482,7 @@ public class ChatBaseCell extends BaseCell { if (drawName && nameLayout != null) { canvas.save(); canvas.translate(currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(19) - nameOffsetX, AndroidUtilities.dp(10)); - namePaint.setColor(AvatarDrawable.getColorForId(currentUser.id)); + namePaint.setColor(AvatarDrawable.getNameColorForId(currentUser.id)); nameLayout.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 c7b316f1..13edf97c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java @@ -28,7 +28,7 @@ import org.telegram.android.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; -import org.telegram.ui.Views.AvatarDrawable; +import org.telegram.ui.Components.AvatarDrawable; public class ChatContactCell extends ChatBaseCell { 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 17b790a0..bd53d1c6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java @@ -21,7 +21,6 @@ import android.text.TextPaint; import android.text.TextUtils; import android.view.MotionEvent; import android.view.SoundEffectConstants; -import android.view.animation.DecelerateInterpolator; import org.telegram.android.AndroidUtilities; import org.telegram.android.ImageLoader; @@ -33,8 +32,9 @@ import org.telegram.messenger.R; import org.telegram.messenger.Utilities; import org.telegram.android.MessageObject; import org.telegram.android.PhotoObject; +import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.PhotoViewer; -import org.telegram.ui.Views.GifDrawable; +import org.telegram.ui.Components.GifDrawable; import org.telegram.android.ImageReceiver; import java.io.File; @@ -58,11 +58,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD private static MessageObject lastDownloadedGifMessage = null; private static TextPaint namePaint; private static Paint docBackPaint; - private static Paint progressPaint; private static Paint deleteProgressPaint; - private static DecelerateInterpolator decelerateInterpolator; private GifDrawable gifDrawable = null; + private RadialProgress radialProgress; private int photoWidth; private int photoHeight; @@ -71,7 +70,6 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD private String currentUrl; private String currentPhotoFilter; private ImageReceiver photoImage; - private boolean progressVisible = false; private boolean photoNotSet = false; private boolean cancelLoading = false; @@ -96,17 +94,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD private String currentNameString; private ChatMediaCellDelegate mediaDelegate = null; - - private float currentProgress = 0; - private RectF progressRect = new RectF(); - private long lastUpdateTime = 0; - private boolean animationStarted = false; - private float radOffset = 0; - private float animatedProgressValue = 0; - private long currentProgressTime = 0; - private float animationProgressStart = 0; private RectF deleteProgressRect = new RectF(); - private int lastSecretSecondsLeft = 0; public ChatMediaCell(Context context) { super(context); @@ -141,26 +129,21 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD docBackPaint = new Paint(); - progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - progressPaint.setStyle(Paint.Style.STROKE); - progressPaint.setStrokeCap(Paint.Cap.ROUND); - progressPaint.setStrokeWidth(AndroidUtilities.dp(2)); - deleteProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); deleteProgressPaint.setColor(0xffe4e2e0); - - decelerateInterpolator = new DecelerateInterpolator(); } TAG = MediaController.getInstance().generateObserverTag(); photoImage = new ImageReceiver(this); + radialProgress = new RadialProgress(this); } public void clearGifImage() { if (currentMessageObject != null && currentMessageObject.type == 8) { gifDrawable = null; buttonState = 2; + radialProgress.setBackground(getDrawableForCurrentState(), false, false); invalidate(); } } @@ -228,7 +211,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD if (event.getAction() == MotionEvent.ACTION_UP) { buttonPressed = 0; playSoundEffect(SoundEffectConstants.CLICK); - didPressedButton(); + didPressedButton(false); invalidate(); } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { buttonPressed = 0; @@ -295,7 +278,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD mediaDelegate.didClickedImage(this); } } else if (buttonState == 0) { - didPressedButton(); + didPressedButton(false); } } else if (currentMessageObject.type == 8) { if (buttonState == -1) { @@ -303,13 +286,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD if (gifDrawable != null) { gifDrawable.pause(); } + radialProgress.setBackground(getDrawableForCurrentState(), false, false); invalidate(); } else if (buttonState == 2 || buttonState == 0) { - didPressedButton(); + didPressedButton(false); } } else if (currentMessageObject.type == 3) { if (buttonState == 0 || buttonState == 3) { - didPressedButton(); + didPressedButton(false); } } else if (currentMessageObject.type == 4) { if (mediaDelegate != null) { @@ -324,7 +308,31 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } } - private void didPressedButton() { + private Drawable getDrawableForCurrentState() { + if (buttonState >= 0 && buttonState < 4) { + Drawable currentButtonDrawable = null; + if (currentMessageObject.type == 9 && gifDrawable == null) { + if (buttonState == 1 && !currentMessageObject.isSending()) { + return buttonStatesDrawablesDoc[2][currentMessageObject.isOut() ? 1 : 0]; + } else { + return buttonStatesDrawablesDoc[buttonState][currentMessageObject.isOut() ? 1 : 0]; + } + } else { + if (buttonState == 1 && !currentMessageObject.isSending()) { + return buttonStatesDrawables[4]; + } else { + return buttonStatesDrawables[buttonState]; + } + } + } else if (buttonState == -1) { + if (currentMessageObject.type == 9 && gifDrawable == null) { + return currentMessageObject.isOut() ? placeholderDocOutDrawable : placeholderDocInDrawable; + } + } + return null; + } + + private void didPressedButton(boolean animated) { if (buttonState == 0) { cancelLoading = false; if (currentMessageObject.type == 1) { @@ -339,9 +347,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } else if (currentMessageObject.type == 3) { FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.video, true); } - progressVisible = true; - startAnimation(); buttonState = 1; + radialProgress.setBackground(getDrawableForCurrentState(), true, animated); invalidate(); } else if (buttonState == 1) { if (currentMessageObject.isOut() && currentMessageObject.isSending()) { @@ -360,9 +367,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } else if (currentMessageObject.type == 3) { FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.video); } - progressVisible = false; - stopAnimation(); buttonState = 0; + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); invalidate(); } } else if (buttonState == 2) { @@ -373,7 +379,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD gifDrawable.start(); gifDrawable.invalidateSelf(); buttonState = -1; - invalidate(); + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); } } else if (buttonState == 3) { if (mediaDelegate != null) { @@ -407,11 +413,11 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD @Override public void setMessageObject(MessageObject messageObject) { media = messageObject.type != 9; - if (currentMessageObject != messageObject || isPhotoDataChanged(messageObject) || isUserDataChanged()) { + boolean dataChanged = currentMessageObject == messageObject && (isUserDataChanged() || photoNotSet); + if (currentMessageObject != messageObject || isPhotoDataChanged(messageObject) || dataChanged) { super.setMessageObject(messageObject); cancelLoading = false; - progressVisible = false; buttonState = -1; gifDrawable = null; currentPhotoObject = null; @@ -630,14 +636,14 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD invalidate(); } - updateButtonState(); + updateButtonState(dataChanged); } public ImageReceiver getPhotoImage() { return photoImage; } - public void updateButtonState() { + public void updateButtonState(boolean animated) { String fileName = null; File cacheFile = null; if (currentMessageObject.type == 1) { @@ -660,16 +666,16 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } } if (fileName == null) { + radialProgress.setBackground(null, false, false); return; } if (currentMessageObject.isOut() && currentMessageObject.isSending()) { if (currentMessageObject.messageOwner.attachPath != null) { MediaController.getInstance().addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this); - progressVisible = true; - startAnimation(); buttonState = 1; + radialProgress.setBackground(getDrawableForCurrentState(), true, animated); Float progress = FileLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath); - setProgress(progress != null ? progress : 0, false); + radialProgress.setProgress(progress != null ? progress : 0, false); invalidate(); } } else { @@ -681,29 +687,26 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } if (!cacheFile.exists()) { MediaController.getInstance().addLoadingFileObserver(fileName, this); + float setProgress = 0; + boolean progressVisible = false; if (!FileLoader.getInstance().isLoadingFile(fileName)) { if (cancelLoading || currentMessageObject.type != 1 || !MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)) { buttonState = 0; - progressVisible = false; - stopAnimation(); } else { - buttonState = 1; progressVisible = true; - startAnimation(); + buttonState = 1; } - setProgress(0, false); } else { - buttonState = 1; progressVisible = true; - startAnimation(); + buttonState = 1; Float progress = FileLoader.getInstance().getFileProgress(fileName); - setProgress(progress != null ? progress : 0, false); + setProgress = progress != null ? progress : 0; } + radialProgress.setBackground(getDrawableForCurrentState(), progressVisible, animated); + radialProgress.setProgress(setProgress, false); invalidate(); } else { MediaController.getInstance().removeLoadingFileObserver(this); - progressVisible = false; - stopAnimation(); if (currentMessageObject.type == 8 && (gifDrawable == null || gifDrawable != null && !gifDrawable.isRunning())) { buttonState = 2; } else if (currentMessageObject.type == 3) { @@ -711,59 +714,12 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } else { buttonState = -1; } + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); invalidate(); } } } - private void updateAnimation() { - long newTime = System.currentTimeMillis(); - long dt = newTime - lastUpdateTime; - lastUpdateTime = newTime; - - radOffset += 360 * dt / 3000.0f; - float progressDiff = currentProgress - animationProgressStart; - if (progressDiff > 0) { - currentProgressTime += dt; - if (currentProgressTime >= 300) { - animatedProgressValue = currentProgress; - animationProgressStart = currentProgress; - currentProgressTime = 0; - } else { - animatedProgressValue = animationProgressStart + progressDiff * decelerateInterpolator.getInterpolation(currentProgressTime / 300.0f); - } - } - - invalidateProgress(); - } - - private void startAnimation() { - lastUpdateTime = System.currentTimeMillis(); - animationStarted = true; - invalidateProgress(); - } - - private void setProgress(float value, boolean animated) { - if (!animated) { - animatedProgressValue = value; - animationProgressStart = value; - } else { - animationProgressStart = animatedProgressValue; - } - currentProgress = value; - currentProgressTime = 0; - } - - private void invalidateProgress() { - int offset = AndroidUtilities.dp(2); - invalidate((int)progressRect.left - offset, (int)progressRect.top - offset, (int)progressRect.right + offset * 2, (int)progressRect.bottom + offset * 2); - } - - private void stopAnimation() { - radOffset = 0; - animationStarted = false; - } - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), photoHeight + AndroidUtilities.dp(14)); @@ -791,7 +747,8 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD int size = AndroidUtilities.dp(48); buttonX = (int)(x + (photoWidth - size) / 2.0f); buttonY = (int)(AndroidUtilities.dp(7) + (photoHeight - size) / 2.0f); - progressRect.set(buttonX + AndroidUtilities.dp(1), buttonY + AndroidUtilities.dp(1), buttonX + AndroidUtilities.dp(47), buttonY + AndroidUtilities.dp(47)); + + radialProgress.setProgressRect(buttonX, buttonY, buttonX + AndroidUtilities.dp(48), buttonY + AndroidUtilities.dp(48)); deleteProgressRect.set(buttonX + AndroidUtilities.dp(3), buttonY + AndroidUtilities.dp(3), buttonX + AndroidUtilities.dp(45), buttonY + AndroidUtilities.dp(45)); } @@ -841,6 +798,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD drawTime = photoImage.getVisible(); } + radialProgress.setHideCurrentDrawable(false); if (currentMessageObject.type == 9) { Drawable menuDrawable = null; @@ -857,44 +815,37 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD setDrawableBounds(menuDrawable, photoImage.getImageX() + backgroundWidth - AndroidUtilities.dp(44), AndroidUtilities.dp(10)); menuDrawable.draw(canvas); + if (buttonState >= 0 && buttonState < 4) { + if (!imageDrawn) { + if (buttonState == 1 && !currentMessageObject.isSending()) { + radialProgress.swapBackground(buttonStatesDrawablesDoc[2][currentMessageObject.isOut() ? 1 : 0]); + } else { + radialProgress.swapBackground(buttonStatesDrawablesDoc[buttonState][currentMessageObject.isOut() ? 1 : 0]); + } + } else { + if (buttonState == 1 && !currentMessageObject.isSending()) { + radialProgress.swapBackground(buttonStatesDrawables[4]); + } else { + radialProgress.swapBackground(buttonStatesDrawables[buttonState]); + } + } + } + if (!imageDrawn) { canvas.drawRect(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX() + photoImage.getImageWidth(), photoImage.getImageY() + photoImage.getImageHeight(), docBackPaint); - - if (buttonState == -1) { - Drawable drawable = currentMessageObject.isOut() ? placeholderDocOutDrawable : placeholderDocInDrawable; - setDrawableBounds(drawable, photoImage.getImageX() + AndroidUtilities.dp(19), photoImage.getImageY() + AndroidUtilities.dp(19)); - drawable.draw(canvas); - } if (currentMessageObject.isOut()) { - progressPaint.setColor(0xff81bd72); - + radialProgress.setProgressColor(0xff81bd72); } else { - progressPaint.setColor(0xffadbdcc); + radialProgress.setProgressColor(0xffadbdcc); } } else { - progressPaint.setColor(0xffffffff); + if (buttonState == -1) { + radialProgress.setHideCurrentDrawable(true); + } + radialProgress.setProgressColor(0xffffffff); } } else { - progressPaint.setColor(0xffffffff); - } - - if (buttonState >= 0 && buttonState < 4) { - Drawable currentButtonDrawable = null; - if (currentMessageObject.type == 9 && !imageDrawn) { - if (buttonState == 1 && !currentMessageObject.isSending()) { - currentButtonDrawable = buttonStatesDrawablesDoc[2][currentMessageObject.isOut() ? 1 : 0]; - } else { - currentButtonDrawable = buttonStatesDrawablesDoc[buttonState][currentMessageObject.isOut() ? 1 : 0]; - } - } else { - if (buttonState == 1 && !currentMessageObject.isSending()) { - currentButtonDrawable = buttonStatesDrawables[4]; - } else { - currentButtonDrawable = buttonStatesDrawables[buttonState]; - } - } - setDrawableBounds(currentButtonDrawable, buttonX, buttonY); - currentButtonDrawable.draw(canvas); + radialProgress.setProgressColor(0xffffffff); } if (buttonState == -1 && currentMessageObject.isSecretPhoto()) { @@ -920,9 +871,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } } - if (progressVisible) { - canvas.drawArc(progressRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, progressPaint); - } + radialProgress.onDraw(canvas); if (nameLayout != null) { canvas.save(); @@ -951,22 +900,21 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD infoLayout.draw(canvas); canvas.restore(); } - - if (animationStarted) { - updateAnimation(); - } } @Override public void onFailedDownload(String fileName) { - updateButtonState(); + updateButtonState(false); } @Override public void onSuccessDownload(String fileName) { - updateButtonState(); - if (currentMessageObject.type == 8 && lastDownloadedGifMessage != null && lastDownloadedGifMessage.messageOwner.id == currentMessageObject.messageOwner.id && buttonState == 2) { - didPressedButton(); + radialProgress.setProgress(1, true); + if (currentMessageObject.type == 8 && lastDownloadedGifMessage != null && lastDownloadedGifMessage.messageOwner.id == currentMessageObject.messageOwner.id) { + buttonState = 2; + didPressedButton(true); + } else if (!photoNotSet) { + updateButtonState(true); } if (photoNotSet) { setMessageObject(currentMessageObject); @@ -975,18 +923,15 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD @Override public void onProgressDownload(String fileName, float progress) { - progressVisible = true; - setProgress(progress, true); + radialProgress.setProgress(progress, true); if (buttonState != 1) { - updateButtonState(); + updateButtonState(true); } - invalidateProgress(); } @Override public void onProgressUpload(String fileName, float progress, boolean isEncrypted) { - setProgress(progress, true); - invalidateProgress(); + radialProgress.setProgress(progress, true); } @Override 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 639d34a4..ef2814c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -147,10 +147,10 @@ public class ChatMessageCell extends ChatBaseCell { } } else { if (isChat && !messageObject.isOut()) { - maxWidth = AndroidUtilities.displaySize.x - AndroidUtilities.dp(122); + maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(122); drawName = true; } else { - maxWidth = AndroidUtilities.displaySize.x - AndroidUtilities.dp(80); + maxWidth = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(80); drawName = false; } } 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 ebbe032f..027b8cbf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -30,7 +30,7 @@ import org.telegram.android.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.android.ImageReceiver; -import org.telegram.ui.Views.AvatarDrawable; +import org.telegram.ui.Components.AvatarDrawable; public class DialogCell extends BaseCell { 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 d9f5199f..f1dfbb2e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -19,8 +19,8 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.AndroidUtilities; import org.telegram.android.ContactsController; import org.telegram.messenger.TLRPC; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; public class DrawerProfileCell extends FrameLayout { 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 40ac4026..47b4773b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -27,7 +27,7 @@ import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; -import org.telegram.ui.Views.AvatarDrawable; +import org.telegram.ui.Components.AvatarDrawable; public class ProfileSearchCell extends BaseCell { private static TextPaint namePaint; 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 5dc3b4ed..4e5da029 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java @@ -18,8 +18,8 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; -import org.telegram.ui.Views.FrameLayoutFixed; -import org.telegram.ui.Views.Switch; +import org.telegram.ui.Components.FrameLayoutFixed; +import org.telegram.ui.Components.Switch; public class TextCheckCell extends FrameLayoutFixed { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailDocumentsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailDocumentsCell.java index 43700151..89d0b8a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailDocumentsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailDocumentsCell.java @@ -18,8 +18,8 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; -import org.telegram.ui.Views.BackupImageView; -import org.telegram.ui.Views.CheckBox; +import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.CheckBox; public class TextDetailDocumentsCell extends FrameLayout { 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 03330695..4d62db65 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailSettingsCell.java @@ -17,7 +17,7 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; -import org.telegram.ui.Views.FrameLayoutFixed; +import org.telegram.ui.Components.FrameLayoutFixed; public class TextDetailSettingsCell extends FrameLayoutFixed { 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 4d49a33a..50f1ead8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -24,9 +24,9 @@ import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.BackupImageView; -import org.telegram.ui.Views.CheckBox; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.CheckBox; public class UserCell extends FrameLayout { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java index b5711b2a..ddecb6b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java @@ -26,6 +26,7 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.TLRPC; import org.telegram.android.MessagesController; import org.telegram.messenger.R; @@ -79,7 +80,7 @@ public class ChangeChatNameActivity extends BaseFragment { TLRPC.Chat currentChat = MessagesController.getInstance().getChat(chat_id); - fragmentView = new LinearLayout(inflater.getContext()); + fragmentView = new LinearLayout(getParentActivity()); fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL); fragmentView.setOnTouchListener(new View.OnTouchListener() { @@ -89,7 +90,7 @@ public class ChangeChatNameActivity extends BaseFragment { } }); - firstNameField = new EditText(inflater.getContext()); + firstNameField = new EditText(getParentActivity()); firstNameField.setText(currentChat.title); firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); firstNameField.setHintTextColor(0xff979797); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java index 667de884..666525aa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java @@ -25,6 +25,7 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.ConnectionsManager; @@ -74,7 +75,7 @@ public class ChangeNameActivity extends BaseFragment { user = UserConfig.getCurrentUser(); } - fragmentView = new LinearLayout(inflater.getContext()); + fragmentView = new LinearLayout(getParentActivity()); fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL); fragmentView.setOnTouchListener(new View.OnTouchListener() { @@ -84,7 +85,7 @@ public class ChangeNameActivity extends BaseFragment { } }); - firstNameField = new EditText(inflater.getContext()); + firstNameField = new EditText(getParentActivity()); firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); firstNameField.setHintTextColor(0xff979797); firstNameField.setTextColor(0xff212121); @@ -116,7 +117,7 @@ public class ChangeNameActivity extends BaseFragment { } }); - lastNameField = new EditText(inflater.getContext()); + lastNameField = new EditText(getParentActivity()); lastNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); lastNameField.setHintTextColor(0xff979797); lastNameField.setTextColor(0xff212121); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java new file mode 100644 index 00000000..d0dc19b2 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java @@ -0,0 +1,1089 @@ +/* + * This is the source code of Telegram for Android v. 2.0.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. + */ + +package org.telegram.ui; + +import android.app.AlertDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.os.Bundle; +import android.telephony.TelephonyManager; +import android.text.Editable; +import android.text.InputFilter; +import android.text.InputType; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.inputmethod.EditorInfo; +import android.widget.AdapterView; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +import org.telegram.PhoneFormat.PhoneFormat; +import org.telegram.android.AndroidUtilities; +import org.telegram.android.LocaleController; +import org.telegram.android.MessagesController; +import org.telegram.android.MessagesStorage; +import org.telegram.android.NotificationCenter; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.ConnectionsManager; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; +import org.telegram.messenger.RPCRequest; +import org.telegram.messenger.TLObject; +import org.telegram.messenger.TLRPC; +import org.telegram.messenger.UserConfig; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.ActionBarMenu; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.AnimationCompat.AnimatorListenerAdapterProxy; +import org.telegram.ui.AnimationCompat.AnimatorSetProxy; +import org.telegram.ui.AnimationCompat.ObjectAnimatorProxy; +import org.telegram.ui.AnimationCompat.ViewProxy; +import org.telegram.ui.Components.SlideView; +import org.telegram.ui.Components.TypefaceSpan; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Locale; +import java.util.Timer; +import java.util.TimerTask; + +public class ChangePhoneActivity extends BaseFragment { + + private int currentViewNum = 0; + private SlideView[] views = new SlideView[2]; + private ProgressDialog progressDialog; + + private final static int done_button = 1; + + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + for (SlideView v : views) { + if (v != null) { + v.onDestroyActivity(); + } + } + if (progressDialog != null) { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + progressDialog = null; + } + if (!AndroidUtilities.isTablet() && getParentActivity() != null) { + getParentActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); + } + } + + @Override + public View createView(LayoutInflater inflater, ViewGroup container) { + if (fragmentView == null) { + actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName)); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == done_button) { + views[currentViewNum].onNextPressed(); + } else if (id == -1) { + finishFragment(); + } + } + }); + + ActionBarMenu menu = actionBar.createMenu(); + menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + + fragmentView = new ScrollView(getParentActivity()); + ScrollView scrollView = (ScrollView) fragmentView; + scrollView.setFillViewport(true); + + FrameLayout frameLayout = new FrameLayout(getParentActivity()); + scrollView.addView(frameLayout); + ScrollView.LayoutParams layoutParams = (ScrollView.LayoutParams) frameLayout.getLayoutParams(); + layoutParams.width = ScrollView.LayoutParams.MATCH_PARENT; + layoutParams.height = ScrollView.LayoutParams.WRAP_CONTENT; + layoutParams.gravity = Gravity.TOP | Gravity.LEFT; + frameLayout.setLayoutParams(layoutParams); + + views[0] = new PhoneView(getParentActivity()); + views[0].setVisibility(View.VISIBLE); + frameLayout.addView(views[0]); + FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) views[0].getLayoutParams(); + layoutParams1.width = FrameLayout.LayoutParams.MATCH_PARENT; + layoutParams1.height = FrameLayout.LayoutParams.WRAP_CONTENT; + layoutParams1.leftMargin = AndroidUtilities.dp(16); + layoutParams1.rightMargin = AndroidUtilities.dp(16); + layoutParams1.topMargin = AndroidUtilities.dp(30); + layoutParams1.gravity = Gravity.TOP | Gravity.LEFT; + views[0].setLayoutParams(layoutParams1); + + views[1] = new LoginActivitySmsView(getParentActivity()); + views[1].setVisibility(View.GONE); + frameLayout.addView(views[1]); + layoutParams1 = (FrameLayout.LayoutParams) views[1].getLayoutParams(); + layoutParams1.width = FrameLayout.LayoutParams.MATCH_PARENT; + layoutParams1.height = FrameLayout.LayoutParams.MATCH_PARENT; + layoutParams1.leftMargin = AndroidUtilities.dp(16); + layoutParams1.rightMargin = AndroidUtilities.dp(16); + layoutParams1.topMargin = AndroidUtilities.dp(30); + layoutParams1.gravity = Gravity.TOP | Gravity.LEFT; + views[1].setLayoutParams(layoutParams1); + + try { + if (views[0] == null || views[1] == null) { + FrameLayout parent = (FrameLayout)((ScrollView) fragmentView).getChildAt(0); + for (int a = 0; a < views.length; a++) { + if (views[a] == null) { + views[a] = (SlideView)parent.getChildAt(a); + } + } + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + + actionBar.setTitle(views[0].getHeaderName()); + } else { + ViewGroup parent = (ViewGroup)fragmentView.getParent(); + if (parent != null) { + parent.removeView(fragmentView); + } + } + return fragmentView; + } + + @Override + public void onResume() { + super.onResume(); + if (!AndroidUtilities.isTablet()) { + getParentActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + } + } + + @Override + public boolean onBackPressed() { + if (currentViewNum == 0) { + for (SlideView v : views) { + if (v != null) { + v.onDestroyActivity(); + } + } + return true; + } else if (currentViewNum == 1) { + setPage(0, true, null, true); + } + return false; + } + + @Override + public void onOpenAnimationEnd() { + super.onOpenAnimationEnd(); + views[currentViewNum].onShow(); + } + + public void needShowAlert(final String text) { + if (text == null || getParentActivity() == null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(text); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + showAlertDialog(builder); + } + + public void needShowProgress() { + if (getParentActivity() == null || getParentActivity().isFinishing() || progressDialog != null) { + return; + } + progressDialog = new ProgressDialog(getParentActivity()); + progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.setCancelable(false); + progressDialog.show(); + } + + public void needHideProgress() { + if (progressDialog == null) { + return; + } + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + progressDialog = null; + } + + public void setPage(int page, boolean animated, Bundle params, boolean back) { + if(android.os.Build.VERSION.SDK_INT > 10) { + final SlideView outView = views[currentViewNum]; + final SlideView newView = views[page]; + currentViewNum = page; + + newView.setParams(params); + actionBar.setTitle(newView.getHeaderName()); + newView.onShow(); + ViewProxy.setX(newView, back ? -AndroidUtilities.displaySize.x : AndroidUtilities.displaySize.x); + + AnimatorSetProxy animatorSet = new AnimatorSetProxy(); + animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); + animatorSet.setDuration(300); + animatorSet.playTogether( + ObjectAnimatorProxy.ofFloat(outView, "translationX", back ? AndroidUtilities.displaySize.x : -AndroidUtilities.displaySize.x), + ObjectAnimatorProxy.ofFloat(newView, "translationX", 0)); + animatorSet.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationStart(Object animation) { + newView.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Object animation) { + outView.setVisibility(View.GONE); + outView.setX(0); + } + }); + animatorSet.start(); + } else { + views[currentViewNum].setVisibility(View.GONE); + currentViewNum = page; + views[page].setParams(params); + views[page].setVisibility(View.VISIBLE); + actionBar.setTitle(views[page].getHeaderName()); + views[page].onShow(); + } + } + + public class PhoneView extends SlideView implements AdapterView.OnItemSelectedListener { + + private EditText codeField; + private EditText phoneField; + private TextView countryButton; + + private int countryState = 0; + + private ArrayList countriesArray = new ArrayList(); + private HashMap countriesMap = new HashMap(); + private HashMap codesMap = new HashMap(); + + private boolean ignoreSelection = false; + private boolean ignoreOnTextChange = false; + private boolean ignoreOnPhoneChange = false; + private boolean nextPressed = false; + + public PhoneView(Context context) { + super(context); + + setOrientation(VERTICAL); + + countryButton = new TextView(context); + countryButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + countryButton.setPadding(AndroidUtilities.dp(12), AndroidUtilities.dp(10), AndroidUtilities.dp(12), 0); + countryButton.setTextColor(0xff212121); + countryButton.setMaxLines(1); + countryButton.setSingleLine(true); + countryButton.setEllipsize(TextUtils.TruncateAt.END); + countryButton.setGravity(Gravity.LEFT | Gravity.CENTER_HORIZONTAL); + countryButton.setBackgroundResource(R.drawable.spinner_states); + addView(countryButton); + LayoutParams layoutParams = (LayoutParams) countryButton.getLayoutParams(); + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = AndroidUtilities.dp(36); + layoutParams.leftMargin = AndroidUtilities.dp(20); + layoutParams.rightMargin = AndroidUtilities.dp(20); + layoutParams.bottomMargin = AndroidUtilities.dp(14); + countryButton.setLayoutParams(layoutParams); + countryButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + CountrySelectActivity fragment = new CountrySelectActivity(); + fragment.setCountrySelectActivityDelegate(new CountrySelectActivity.CountrySelectActivityDelegate() { + @Override + public void didSelectCountry(String name) { + selectCountry(name); + phoneField.requestFocus(); + } + }); + presentFragment(fragment); + } + }); + + View view = new View(context); + view.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0); + view.setBackgroundColor(0xffdbdbdb); + addView(view); + layoutParams = (LayoutParams) view.getLayoutParams(); + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = 1; + layoutParams.leftMargin = AndroidUtilities.dp(24); + layoutParams.rightMargin = AndroidUtilities.dp(24); + layoutParams.topMargin = AndroidUtilities.dp(-17.5f); + view.setLayoutParams(layoutParams); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(HORIZONTAL); + addView(linearLayout); + layoutParams = (LayoutParams) linearLayout.getLayoutParams(); + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.topMargin = AndroidUtilities.dp(20); + linearLayout.setLayoutParams(layoutParams); + + TextView textView = new TextView(context); + textView.setText("+"); + textView.setTextColor(0xff212121); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + linearLayout.addView(textView); + layoutParams = (LayoutParams) textView.getLayoutParams(); + layoutParams.width = LayoutParams.WRAP_CONTENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.leftMargin = AndroidUtilities.dp(24); + textView.setLayoutParams(layoutParams); + + codeField = new EditText(context); + codeField.setInputType(InputType.TYPE_CLASS_PHONE); + codeField.setTextColor(0xff212121); + AndroidUtilities.clearCursorDrawable(codeField); + codeField.setPadding(AndroidUtilities.dp(10), 0, 0, 0); + codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + codeField.setMaxLines(1); + codeField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + InputFilter[] inputFilters = new InputFilter[1]; + inputFilters[0] = new InputFilter.LengthFilter(4); + codeField.setFilters(inputFilters); + linearLayout.addView(codeField); + layoutParams = (LayoutParams) codeField.getLayoutParams(); + layoutParams.width = AndroidUtilities.dp(55); + layoutParams.height = AndroidUtilities.dp(36); + layoutParams.rightMargin = AndroidUtilities.dp(16); + layoutParams.leftMargin = AndroidUtilities.dp(-9); + codeField.setLayoutParams(layoutParams); + codeField.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { + + } + + @Override + public void afterTextChanged(Editable editable) { + if (ignoreOnTextChange) { + ignoreOnTextChange = false; + return; + } + ignoreOnTextChange = true; + String text = PhoneFormat.stripExceptNumbers(codeField.getText().toString()); + codeField.setText(text); + if (text.length() == 0) { + countryButton.setText(LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); + countryState = 1; + } else { + String country = codesMap.get(text); + if (country != null) { + int index = countriesArray.indexOf(country); + if (index != -1) { + ignoreSelection = true; + countryButton.setText(countriesArray.get(index)); + + updatePhoneField(); + countryState = 0; + } else { + countryButton.setText(LocaleController.getString("WrongCountry", R.string.WrongCountry)); + countryState = 2; + } + } else { + countryButton.setText(LocaleController.getString("WrongCountry", R.string.WrongCountry)); + countryState = 2; + } + codeField.setSelection(codeField.getText().length()); + } + } + }); + codeField.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { + if (i == EditorInfo.IME_ACTION_NEXT) { + phoneField.requestFocus(); + return true; + } + return false; + } + }); + + phoneField = new EditText(context); + phoneField.setInputType(InputType.TYPE_CLASS_PHONE); + phoneField.setTextColor(0xff212121); + phoneField.setHintTextColor(0xff979797); + phoneField.setPadding(0, 0, 0, 0); + AndroidUtilities.clearCursorDrawable(phoneField); + phoneField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + phoneField.setMaxLines(1); + phoneField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); + phoneField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + linearLayout.addView(phoneField); + layoutParams = (LayoutParams) phoneField.getLayoutParams(); + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = AndroidUtilities.dp(36); + layoutParams.rightMargin = AndroidUtilities.dp(24); + phoneField.setLayoutParams(layoutParams); + phoneField.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (ignoreOnPhoneChange) { + return; + } + if (count == 1 && after == 0 && s.length() > 1) { + String phoneChars = "0123456789"; + String str = s.toString(); + String substr = str.substring(start, start + 1); + if (!phoneChars.contains(substr)) { + ignoreOnPhoneChange = true; + StringBuilder builder = new StringBuilder(str); + int toDelete = 0; + for (int a = start; a >= 0; a--) { + substr = str.substring(a, a + 1); + if(phoneChars.contains(substr)) { + break; + } + toDelete++; + } + builder.delete(Math.max(0, start - toDelete), start + 1); + str = builder.toString(); + if (PhoneFormat.strip(str).length() == 0) { + phoneField.setText(""); + } else { + phoneField.setText(str); + updatePhoneField(); + } + ignoreOnPhoneChange = false; + } + } + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (ignoreOnPhoneChange) { + return; + } + updatePhoneField(); + } + }); + phoneField.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { + if (i == EditorInfo.IME_ACTION_NEXT) { + onNextPressed(); + return true; + } + return false; + } + }); + + textView = new TextView(context); + textView.setText(LocaleController.getString("StartText", R.string.StartText)); + textView.setTextColor(0xff757575); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setGravity(Gravity.LEFT); + textView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + addView(textView); + layoutParams = (LayoutParams) textView.getLayoutParams(); + layoutParams.width = LayoutParams.WRAP_CONTENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.leftMargin = AndroidUtilities.dp(24); + layoutParams.rightMargin = AndroidUtilities.dp(24); + layoutParams.topMargin = AndroidUtilities.dp(28); + layoutParams.bottomMargin = AndroidUtilities.dp(10); + layoutParams.gravity = Gravity.LEFT; + textView.setLayoutParams(layoutParams); + + HashMap languageMap = new HashMap(); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().getAssets().open("countries.txt"))); + String line; + while ((line = reader.readLine()) != null) { + String[] args = line.split(";"); + countriesArray.add(0, args[2]); + countriesMap.put(args[2], args[0]); + codesMap.put(args[0], args[2]); + languageMap.put(args[1], args[2]); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + + Collections.sort(countriesArray, new Comparator() { + @Override + public int compare(String lhs, String rhs) { + return lhs.compareTo(rhs); + } + }); + + String country = null; + + try { + TelephonyManager telephonyManager = (TelephonyManager)ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE); + if (telephonyManager != null) { + country = telephonyManager.getSimCountryIso().toUpperCase(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + + if (country != null) { + String countryName = languageMap.get(country); + if (countryName != null) { + int index = countriesArray.indexOf(countryName); + if (index != -1) { + codeField.setText(countriesMap.get(countryName)); + countryState = 0; + } + } + } + if (codeField.length() == 0) { + countryButton.setText(LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); + countryState = 1; + } + + if (codeField.length() != 0) { + AndroidUtilities.showKeyboard(phoneField); + phoneField.requestFocus(); + } else { + AndroidUtilities.showKeyboard(codeField); + codeField.requestFocus(); + } + } + + public void selectCountry(String name) { + int index = countriesArray.indexOf(name); + if (index != -1) { + ignoreOnTextChange = true; + codeField.setText(countriesMap.get(name)); + countryButton.setText(name); + countryState = 0; + } + } + + private void updatePhoneField() { + ignoreOnPhoneChange = true; + try { + String codeText = codeField.getText().toString(); + String phone = PhoneFormat.getInstance().format("+" + codeText + phoneField.getText().toString()); + int idx = phone.indexOf(" "); + if (idx != -1) { + String resultCode = PhoneFormat.stripExceptNumbers(phone.substring(0, idx)); + if (!codeText.equals(resultCode)) { + phone = PhoneFormat.getInstance().format(phoneField.getText().toString()).trim(); + phoneField.setText(phone); + int len = phoneField.length(); + phoneField.setSelection(phoneField.length()); + } else { + phoneField.setText(phone.substring(idx).trim()); + int len = phoneField.length(); + phoneField.setSelection(phoneField.length()); + } + } else { + phoneField.setSelection(phoneField.length()); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + ignoreOnPhoneChange = false; + } + + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + if (ignoreSelection) { + ignoreSelection = false; + return; + } + ignoreOnTextChange = true; + String str = countriesArray.get(i); + codeField.setText(countriesMap.get(str)); + updatePhoneField(); + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + + } + + @Override + public void onNextPressed() { + if (nextPressed) { + return; + } + if (countryState == 1) { + needShowAlert(LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); + return; + } else if (countryState == 2 && !BuildVars.DEBUG_VERSION) { + needShowAlert(LocaleController.getString("WrongCountry", R.string.WrongCountry)); + return; + } + if (codeField.length() == 0) { + needShowAlert(LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + return; + } + TLRPC.TL_account_sendChangePhoneCode req = new TLRPC.TL_account_sendChangePhoneCode(); + String phone = PhoneFormat.stripExceptNumbers("" + codeField.getText() + phoneField.getText()); + req.phone_number = phone; + final String phone2 = "+" + codeField.getText() + " " + phoneField.getText(); + + final Bundle params = new Bundle(); + params.putString("phone", phone2); + params.putString("phoneFormated", phone); + nextPressed = true; + needShowProgress(); + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + nextPressed = false; + if (error == null) { + TLRPC.TL_account_sentChangePhoneCode res = (TLRPC.TL_account_sentChangePhoneCode)response; + params.putString("phoneHash", res.phone_code_hash); + params.putInt("calltime", res.send_call_timeout * 1000); + setPage(1, true, params, false); + } else { + if (error.text != null) { + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + needShowAlert(LocaleController.getString("InvalidCode", R.string.InvalidCode)); + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + needShowAlert(LocaleController.getString("CodeExpired", R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(LocaleController.getString("FloodWait", R.string.FloodWait)); + } else if (error.text.startsWith("PHONE_NUMBER_OCCUPIED")) { + needShowAlert(LocaleController.formatString("ChangePhoneNumberOccupied", R.string.ChangePhoneNumberOccupied, phone2)); + } else { + needShowAlert(LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred)); + } + } + } + needHideProgress(); + } + }); + } + }, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors); + } + + @Override + public void onShow() { + super.onShow(); + if (phoneField != null) { + AndroidUtilities.showKeyboard(phoneField); + phoneField.setSelection(phoneField.length()); + } + } + + @Override + public String getHeaderName() { + return LocaleController.getString("ChangePhoneNewNumber", R.string.ChangePhoneNewNumber); + } + } + + public class LoginActivitySmsView extends SlideView implements NotificationCenter.NotificationCenterDelegate { + + private String phoneHash; + private String requestPhone; + private EditText codeField; + private TextView confirmTextView; + private TextView timeText; + private Bundle currentParams; + + private Timer timeTimer; + private Timer codeTimer; + private final Object timerSync = new Object(); + private volatile int time = 60000; + private volatile int codeTime = 15000; + private double lastCurrentTime; + private double lastCodeTime; + private boolean waitingForSms = false; + private boolean nextPressed = false; + private String lastError = ""; + + public LoginActivitySmsView(Context context) { + super(context); + + setOrientation(VERTICAL); + + confirmTextView = new TextView(context); + confirmTextView.setTextColor(0xff757575); + confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + confirmTextView.setGravity(Gravity.LEFT); + confirmTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + addView(confirmTextView); + LayoutParams layoutParams = (LayoutParams) confirmTextView.getLayoutParams(); + layoutParams.width = LayoutParams.WRAP_CONTENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.gravity = Gravity.LEFT; + layoutParams.leftMargin = AndroidUtilities.dp(24); + layoutParams.rightMargin = AndroidUtilities.dp(24); + confirmTextView.setLayoutParams(layoutParams); + + codeField = new EditText(context); + codeField.setTextColor(0xff212121); + codeField.setHint(LocaleController.getString("Code", R.string.Code)); + AndroidUtilities.clearCursorDrawable(codeField); + codeField.setHintTextColor(0xff979797); + codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + codeField.setInputType(InputType.TYPE_CLASS_PHONE); + codeField.setMaxLines(1); + codeField.setPadding(0, 0, 0, 0); + addView(codeField); + layoutParams = (LayoutParams) codeField.getLayoutParams(); + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = AndroidUtilities.dp(36); + layoutParams.gravity = Gravity.CENTER_HORIZONTAL; + layoutParams.topMargin = AndroidUtilities.dp(20); + layoutParams.leftMargin = AndroidUtilities.dp(24); + layoutParams.rightMargin = AndroidUtilities.dp(24); + codeField.setLayoutParams(layoutParams); + codeField.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { + if (i == EditorInfo.IME_ACTION_NEXT) { + onNextPressed(); + return true; + } + return false; + } + }); + + timeText = new TextView(context); + timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + timeText.setTextColor(0xff757575); + timeText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + timeText.setGravity(Gravity.LEFT); + addView(timeText); + layoutParams = (LayoutParams) timeText.getLayoutParams(); + layoutParams.width = LayoutParams.WRAP_CONTENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.gravity = Gravity.LEFT; + layoutParams.topMargin = AndroidUtilities.dp(30); + layoutParams.leftMargin = AndroidUtilities.dp(24); + layoutParams.rightMargin = AndroidUtilities.dp(24); + timeText.setLayoutParams(layoutParams); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setGravity(Gravity.BOTTOM | Gravity.CENTER_VERTICAL); + addView(linearLayout); + layoutParams = (LayoutParams) linearLayout.getLayoutParams(); + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = LayoutParams.MATCH_PARENT; + linearLayout.setLayoutParams(layoutParams); + + TextView wrongNumber = new TextView(context); + wrongNumber.setGravity(Gravity.LEFT | Gravity.CENTER_HORIZONTAL); + wrongNumber.setTextColor(0xff4d83b3); + wrongNumber.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + wrongNumber.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + wrongNumber.setPadding(0, AndroidUtilities.dp(24), 0, 0); + linearLayout.addView(wrongNumber); + layoutParams = (LayoutParams) wrongNumber.getLayoutParams(); + layoutParams.width = LayoutParams.WRAP_CONTENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.gravity = Gravity.BOTTOM | Gravity.LEFT; + layoutParams.bottomMargin = AndroidUtilities.dp(10); + layoutParams.leftMargin = AndroidUtilities.dp(24); + layoutParams.rightMargin = AndroidUtilities.dp(24); + wrongNumber.setLayoutParams(layoutParams); + wrongNumber.setText(LocaleController.getString("WrongNumber", R.string.WrongNumber)); + wrongNumber.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + onBackPressed(); + setPage(0, true, null, true); + } + }); + } + + @Override + public String getHeaderName() { + return LocaleController.getString("YourCode", R.string.YourCode); + } + + @Override + public void setParams(Bundle params) { + if (params == null) { + return; + } + codeField.setText(""); + AndroidUtilities.setWaitingForSms(true); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.didReceiveSmsCode); + currentParams = params; + waitingForSms = true; + String phone = params.getString("phone"); + requestPhone = params.getString("phoneFormated"); + phoneHash = params.getString("phoneHash"); + time = params.getInt("calltime"); + + if (phone == null) { + return; + } + + String number = PhoneFormat.getInstance().format(phone); + String str = String.format(Locale.US, LocaleController.getString("SentSmsCode", R.string.SentSmsCode) + " %s", number); + try { + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(str); + TypefaceSpan span = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + int idx = str.indexOf(number); + stringBuilder.setSpan(span, idx, idx + number.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); + confirmTextView.setText(stringBuilder); + } catch (Exception e) { + FileLog.e("tmessages", e); + confirmTextView.setText(str); + } + + AndroidUtilities.showKeyboard(codeField); + codeField.requestFocus(); + + destroyTimer(); + destroyCodeTimer(); + timeText.setText(LocaleController.formatString("CallText", R.string.CallText, 1, 0)); + lastCurrentTime = System.currentTimeMillis(); + + createTimer(); + } + + private void createCodeTimer() { + if (codeTimer != null) { + return; + } + codeTime = 15000; + codeTimer = new Timer(); + lastCodeTime = System.currentTimeMillis(); + codeTimer.schedule(new TimerTask() { + @Override + public void run() { + double currentTime = System.currentTimeMillis(); + double diff = currentTime - lastCodeTime; + codeTime -= diff; + lastCodeTime = currentTime; + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (codeTime <= 1000) { + destroyCodeTimer(); + } + } + }); + } + }, 0, 1000); + } + + private void destroyCodeTimer() { + try { + synchronized(timerSync) { + if (codeTimer != null) { + codeTimer.cancel(); + codeTimer = null; + } + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + + private void createTimer() { + if (timeTimer != null) { + return; + } + timeTimer = new Timer(); + timeTimer.schedule(new TimerTask() { + @Override + public void run() { + double currentTime = System.currentTimeMillis(); + double diff = currentTime - lastCurrentTime; + time -= diff; + lastCurrentTime = currentTime; + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (time >= 1000) { + int minutes = time / 1000 / 60; + int seconds = time / 1000 - minutes * 60; + timeText.setText(LocaleController.formatString("CallText", R.string.CallText, minutes, seconds)); + } else { + timeText.setText(LocaleController.getString("Calling", R.string.Calling)); + destroyTimer(); + createCodeTimer(); + TLRPC.TL_auth_sendCall req = new TLRPC.TL_auth_sendCall(); + req.phone_number = requestPhone; + req.phone_code_hash = phoneHash; + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, final TLRPC.TL_error error) { + if (error != null && error.text != null) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + lastError = error.text; + } + }); + } + } + }, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors | RPCRequest.RPCRequestClassWithoutLogin); + } + } + }); + } + }, 0, 1000); + } + + private void destroyTimer() { + try { + synchronized(timerSync) { + if (timeTimer != null) { + timeTimer.cancel(); + timeTimer = null; + } + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + + @Override + public void onNextPressed() { + if (nextPressed) { + return; + } + nextPressed = true; + waitingForSms = false; + AndroidUtilities.setWaitingForSms(false); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didReceiveSmsCode); + final TLRPC.TL_account_changePhone req = new TLRPC.TL_account_changePhone(); + req.phone_number = requestPhone; + req.phone_code = codeField.getText().toString(); + req.phone_code_hash = phoneHash; + destroyTimer(); + needShowProgress(); + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + needHideProgress(); + nextPressed = false; + if (error == null) { + TLRPC.User user = (TLRPC.User) response; + destroyTimer(); + destroyCodeTimer(); + UserConfig.setCurrentUser(user); + UserConfig.saveConfig(true); + ArrayList users = new ArrayList(); + users.add(user); + MessagesStorage.getInstance().putUsersAndChats(users, null, true, true); + MessagesController.getInstance().putUser(user, false); + finishFragment(); + } else { + lastError = error.text; + createTimer(); + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + needShowAlert(LocaleController.getString("InvalidCode", R.string.InvalidCode)); + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + needShowAlert(LocaleController.getString("CodeExpired", R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(LocaleController.getString("FloodWait", R.string.FloodWait)); + } else { + needShowAlert(error.text); + } + } + } + }); + } + }, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors | RPCRequest.RPCRequestClassWithoutLogin); + } + + @Override + public void onBackPressed() { + destroyTimer(); + destroyCodeTimer(); + currentParams = null; + AndroidUtilities.setWaitingForSms(false); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didReceiveSmsCode); + waitingForSms = false; + } + + @Override + public void onDestroyActivity() { + super.onDestroyActivity(); + AndroidUtilities.setWaitingForSms(false); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didReceiveSmsCode); + destroyTimer(); + destroyCodeTimer(); + waitingForSms = false; + } + + @Override + public void onShow() { + super.onShow(); + if (codeField != null) { + codeField.requestFocus(); + codeField.setSelection(codeField.length()); + } + } + + @Override + public void didReceivedNotification(int id, final Object... args) { + if (id == NotificationCenter.didReceiveSmsCode) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (!waitingForSms) { + return; + } + if (codeField != null) { + codeField.setText("" + args[0]); + onNextPressed(); + } + } + }); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java new file mode 100644 index 00000000..e2c2b2cb --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java @@ -0,0 +1,163 @@ +/* + * This is the source code of Telegram for Android v. 1.7.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. + */ + +package org.telegram.ui; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +import org.telegram.PhoneFormat.PhoneFormat; +import org.telegram.android.AndroidUtilities; +import org.telegram.android.LocaleController; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; +import org.telegram.messenger.TLRPC; +import org.telegram.messenger.UserConfig; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BaseFragment; + +public class ChangePhoneHelpActivity extends BaseFragment { + + @Override + public View createView(LayoutInflater inflater, ViewGroup container) { + if (fragmentView == null) { + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setAllowOverlayTitle(true); + + TLRPC.User user = UserConfig.getCurrentUser(); + String value; + if (user != null && user.phone != null && user.phone.length() != 0) { + value = PhoneFormat.getInstance().format("+" + user.phone); + } else { + value = LocaleController.getString("NumberUnknown", R.string.NumberUnknown); + } + + actionBar.setTitle(value); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + + fragmentView = new RelativeLayout(getParentActivity()); + fragmentView.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); + + RelativeLayout relativeLayout = (RelativeLayout) fragmentView; + + ScrollView scrollView = new ScrollView(getParentActivity()); + relativeLayout.addView(scrollView); + RelativeLayout.LayoutParams layoutParams3 = (RelativeLayout.LayoutParams) scrollView.getLayoutParams(); + layoutParams3.width = RelativeLayout.LayoutParams.MATCH_PARENT; + layoutParams3.height = RelativeLayout.LayoutParams.WRAP_CONTENT; + layoutParams3.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE); + scrollView.setLayoutParams(layoutParams3); + + LinearLayout linearLayout = new LinearLayout(getParentActivity()); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(0, AndroidUtilities.dp(20), 0, AndroidUtilities.dp(20)); + scrollView.addView(linearLayout); + ScrollView.LayoutParams layoutParams = (ScrollView.LayoutParams) linearLayout.getLayoutParams(); + layoutParams.width = ScrollView.LayoutParams.MATCH_PARENT; + layoutParams.height = ScrollView.LayoutParams.WRAP_CONTENT; + linearLayout.setLayoutParams(layoutParams); + + ImageView imageView = new ImageView(getParentActivity()); + imageView.setImageResource(R.drawable.phone_change); + linearLayout.addView(imageView); + LinearLayout.LayoutParams layoutParams2 = (LinearLayout.LayoutParams)imageView.getLayoutParams(); + layoutParams2.width = LinearLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.height = LinearLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.gravity = Gravity.CENTER_HORIZONTAL; + imageView.setLayoutParams(layoutParams2); + + TextView textView = new TextView(getParentActivity()); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setGravity(Gravity.CENTER_HORIZONTAL); + textView.setTextColor(0xff212121); + + try { + textView.setText(AndroidUtilities.replaceBold(LocaleController.getString("PhoneNumberHelp", R.string.PhoneNumberHelp))); + } catch (Exception e) { + FileLog.e("tmessages", e); + textView.setText(LocaleController.getString("PhoneNumberHelp", R.string.PhoneNumberHelp)); + } + linearLayout.addView(textView); + layoutParams2 = (LinearLayout.LayoutParams)textView.getLayoutParams(); + layoutParams2.width = LinearLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.height = LinearLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.gravity = Gravity.CENTER_HORIZONTAL; + layoutParams2.leftMargin = AndroidUtilities.dp(20); + layoutParams2.rightMargin = AndroidUtilities.dp(20); + layoutParams2.topMargin = AndroidUtilities.dp(56); + textView.setLayoutParams(layoutParams2); + + textView = new TextView(getParentActivity()); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + textView.setGravity(Gravity.CENTER_HORIZONTAL); + textView.setTextColor(0xff4d83b3); + textView.setText(LocaleController.getString("PhoneNumberChange", R.string.PhoneNumberChange)); + textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + textView.setPadding(0, AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10)); + linearLayout.addView(textView); + layoutParams2 = (LinearLayout.LayoutParams)textView.getLayoutParams(); + layoutParams2.width = LinearLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.height = LinearLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.gravity = Gravity.CENTER_HORIZONTAL; + layoutParams2.leftMargin = AndroidUtilities.dp(20); + layoutParams2.rightMargin = AndroidUtilities.dp(20); + layoutParams2.topMargin = AndroidUtilities.dp(46); + textView.setLayoutParams(layoutParams2); + + textView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (getParentActivity() == null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("PhoneNumberAlert", R.string.PhoneNumberAlert)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + presentFragment(new ChangePhoneActivity(), true); + } + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + showAlertDialog(builder); + } + }); + + } else { + ViewGroup parent = (ViewGroup)fragmentView.getParent(); + if (parent != null) { + parent.removeView(fragmentView); + } + } + return fragmentView; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java index 6ebeae2d..681228d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java @@ -34,6 +34,7 @@ import org.telegram.android.LocaleController; import org.telegram.android.MessagesController; import org.telegram.android.MessagesStorage; import org.telegram.android.NotificationCenter; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; @@ -84,7 +85,7 @@ public class ChangeUsernameActivity extends BaseFragment { user = UserConfig.getCurrentUser(); } - fragmentView = new LinearLayout(inflater.getContext()); + fragmentView = new LinearLayout(getParentActivity()); fragmentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); ((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL); fragmentView.setOnTouchListener(new View.OnTouchListener() { @@ -94,7 +95,7 @@ public class ChangeUsernameActivity extends BaseFragment { } }); - firstNameField = new EditText(inflater.getContext()); + firstNameField = new EditText(getParentActivity()); firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); firstNameField.setHintTextColor(0xff979797); firstNameField.setTextColor(0xff212121); @@ -132,7 +133,7 @@ public class ChangeUsernameActivity extends BaseFragment { firstNameField.setSelection(firstNameField.length()); } - checkTextView = new TextView(inflater.getContext()); + checkTextView = new TextView(getParentActivity()); checkTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); checkTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); ((LinearLayout) fragmentView).addView(checkTextView); @@ -145,7 +146,7 @@ public class ChangeUsernameActivity extends BaseFragment { layoutParams.rightMargin = AndroidUtilities.dp(24); checkTextView.setLayoutParams(layoutParams); - TextView helpTextView = new TextView(inflater.getContext()); + TextView helpTextView = new TextView(getParentActivity()); helpTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); helpTextView.setTextColor(0xff6d6d72); helpTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index a8880bab..508f34ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -49,7 +49,9 @@ import org.telegram.android.LocaleController; import org.telegram.android.MediaController; import org.telegram.android.MessagesStorage; import org.telegram.android.NotificationsController; +import org.telegram.android.SecretChatHelper; import org.telegram.android.SendMessagesHelper; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; import org.telegram.messenger.TLRPC; import org.telegram.android.ContactsController; @@ -75,16 +77,16 @@ import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.ChatActivityEnterView; +import org.telegram.ui.Components.ChatActivityEnterView; import org.telegram.android.ImageReceiver; -import org.telegram.ui.Views.FrameLayoutFixed; -import org.telegram.ui.Views.LayoutListView; -import org.telegram.ui.Views.SizeNotifierRelativeLayout; -import org.telegram.ui.Views.TimerDrawable; -import org.telegram.ui.Views.TypingDotsDrawable; +import org.telegram.ui.Components.FrameLayoutFixed; +import org.telegram.ui.Components.LayoutListView; +import org.telegram.ui.Components.SizeNotifierRelativeLayout; +import org.telegram.ui.Components.TimerDrawable; +import org.telegram.ui.Components.TypingDotsDrawable; import java.io.File; import java.util.ArrayList; @@ -429,8 +431,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not typingDotsDrawable = new TypingDotsDrawable(); typingDotsDrawable.setIsChat(currentChat != null); - if (currentEncryptedChat != null && AndroidUtilities.getMyLayerVersion(currentEncryptedChat.layer) != SendMessagesHelper.CURRENT_SECRET_CHAT_LAYER) { - SendMessagesHelper.getInstance().sendNotifyLayerMessage(currentEncryptedChat, null); + if (currentEncryptedChat != null && AndroidUtilities.getMyLayerVersion(currentEncryptedChat.layer) != SecretChatHelper.CURRENT_SECRET_CHAT_LAYER) { + SecretChatHelper.getInstance().sendNotifyLayerMessage(currentEncryptedChat, null); } return true; @@ -2431,7 +2433,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (obj.isOut() && !obj.isUnread()) { break; } - if (obj.messageOwner.date <= date) { + if (obj.messageOwner.date - 1 <= date) { obj.setIsRead(); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/AvatarDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java similarity index 96% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/AvatarDrawable.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java index b38772f3..7c7e230c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/AvatarDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; @@ -22,7 +22,7 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; import java.util.Locale; @@ -34,9 +34,12 @@ public class AvatarDrawable extends Drawable { private static int[] arrColorsProfiles = {0xffd86f65, 0xfff69d61, 0xfffabb3c, 0xff67b35d, 0xff56a2bb, 0xff5c98cd, 0xff8c79d2, 0xfff37fa6}; private static int[] arrColorsProfilesBack = {0xffca6056, 0xfff18944, 0xfff2b02c, 0xff56a14c, 0xff4492ac, 0xff4c84b6, 0xff7d6ac4, 0xffe66b94}; private static int[] arrColorsProfilesText = {0xfff9cbc5, 0xfffdddc8, 0xfffce5bb, 0xffc0edba, 0xffb8e2f0, 0xffb3d7f7, 0xffcdc4ed, 0xfffed1e0}; + private static int[] arrColorsNames = {0xffca5650, 0xffd87b29, 0xffc7a21c, 0xff50b232, 0xff42b1a8, 0xff4e92cc, 0xff4e92cc, 0xffdb5b9d}; private static int[] arrColorsButtons = {R.drawable.bar_selector_red, R.drawable.bar_selector_orange, R.drawable.bar_selector_yellow, R.drawable.bar_selector_green, R.drawable.bar_selector_cyan, R.drawable.bar_selector_blue, R.drawable.bar_selector_violet, R.drawable.bar_selector_pink}; + + private static Drawable broadcastDrawable; private static Drawable photoDrawable; @@ -132,6 +135,10 @@ public class AvatarDrawable extends Drawable { return arrColorsProfilesBack[getColorIndex(id)]; } + public static int getNameColorForId(int id) { + return arrColorsNames[getColorIndex(id)]; + } + public void setInfo(TLRPC.User user) { if (user != null) { setInfo(user.id, user.first_name, user.last_name, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/AvatarUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/AvatarUpdater.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java index c462cd51..07edc7ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/AvatarUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.app.Activity; import android.content.Intent; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/BackupImageView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index f311f94b..950a2cda 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Bitmap; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java similarity index 89% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/ChatActivityEnterView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index 10643559..01cbcdc0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -6,12 +6,13 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.graphics.Rect; +import android.os.Build; import android.os.PowerManager; import android.text.Editable; import android.text.TextWatcher; @@ -29,7 +30,6 @@ import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.PopupWindow; import android.widget.TextView; import org.telegram.android.AndroidUtilities; @@ -43,11 +43,12 @@ import org.telegram.messenger.FileLog; import org.telegram.android.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; +import org.telegram.messenger.UserConfig; import org.telegram.ui.AnimationCompat.AnimatorListenerAdapterProxy; import org.telegram.ui.AnimationCompat.AnimatorSetProxy; import org.telegram.ui.AnimationCompat.ObjectAnimatorProxy; import org.telegram.ui.AnimationCompat.ViewProxy; -import org.telegram.ui.ApplicationLoader; +import org.telegram.messenger.ApplicationLoader; public class ChatActivityEnterView implements NotificationCenter.NotificationCenterDelegate, SizeNotifierRelativeLayout.SizeNotifierRelativeLayoutDelegate { @@ -60,7 +61,6 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen private EditText messsageEditText; private ImageButton sendButton; - private PopupWindow emojiPopup; private ImageView emojiButton; private EmojiView emojiView; private TextView recordTimeText; @@ -76,6 +76,9 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen private int runningAnimationType; private int audioInterfaceState; + private WindowManager.LayoutParams windowLayoutParams; + private boolean showingEmoji; + private int keyboardHeight; private int keyboardHeightLand; private boolean keyboardVisible; @@ -124,6 +127,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.delegate = null; } + removeEmojiWindow(); } public void setContainerView(Activity activity, View containerView) { @@ -160,18 +164,14 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen emojiButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if (emojiPopup == null) { - showEmojiPopup(true); - } else { - showEmojiPopup(!emojiPopup.isShowing()); - } + showEmojiPopup(!showingEmoji); } }); messsageEditText.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View view, int i, KeyEvent keyEvent) { - if (i == 4 && !keyboardVisible && emojiPopup != null && emojiPopup.isShowing()) { + if (i == 4 && !keyboardVisible && showingEmoji) { if (keyEvent.getAction() == 1) { showEmojiPopup(false); } @@ -187,7 +187,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen messsageEditText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - if (emojiPopup != null && emojiPopup.isShowing()) { + if (showingEmoji) { showEmojiPopup(false); } } @@ -291,7 +291,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen if ((int) dialog_id > 0) { currentUser = MessagesController.getInstance().getUser((int) dialog_id); } - if (currentUser != null && currentUser.status != null && currentUser.status.expires < currentTime) { + if (currentUser != null && (currentUser.id == UserConfig.getClientUserId() || currentUser.status != null && currentUser.status.expires < currentTime)) { return; } lastTypingTimeSend = System.currentTimeMillis(); @@ -609,13 +609,47 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen } private void showEmojiPopup(boolean show) { + showingEmoji = show; if (show) { - if (emojiPopup == null) { - createEmojiPopup(); + if (emojiView == null) { + if (parentActivity == null) { + return; + } + emojiView = new EmojiView(parentActivity); + emojiView.setListener(new EmojiView.Listener() { + public void onBackspace() { + messsageEditText.dispatchKeyEvent(new KeyEvent(0, 67)); + } + + public void onEmojiSelected(String symbol) { + int i = messsageEditText.getSelectionEnd(); + if (i < 0) { + i = 0; + } + try { + CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messsageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); + messsageEditText.setText(messsageEditText.getText().insert(i, localCharSequence)); + int j = i + localCharSequence.length(); + messsageEditText.setSelection(j, j); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + + windowLayoutParams = new WindowManager.LayoutParams(); + windowLayoutParams.gravity = Gravity.BOTTOM | Gravity.LEFT; + if (Build.VERSION.SDK_INT >= 21) { + windowLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; + } else { + windowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; + windowLayoutParams.token = parentActivity.getWindow().getDecorView().getWindowToken(); + } + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; } int currentHeight; - WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); - int rotation = manager.getDefaultDisplay().getRotation(); + WindowManager wm = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); + int rotation = wm.getDefaultDisplay().getRotation(); if (keyboardHeight <= 0) { keyboardHeight = ApplicationLoader.applicationContext.getSharedPreferences("emoji", 0).getInt("kbd_height", AndroidUtilities.dp(200)); } @@ -627,16 +661,24 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen } else { currentHeight = keyboardHeight; } - emojiPopup.setHeight(View.MeasureSpec.makeMeasureSpec(currentHeight, View.MeasureSpec.EXACTLY)); - if (sizeNotifierRelativeLayout != null) { - emojiPopup.setWidth(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.EXACTLY)); - } + windowLayoutParams.height = currentHeight; + windowLayoutParams.width = AndroidUtilities.displaySize.x; try { - emojiPopup.showAtLocation(parentActivity.getWindow().getDecorView(), Gravity.BOTTOM | Gravity.LEFT, 0, 0); + if (emojiView.getParent() != null) { + wm.removeViewImmediate(emojiView); + } } catch (Exception e) { FileLog.e("tmessages", e); } + + try { + wm.addView(emojiView, windowLayoutParams); + } catch (Exception e) { + FileLog.e("tmessages", e); + return; + } + if (!keyboardVisible) { if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.setPadding(0, 0, 0, currentHeight); @@ -650,9 +692,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen if (emojiButton != null) { emojiButton.setImageResource(R.drawable.ic_msg_panel_smiles); } - if (emojiPopup != null) { - emojiPopup.dismiss(); - } + removeEmojiWindow(); if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.post(new Runnable() { public void run() { @@ -664,38 +704,24 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen } } - public void hideEmojiPopup() { - if (emojiPopup != null && emojiPopup.isShowing()) { - showEmojiPopup(false); + private void removeEmojiWindow() { + if (emojiView == null) { + return; + } + try { + if (emojiView.getParent() != null) { + WindowManager wm = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE); + wm.removeViewImmediate(emojiView); + } + } catch (Exception e) { + FileLog.e("tmessages", e); } } - private void createEmojiPopup() { - if (parentActivity == null) { - return; + public void hideEmojiPopup() { + if (showingEmoji) { + showEmojiPopup(false); } - emojiView = new EmojiView(parentActivity); - emojiView.setListener(new EmojiView.Listener() { - public void onBackspace() { - messsageEditText.dispatchKeyEvent(new KeyEvent(0, 67)); - } - - public void onEmojiSelected(String symbol) { - int i = messsageEditText.getSelectionEnd(); - if (i < 0) { - i = 0; - } - try { - CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messsageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); - messsageEditText.setText(messsageEditText.getText().insert(i, localCharSequence)); - int j = i + localCharSequence.length(); - messsageEditText.setSelection(j, j); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - }); - emojiPopup = new PopupWindow(emojiView); } public void setDelegate(ChatActivityEnterViewDelegate delegate) { @@ -754,7 +780,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen } public boolean isEmojiPopupShowing() { - return emojiPopup != null && emojiPopup.isShowing(); + return showingEmoji; } public void addToAttachLayout(View view) { @@ -778,11 +804,11 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen Rect localRect = new Rect(); parentActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(localRect); - WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); - if (manager == null || manager.getDefaultDisplay() == null) { + WindowManager wm = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); + if (wm == null || wm.getDefaultDisplay() == null) { return; } - int rotation = manager.getDefaultDisplay().getRotation(); + int rotation = wm.getDefaultDisplay().getRotation(); if (height > AndroidUtilities.dp(50) && keyboardVisible) { if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) { @@ -794,25 +820,23 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen } } - if (emojiPopup != null && emojiPopup.isShowing()) { + if (showingEmoji) { int newHeight = 0; if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) { newHeight = keyboardHeightLand; } else { newHeight = keyboardHeight; } - final WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) emojiPopup.getContentView().getLayoutParams(); - if (layoutParams.width != AndroidUtilities.displaySize.x || layoutParams.height != newHeight) { - WindowManager wm = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE); - layoutParams.width = AndroidUtilities.displaySize.x; - layoutParams.height = newHeight; - wm.updateViewLayout(emojiPopup.getContentView(), layoutParams); + if (windowLayoutParams.width != AndroidUtilities.displaySize.x || windowLayoutParams.height != newHeight) { + windowLayoutParams.width = AndroidUtilities.displaySize.x; + windowLayoutParams.height = newHeight; + wm.updateViewLayout(emojiView, windowLayoutParams); if (!keyboardVisible) { sizeNotifierRelativeLayout.post(new Runnable() { @Override public void run() { if (sizeNotifierRelativeLayout != null) { - sizeNotifierRelativeLayout.setPadding(0, 0, 0, layoutParams.height); + sizeNotifierRelativeLayout.setPadding(0, 0, 0, windowLayoutParams.height); sizeNotifierRelativeLayout.requestLayout(); } } @@ -825,7 +849,7 @@ public class ChatActivityEnterView implements NotificationCenter.NotificationCen keyboardVisible = height > 0; if (keyboardVisible && sizeNotifierRelativeLayout.getPaddingBottom() > 0) { showEmojiPopup(false); - } else if (!keyboardVisible && keyboardVisible != oldValue && emojiPopup != null && emojiPopup.isShowing()) { + } else if (!keyboardVisible && keyboardVisible != oldValue && showingEmoji) { showEmojiPopup(false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/CheckBox.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/CheckBox.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java index 6f5275b2..7bedce80 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/CheckBox.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CheckBox.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Bitmap; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/ClippingImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/ClippingImageView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java index e3243f9e..a288647f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/ClippingImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Bitmap; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/ColorPickerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPickerView.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/ColorPickerView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPickerView.java index 7135cbfb..ef7319a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/ColorPickerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPickerView.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/EmojiView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index eb018421..708e00f0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.database.DataSetObserver; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/FrameLayoutFixed.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/FrameLayoutFixed.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java index 73bcd9dc..1d30c568 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/FrameLayoutFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FrameLayoutFixed.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.drawable.Drawable; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/GifDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GifDrawable.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/GifDrawable.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/GifDrawable.java index 5af31e03..2462db98 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/GifDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GifDrawable.java @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.graphics.Bitmap; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/HorizontalListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/HorizontalListView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java index 0bef5eb8..4cc5b091 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/HorizontalListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java @@ -5,7 +5,7 @@ * * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import java.util.HashMap; import java.util.LinkedList; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/IdenticonDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java similarity index 74% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/IdenticonDrawable.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java index 6ceba01c..b1a04b8e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/IdenticonDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/IdenticonDrawable.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; @@ -14,9 +14,11 @@ import android.graphics.Paint; import android.graphics.drawable.Drawable; import org.telegram.android.AndroidUtilities; +import org.telegram.messenger.TLRPC; import org.telegram.messenger.Utilities; public class IdenticonDrawable extends Drawable { + private byte[] data; private Paint paint = new Paint(); private int colors[] = { @@ -26,23 +28,16 @@ public class IdenticonDrawable extends Drawable { 0xff2f99c9 }; - int get_bits(int bitOffset, int numBits) { - numBits = (int)Math.pow(2, numBits) - 1; - int offset = bitOffset / 8; - bitOffset %= 8; - int val = data[offset + 3] << 24 | data[offset + 2] << 16 | data[offset + 1] << 8 | data[offset]; - return (val >> bitOffset) & numBits; + private int getBits(int bitOffset) { + return (data[bitOffset / 8] >> (bitOffset % 8)) & 0x3; } - public void setBytes(byte[] bytes) { - if (bytes == null) { - return; - } - data = Utilities.computeSHA1(bytes); - if (data.length < 128) { - byte[] temp = new byte[128]; - System.arraycopy(data, 0, temp, 0, data.length); - data = temp; + public void setEncryptedChat(TLRPC.EncryptedChat encryptedChat) { + data = encryptedChat.key_hash; + if (data == null) { + byte[] sha1 = Utilities.computeSHA1(encryptedChat.auth_key); + encryptedChat.key_hash = data = new byte[16]; + System.arraycopy(sha1, 0, data, 0, data.length); } invalidateSelf(); } @@ -59,7 +54,7 @@ public class IdenticonDrawable extends Drawable { float yOffset = Math.max(0, (getBounds().height() - rectSize * 8) / 2); for (int iy = 0; iy < 8; iy++) { for (int ix = 0; ix < 8; ix++) { - int byteValue = get_bits(bitPointer, 2); + int byteValue = getBits(bitPointer); bitPointer += 2; int colorIndex = Math.abs(byteValue) % 4; paint.setColor(colors[colorIndex]); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/LayoutListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutListView.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/LayoutListView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutListView.java index 4d5617a8..6712cf6f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/LayoutListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutListView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.util.AttributeSet; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/NumberPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/NumberPicker.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java index bd5e23b2..a0c15f5f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/NumberPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.content.res.ColorStateList; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/PagerSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/PagerSlidingTabStrip.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java index e3ab3e1c..c568f4a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/PagerSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import java.util.Locale; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/PopupAudioView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/PopupAudioView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java index 2af5b6c6..e7a78a4a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/PopupAudioView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/ProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java similarity index 97% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/ProgressView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java index 6dc14ac3..adaa786e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/ProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.Paint; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java new file mode 100644 index 00000000..02438ea9 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java @@ -0,0 +1,163 @@ +/* + * This is the source code of Telegram for Android v. 2.0.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. + */ + +package org.telegram.ui.Components; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.view.animation.DecelerateInterpolator; + +import org.telegram.android.AndroidUtilities; + +public class RadialProgress { + + private long lastUpdateTime = 0; + private float radOffset = 0; + private float currentProgress = 0; + private float animationProgressStart = 0; + private long currentProgressTime = 0; + private float animatedProgressValue = 0; + private RectF progressRect = new RectF(); + private RectF cicleRect = new RectF(); + private View parent = null; + private float animatedAlphaValue = 1.0f; + + private boolean currentWithRound; + private boolean previousWithRound; + private Drawable currentDrawable; + private Drawable previousDrawable; + private boolean hideCurrentDrawable; + + private static DecelerateInterpolator decelerateInterpolator = null; + private static Paint progressPaint = null; + + public RadialProgress(View parentView) { + if (decelerateInterpolator == null) { + decelerateInterpolator = new DecelerateInterpolator(); + progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + progressPaint.setStyle(Paint.Style.STROKE); + progressPaint.setStrokeCap(Paint.Cap.ROUND); + progressPaint.setStrokeWidth(AndroidUtilities.dp(2)); + progressPaint.setColor(0xffffffff); + } + parent = parentView; + } + + public void setProgressRect(int left, int top, int right, int bottom) { + progressRect.set(left, top, right, bottom); + } + + private void updateAnimation() { + long newTime = System.currentTimeMillis(); + long dt = newTime - lastUpdateTime; + lastUpdateTime = newTime; + + if (animatedProgressValue != 1) { + radOffset += 360 * dt / 3000.0f; + float progressDiff = currentProgress - animationProgressStart; + if (progressDiff > 0) { + currentProgressTime += dt; + if (currentProgressTime >= 300) { + animatedProgressValue = currentProgress; + animationProgressStart = currentProgress; + currentProgressTime = 0; + } else { + animatedProgressValue = animationProgressStart + progressDiff * decelerateInterpolator.getInterpolation(currentProgressTime / 300.0f); + } + } + invalidateParent(); + } + if (animatedProgressValue >= 1 && previousDrawable != null) { + animatedAlphaValue -= dt / 200.0f; + if (animatedAlphaValue <= 0) { + animatedAlphaValue = 0.0f; + previousDrawable = null; + } + invalidateParent(); + } + } + + public void setProgressColor(int color) { + progressPaint.setColor(color); + } + + public void setHideCurrentDrawable(boolean value) { + hideCurrentDrawable = value; + } + + public void setProgress(float value, boolean animated) { + if (!animated) { + animatedProgressValue = value; + animationProgressStart = value; + } else { + animationProgressStart = animatedProgressValue; + } + currentProgress = value; + currentProgressTime = 0; + + invalidateParent(); + } + + private void invalidateParent() { + int offset = AndroidUtilities.dp(2); + parent.invalidate((int)progressRect.left - offset, (int)progressRect.top - offset, (int)progressRect.right + offset * 2, (int)progressRect.bottom + offset * 2); + } + + public void setBackground(Drawable drawable, boolean withRound, boolean animated) { + lastUpdateTime = System.currentTimeMillis(); + if (animated && currentDrawable != drawable) { + setProgress(1, animated); + previousDrawable = currentDrawable; + previousWithRound = currentWithRound; + animatedAlphaValue = 1.0f; + } else { + previousDrawable = null; + previousWithRound = false; + } + currentWithRound = withRound; + currentDrawable = drawable; + invalidateParent(); + } + + public void swapBackground(Drawable drawable) { + currentDrawable = drawable; + } + + public void onDraw(Canvas canvas) { + if (previousDrawable != null) { + previousDrawable.setAlpha((int)(255 * animatedAlphaValue)); + previousDrawable.setBounds((int)progressRect.left, (int)progressRect.top, (int)progressRect.right, (int)progressRect.bottom); + previousDrawable.draw(canvas); + } + + if (!hideCurrentDrawable && currentDrawable != null) { + if (previousDrawable != null) { + currentDrawable.setAlpha((int)(255 * (1.0f - animatedAlphaValue))); + } else { + currentDrawable.setAlpha(255); + } + currentDrawable.setBounds((int)progressRect.left, (int)progressRect.top, (int)progressRect.right, (int)progressRect.bottom); + currentDrawable.draw(canvas); + } + + if (currentWithRound || previousWithRound) { + int diff = AndroidUtilities.dp(1); + if (previousWithRound) { + progressPaint.setAlpha((int)(255 * animatedAlphaValue)); + } else { + progressPaint.setAlpha(255); + } + cicleRect.set(progressRect.left + diff, progressRect.top + diff, progressRect.right - diff, progressRect.bottom - diff); + canvas.drawArc(cicleRect, -90 + radOffset, Math.max(4, 360 * animatedProgressValue), false, progressPaint); + updateAnimation(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/Scroller.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Scroller.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/Scroller.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/Scroller.java index b87b9b7c..56890bfb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/Scroller.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Scroller.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.hardware.SensorManager; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/SectionsListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/SectionsListView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java index 90898f5b..0d833ee4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/SectionsListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SectionsListView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/SeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/SeekBar.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java index 37543fc2..8efc59c2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/SeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/SizeNotifierRelativeLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierRelativeLayout.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/SizeNotifierRelativeLayout.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierRelativeLayout.java index f74e2a4c..214f320f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/SizeNotifierRelativeLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierRelativeLayout.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java new file mode 100644 index 00000000..6464ce5f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideView.java @@ -0,0 +1,52 @@ +/* + * This is the source code of Telegram for Android v. 2.0.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. + */ + +package org.telegram.ui.Components; + +import android.content.Context; +import android.os.Bundle; +import android.widget.LinearLayout; + +public class SlideView extends LinearLayout { + + public SlideView(Context context) { + super(context); + } + + public String getHeaderName() { + return ""; + } + + public void setParams(Bundle params) { + + } + + public void onBackPressed() { + + } + + public void onShow() { + + } + + public void onDestroyActivity() { + + } + + public void onNextPressed() { + + } + + public void saveStateParams(Bundle bundle) { + + } + + public void restoreStateParams(Bundle bundle) { + + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/Switch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/Switch.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java index 02e2a537..f1a940f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/Switch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/TimerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/TimerDrawable.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java index 6252ac35..7bfd4799 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/TimerDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java new file mode 100644 index 00000000..9f86fe3b --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypefaceSpan.java @@ -0,0 +1,35 @@ +/* + * This is the source code of Telegram for Android v. 1.7.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. + */ + +package org.telegram.ui.Components; + +import android.graphics.Paint; +import android.graphics.Typeface; +import android.text.TextPaint; +import android.text.style.MetricAffectingSpan; + +public class TypefaceSpan extends MetricAffectingSpan { + + private Typeface mTypeface; + + public TypefaceSpan(Typeface typeface) { + mTypeface = typeface; + } + + @Override + public void updateMeasureState(TextPaint p) { + p.setTypeface(mTypeface); + p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); + } + + @Override + public void updateDrawState(TextPaint tp) { + tp.setTypeface(mTypeface); + tp.setFlags(tp.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/TypingDotsDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/TypingDotsDrawable.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java index ff9d59c4..393482f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/TypingDotsDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.graphics.Canvas; import android.graphics.ColorFilter; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/URLSpanNoUnderline.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java similarity index 94% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/URLSpanNoUnderline.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java index c2d7b1e0..8debb521 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/URLSpanNoUnderline.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.text.TextPaint; import android.text.style.URLSpan; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/VideoSeekBarView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/VideoSeekBarView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java index f414b650..c62ed506 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/VideoSeekBarView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Views/VideoTimelineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java similarity index 99% rename from TMessagesProj/src/main/java/org/telegram/ui/Views/VideoTimelineView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java index 451a7e14..33740781 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Views/VideoTimelineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java @@ -6,7 +6,7 @@ * Copyright Nikolai Kudashov, 2013-2014. */ -package org.telegram.ui.Views; +package org.telegram.ui.Components; import android.annotation.TargetApi; import android.content.Context; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index 8afcbcb5..19e7c29d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -31,14 +31,15 @@ import org.telegram.android.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.ContactsController; import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.TLRPC; import org.telegram.android.MessagesController; import org.telegram.android.NotificationCenter; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; public class ContactAddActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -107,53 +108,6 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent ActionBarMenu menu = actionBar.createMenu(); doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); - /* - - - - - - - - - - - - - - - -*/ - fragmentView = new ScrollView(getParentActivity()); LinearLayout linearLayout = new LinearLayout(getParentActivity()); @@ -227,7 +181,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent layoutParams3.gravity = (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP; onlineTextView.setLayoutParams(layoutParams3); - firstNameField = new EditText(inflater.getContext()); + firstNameField = new EditText(getParentActivity()); firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); firstNameField.setHintTextColor(0xff979797); firstNameField.setTextColor(0xff212121); @@ -259,7 +213,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent } }); - lastNameField = new EditText(inflater.getContext()); + lastNameField = new EditText(getParentActivity()); lastNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); lastNameField.setHintTextColor(0xff979797); lastNameField.setTextColor(0xff212121); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index a2b44f87..accab286 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -32,6 +32,7 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.android.MessagesStorage; +import org.telegram.android.SecretChatHelper; import org.telegram.messenger.TLRPC; import org.telegram.android.ContactsController; import org.telegram.messenger.FileLog; @@ -47,7 +48,7 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.SectionsListView; +import org.telegram.ui.Components.SectionsListView; import java.util.ArrayList; import java.util.HashMap; @@ -268,7 +269,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter } else { if (createSecretChat) { creatingChat = true; - MessagesController.getInstance().startSecretChat(getParentActivity(), user); + SecretChatHelper.getInstance().startSecretChat(getParentActivity(), user); } else { Bundle args = new Bundle(); args.putInt("user_id", user.id); @@ -324,7 +325,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter } else { if (createSecretChat) { creatingChat = true; - MessagesController.getInstance().startSecretChat(getParentActivity(), user); + SecretChatHelper.getInstance().startSecretChat(getParentActivity(), user); } else { Bundle args = new Bundle(); args.putInt("user_id", user.id); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java index 66b77fa5..3192b2fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java @@ -32,7 +32,7 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.SectionsListView; +import org.telegram.ui.Components.SectionsListView; public class CountrySelectActivity extends BaseFragment { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 18ec6a7e..d8722289 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -41,6 +41,7 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.TLRPC; import org.telegram.android.ContactsController; import org.telegram.messenger.FileLog; @@ -53,7 +54,7 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Cells.UserCell; -import org.telegram.ui.Views.SectionsListView; +import org.telegram.ui.Components.SectionsListView; import java.util.ArrayList; import java.util.HashMap; @@ -514,7 +515,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen } private XImageSpan createAndPutChipForUser(TLRPC.User user) { - LayoutInflater lf = (LayoutInflater)ApplicationLoader.applicationContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); + LayoutInflater lf = (LayoutInflater) ApplicationLoader.applicationContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); View textView = lf.inflate(R.layout.group_create_bubble, null); TextView text = (TextView)textView.findViewById(R.id.bubble_text_view); String name = ContactsController.formatName(user.first_name, user.last_name); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index b558745e..ab3fd663 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -42,11 +42,11 @@ import org.telegram.ui.Cells.GreySectionCell; import org.telegram.ui.Cells.UserCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.AvatarUpdater; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.AvatarUpdater; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.FrameLayoutFixed; +import org.telegram.ui.Components.FrameLayoutFixed; import java.util.ArrayList; import java.util.concurrent.Semaphore; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java index f33daa47..a4a59199 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java @@ -23,12 +23,13 @@ import android.widget.LinearLayout; import android.widget.TextView; import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.TLRPC; import org.telegram.android.MessagesController; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.IdenticonDrawable; +import org.telegram.ui.Components.IdenticonDrawable; public class IdenticonActivity extends BaseFragment { private int chat_id; @@ -66,7 +67,7 @@ public class IdenticonActivity extends BaseFragment { if (encryptedChat != null) { IdenticonDrawable drawable = new IdenticonDrawable(); identiconView.setImageDrawable(drawable); - drawable.setBytes(encryptedChat.auth_key); + drawable.setEncryptedChat(encryptedChat); TLRPC.User user = MessagesController.getInstance().getUser(encryptedChat.user_id); textView.setText(Html.fromHtml(LocaleController.formatString("EncryptionKeyDescription", R.string.EncryptionKeyDescription, user.first_name, user.first_name))); } @@ -110,7 +111,7 @@ public class IdenticonActivity extends BaseFragment { return true; } LinearLayout layout = (LinearLayout)fragmentView; - WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE); + WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE); int rotation = manager.getDefaultDisplay().getRotation(); if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java index 653e39fd..7ed9dd15 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java @@ -32,6 +32,7 @@ import org.telegram.android.ContactsController; import org.telegram.android.LocaleController; import org.telegram.android.MessagesController; import org.telegram.android.NotificationCenter; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 604f0de2..4b59bcec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -9,7 +9,9 @@ package org.telegram.ui; import android.app.Activity; +import android.app.ProgressDialog; import android.content.ContentResolver; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; @@ -39,12 +41,17 @@ import android.widget.Toast; import org.telegram.android.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.ContactsController; +import org.telegram.android.MessagesController; +import org.telegram.android.MessagesStorage; import org.telegram.android.SendMessagesHelper; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; import org.telegram.android.LocaleController; import org.telegram.android.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.RPCRequest; +import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; @@ -352,11 +359,16 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa FileLog.e("tmessages", e); } } else { + boolean allowOpen = false; if (AndroidUtilities.isTablet()) { - drawerLayoutContainer.setAllowOpenDrawer(actionBarLayout.fragmentsStack.size() <= 1 && layersActionBarLayout.fragmentsStack.isEmpty()); + allowOpen = actionBarLayout.fragmentsStack.size() <= 1 && layersActionBarLayout.fragmentsStack.isEmpty(); } else { - drawerLayoutContainer.setAllowOpenDrawer(actionBarLayout.fragmentsStack.size() <= 1); + allowOpen = actionBarLayout.fragmentsStack.size() <= 1; } + if (actionBarLayout.fragmentsStack.size() == 1 && actionBarLayout.fragmentsStack.get(0) instanceof LoginActivity) { + allowOpen = false; + } + drawerLayoutContainer.setAllowOpenDrawer(allowOpen); } handleIntent(getIntent(), false, savedInstanceState != null); @@ -381,7 +393,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa documentsUrisArray = null; contactsToSend = null; - if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) { + if (UserConfig.isClientActivated() && (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) { if (intent != null && intent.getAction() != null && !restore) { if (Intent.ACTION_SEND.equals(intent.getAction())) { boolean error = false; @@ -567,39 +579,112 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa Toast.makeText(this, "Unsupported content", Toast.LENGTH_SHORT).show(); } } else if (Intent.ACTION_VIEW.equals(intent.getAction())) { - try { - Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null); - if (cursor != null) { - if (cursor.moveToFirst()) { - int userId = cursor.getInt(cursor.getColumnIndex("DATA4")); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); - push_user_id = userId; + Uri data = intent.getData(); + if (data != null) { + String username = null; + String scheme = data.getScheme(); + if (scheme != null) { + if ((scheme.equals("http") || scheme.equals("https"))) { + String host = data.getHost(); + if (host.equals("telegram.me")) { + String path = data.getPath(); + if (path != null && path.length() >= 6) { + username = path.substring(1); + } + } + } else if (scheme.equals("tg")) { + String url = data.toString(); + if (url.startsWith("tg:resolve") || url.startsWith("tg://resolve")) { + url = url.replace("tg:resolve", "tg://telegram.org").replace("tg://resolve", "tg://telegram.org"); + data = Uri.parse(url); + username = data.getQueryParameter("domain"); + } + } + } + if (username != null) { + final ProgressDialog progressDialog = new ProgressDialog(this); + progressDialog.setMessage(LocaleController.getString("Loading", R.string.Loading)); + progressDialog.setCanceledOnTouchOutside(false); + progressDialog.setCancelable(false); + + TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); + req.username = username; + final long reqId = ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(final TLObject response, final TLRPC.TL_error error) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (!LaunchActivity.this.isFinishing()) { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + if (error == null && actionBarLayout != null) { + TLRPC.User user = (TLRPC.User) response; + MessagesController.getInstance().putUser(user, false); + ArrayList users = new ArrayList(); + users.add(user); + MessagesStorage.getInstance().putUsersAndChats(users, null, false, true); + Bundle args = new Bundle(); + args.putInt("user_id", user.id); + ChatActivity fragment = new ChatActivity(args); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); + actionBarLayout.presentFragment(fragment, false, true, true); + } + } + } + }); + } + }); + + progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, LocaleController.getString("Cancel", R.string.Cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + ConnectionsManager.getInstance().cancelRpc(reqId, true); + try { + dialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + progressDialog.show(); + } else { + try { + Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null); + if (cursor != null) { + if (cursor.moveToFirst()) { + int userId = cursor.getInt(cursor.getColumnIndex("DATA4")); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); + push_user_id = userId; + } + cursor.close(); + } + } catch (Exception e) { + FileLog.e("tmessages", e); } - cursor.close(); } - } catch (Exception e) { - FileLog.e("tmessages", e); } } else if (intent.getAction().equals("org.telegram.messenger.OPEN_ACCOUNT")) { open_settings = 1; - } - } - - if (intent.getAction() != null && intent.getAction().startsWith("com.tmessages.openchat") && !restore) { - int chatId = intent.getIntExtra("chatId", 0); - int userId = intent.getIntExtra("userId", 0); - int encId = intent.getIntExtra("encId", 0); - if (chatId != 0) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); - push_chat_id = chatId; - } else if (userId != 0) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); - push_user_id = userId; - } else if (encId != 0) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); - push_enc_id = encId; - } else { - showDialogsList = true; + } else if (intent.getAction().startsWith("com.tmessages.openchat")) { + int chatId = intent.getIntExtra("chatId", 0); + int userId = intent.getIntExtra("userId", 0); + int encId = intent.getIntExtra("encId", 0); + if (chatId != 0) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); + push_chat_id = chatId; + } else if (userId != 0) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); + push_user_id = userId; + } else if (encId != 0) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); + push_enc_id = encId; + } else { + showDialogsList = true; + } } } } @@ -635,8 +720,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } pushOpened = false; isNew = false; - } - if (videoPath != null || photoPathsArray != null || sendingText != null || documentsPathsArray != null || contactsToSend != null || documentsUrisArray != null) { + } else if (videoPath != null || photoPathsArray != null || sendingText != null || documentsPathsArray != null || contactsToSend != null || documentsUrisArray != null) { if (!AndroidUtilities.isTablet()) { NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); } @@ -657,8 +741,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa rightActionBarLayout.showLastFragment(); } drawerLayoutContainer.setAllowOpenDrawer(false); - } - if (open_settings != 0) { + } else if (open_settings != 0) { actionBarLayout.presentFragment(new SettingsActivity(), false, true, true); drawerLayoutContainer.setAllowOpenDrawer(false); if (AndroidUtilities.isTablet()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index be7760ae..195ebf11 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -29,6 +29,7 @@ import com.google.android.gms.maps.model.MarkerOptions; import org.telegram.android.AndroidUtilities; import org.telegram.android.ContactsController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.android.LocaleController; import org.telegram.messenger.TLRPC; @@ -39,8 +40,8 @@ import org.telegram.messenger.R; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; import java.util.List; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index a906231c..2e0a5186 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -16,8 +16,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; -import android.graphics.Paint; -import android.graphics.Typeface; import android.os.Build; import android.os.Bundle; import android.telephony.TelephonyManager; @@ -26,10 +24,8 @@ import android.text.InputFilter; import android.text.InputType; import android.text.SpannableStringBuilder; import android.text.Spanned; -import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; -import android.text.style.MetricAffectingSpan; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; @@ -52,6 +48,7 @@ import org.telegram.android.ContactsController; import org.telegram.android.MessagesController; import org.telegram.android.MessagesStorage; import org.telegram.android.NotificationCenter; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; @@ -64,6 +61,8 @@ import org.telegram.messenger.UserConfig; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Components.SlideView; +import org.telegram.ui.Components.TypefaceSpan; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -78,6 +77,7 @@ import java.util.Timer; import java.util.TimerTask; public class LoginActivity extends BaseFragment { + private int currentViewNum = 0; private SlideView[] views = new SlideView[3]; private ProgressDialog progressDialog; @@ -418,45 +418,6 @@ public class LoginActivity extends BaseFragment { NotificationCenter.getInstance().postNotificationName(NotificationCenter.mainUserInfoChanged); } - public class SlideView extends LinearLayout { - - public SlideView(Context context) { - super(context); - } - - public String getHeaderName() { - return ""; - } - - public void setParams(Bundle params) { - - } - - public void onBackPressed() { - - } - - public void onShow() { - - } - - public void onDestroyActivity() { - - } - - public void onNextPressed() { - - } - - public void saveStateParams(Bundle bundle) { - - } - - public void restoreStateParams(Bundle bundle) { - - } - } - public class PhoneView extends SlideView implements AdapterView.OnItemSelectedListener { private EditText codeField; @@ -480,7 +441,7 @@ public class LoginActivity extends BaseFragment { setOrientation(VERTICAL); countryButton = new TextView(context); - countryButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + countryButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); countryButton.setPadding(AndroidUtilities.dp(12), AndroidUtilities.dp(10), AndroidUtilities.dp(12), 0); countryButton.setTextColor(0xff212121); countryButton.setMaxLines(1); @@ -535,7 +496,7 @@ public class LoginActivity extends BaseFragment { TextView textView = new TextView(context); textView.setText("+"); textView.setTextColor(0xff212121); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); linearLayout.addView(textView); layoutParams = (LayoutParams) textView.getLayoutParams(); layoutParams.width = LayoutParams.WRAP_CONTENT; @@ -548,7 +509,7 @@ public class LoginActivity extends BaseFragment { codeField.setTextColor(0xff212121); AndroidUtilities.clearCursorDrawable(codeField); codeField.setPadding(AndroidUtilities.dp(10), 0, 0, 0); - codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); codeField.setMaxLines(1); codeField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); @@ -624,7 +585,7 @@ public class LoginActivity extends BaseFragment { phoneField.setHintTextColor(0xff979797); phoneField.setPadding(0, 0, 0, 0); AndroidUtilities.clearCursorDrawable(phoneField); - phoneField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + phoneField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); phoneField.setMaxLines(1); phoneField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); phoneField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); @@ -693,7 +654,7 @@ public class LoginActivity extends BaseFragment { }); textView = new TextView(context); - textView.setText(LocaleController.getString("StartText", R.string.StartText)); + textView.setText(LocaleController.getString("ChangePhoneHelp", R.string.ChangePhoneHelp)); textView.setTextColor(0xff757575); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setGravity(Gravity.LEFT); @@ -828,7 +789,7 @@ public class LoginActivity extends BaseFragment { if (countryState == 1) { needShowAlert(LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); return; - } else if (countryState == 2) { + } else if (countryState == 2 && !BuildVars.DEBUG_VERSION) { needShowAlert(LocaleController.getString("WrongCountry", R.string.WrongCountry)); return; } @@ -951,27 +912,6 @@ public class LoginActivity extends BaseFragment { private boolean nextPressed = false; private String lastError = ""; - public class TypefaceSpan extends MetricAffectingSpan { - - private Typeface mTypeface; - - public TypefaceSpan(Typeface typeface) { - mTypeface = typeface; - } - - @Override - public void updateMeasureState(TextPaint p) { - p.setTypeface(mTypeface); - p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); - } - - @Override - public void updateDrawState(TextPaint tp) { - tp.setTypeface(mTypeface); - tp.setFlags(tp.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); - } - } - public LoginActivitySmsView(Context context) { super(context); @@ -997,7 +937,7 @@ public class LoginActivity extends BaseFragment { AndroidUtilities.clearCursorDrawable(codeField); codeField.setHintTextColor(0xff979797); codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); codeField.setInputType(InputType.TYPE_CLASS_PHONE); codeField.setMaxLines(1); codeField.setPadding(0, 0, 0, 0); @@ -1440,7 +1380,7 @@ public class LoginActivity extends BaseFragment { AndroidUtilities.clearCursorDrawable(firstNameField); firstNameField.setHint(LocaleController.getString("FirstName", R.string.FirstName)); firstNameField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); firstNameField.setMaxLines(1); firstNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_WORDS); addView(firstNameField); @@ -1468,7 +1408,7 @@ public class LoginActivity extends BaseFragment { lastNameField.setTextColor(0xff212121); AndroidUtilities.clearCursorDrawable(lastNameField); lastNameField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - lastNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + lastNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); lastNameField.setMaxLines(1); lastNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_WORDS); addView(lastNameField); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index 844a63fe..7443e4c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -26,6 +26,7 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; import org.telegram.messenger.TLRPC; import org.telegram.android.MessageObject; @@ -34,7 +35,7 @@ import org.telegram.android.NotificationCenter; import org.telegram.messenger.R; import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.ActionBar.ActionBar; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; import java.util.ArrayList; @@ -122,6 +123,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { + if (i < 0 || i >= messages.size()) { + return; + } PhotoViewer.getInstance().setParentActivity(getParentActivity()); PhotoViewer.getInstance().openPhoto(messages, i, MediaActivity.this); } @@ -331,7 +335,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No obs.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); + WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); int rotation = manager.getDefaultDisplay().getRotation(); if (AndroidUtilities.isTablet()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index cfdeee9b..ace44bad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -31,6 +31,7 @@ import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.android.NotificationsController; import org.telegram.android.NotificationCenter; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.ConnectionsManager; @@ -46,7 +47,7 @@ import org.telegram.ui.Cells.TextColorCell; import org.telegram.ui.Cells.TextDetailSettingsCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.ColorPickerView; +import org.telegram.ui.Components.ColorPickerView; public class NotificationsSettingsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListView listView; @@ -660,7 +661,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } else if (i == eventsSectionRow) { ((HeaderCell) view).setText(LocaleController.getString("Events", R.string.Events)); } else if (i == otherSectionRow) { - ((HeaderCell) view).setText(LocaleController.getString("PhoneOther", R.string.PhoneOther)); + ((HeaderCell) view).setText(LocaleController.getString("NotificationsOther", R.string.NotificationsOther)); } else if (i == resetSectionRow) { ((HeaderCell) view).setText(LocaleController.getString("Reset", R.string.Reset)); } @@ -761,7 +762,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif int minutes = preferences.getInt("repeat_messages", 60); String value; if (minutes == 0) { - value = LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever); + value = LocaleController.getString("RepeatNotificationsNever", R.string.RepeatNotificationsNever); } else if (minutes < 60) { value = LocaleController.formatPluralString("Minutes", minutes); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index 3e2ea05b..5d0681e7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -28,6 +28,7 @@ import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.android.MediaController; import org.telegram.android.NotificationCenter; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.android.MessageObject; @@ -35,7 +36,7 @@ import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.BackupImageView; import java.util.ArrayList; import java.util.HashMap; @@ -401,7 +402,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen return; } int position = listView.getFirstVisiblePosition(); - WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); + WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); int rotation = manager.getDefaultDisplay().getRotation(); int columnsCount = 2; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index e6c74915..4d32b700 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -48,6 +48,7 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.ContactsController; import org.telegram.android.MessagesStorage; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; @@ -67,7 +68,7 @@ import org.telegram.ui.AnimationCompat.ViewProxy; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.Views.ClippingImageView; +import org.telegram.ui.Components.ClippingImageView; import org.telegram.android.ImageReceiver; import java.io.File; @@ -692,6 +693,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ActionBarMenu menu = actionBar.createMenu(); menuItem = menu.addItem(0, R.drawable.ic_ab_other); + menuItem.setNeedOffset(false); menuItem.addSubItem(gallery_menu_save, LocaleController.getString("SaveToGallery", R.string.SaveToGallery), 0); menuItem.addSubItem(gallery_menu_showall, LocaleController.getString("ShowAllMedia", R.string.ShowAllMedia), 0); @@ -927,7 +929,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat layoutParams.height = AndroidUtilities.dp(46); layoutParams.gravity = Gravity.RIGHT; layoutParams.rightMargin = AndroidUtilities.dp(10); - WindowManager manager = (WindowManager)ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); + WindowManager manager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); int rotation = manager.getDefaultDisplay().getRotation(); if (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90) { layoutParams.topMargin = AndroidUtilities.dp(48); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index f1acb8a5..5c7b2226 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -37,6 +37,7 @@ import org.telegram.android.MediaController; import org.telegram.android.MessagesController; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.NotificationsController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; @@ -47,15 +48,16 @@ import org.telegram.android.MessageObject; import org.telegram.android.PhotoObject; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.BackupImageView; -import org.telegram.ui.Views.ChatActivityEnterView; -import org.telegram.ui.Views.FrameLayoutFixed; -import org.telegram.ui.Views.PopupAudioView; -import org.telegram.ui.Views.TypingDotsDrawable; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.ChatActivityEnterView; +import org.telegram.ui.Components.FrameLayoutFixed; +import org.telegram.ui.Components.PopupAudioView; +import org.telegram.ui.Components.TypingDotsDrawable; import java.io.File; import java.util.ArrayList; +import java.util.Locale; public class PopupNotificationActivity extends Activity implements NotificationCenter.NotificationCenterDelegate { @@ -282,7 +284,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC chatActivityEnterView.setContainerView(this, findViewById(R.id.chat_layout)); - PowerManager pm = (PowerManager)ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE); + PowerManager pm = (PowerManager) ApplicationLoader.applicationContext.getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "screen"); wakeLock.setReferenceCounted(false); @@ -490,7 +492,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC } ViewGroup view = null; MessageObject messageObject = NotificationsController.getInstance().popupMessages.get(num); - if (messageObject.type == 1) { + if (messageObject.type == 1 || messageObject.type == 4) { if (imageViews.size() > 0) { view = imageViews.get(0); imageViews.remove(0); @@ -510,34 +512,45 @@ public class PopupNotificationActivity extends Activity implements NotificationC TextView messageText = (TextView)view.findViewById(R.id.message_text); BackupImageView imageView = (BackupImageView) view.findViewById(R.id.message_image); imageView.imageReceiver.setAspectFit(true); - PhotoObject currentPhotoObject = PhotoObject.getClosestImageWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); - boolean photoSet = false; - if (currentPhotoObject != null) { - boolean photoExist = true; - if (messageObject.type == 1) { - File cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); - if (!cacheFile.exists()) { - photoExist = false; + + if (messageObject.type == 1) { + PhotoObject currentPhotoObject = PhotoObject.getClosestImageWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); + boolean photoSet = false; + if (currentPhotoObject != null) { + boolean photoExist = true; + if (messageObject.type == 1) { + File cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); + if (!cacheFile.exists()) { + photoExist = false; + } } - } - if (photoExist || MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)) { - imageView.setImage(currentPhotoObject.photoOwner.location, "100_100", messageObject.imagePreview, currentPhotoObject.photoOwner.size); - photoSet = true; - } else { - if (messageObject.imagePreview != null) { - imageView.setImageBitmap(messageObject.imagePreview); + if (photoExist || MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)) { + imageView.setImage(currentPhotoObject.photoOwner.location, "100_100", messageObject.imagePreview, currentPhotoObject.photoOwner.size); photoSet = true; + } else { + if (messageObject.imagePreview != null) { + imageView.setImageBitmap(messageObject.imagePreview); + photoSet = true; + } } } - } - if (!photoSet) { - imageView.setVisibility(View.GONE); - messageText.setVisibility(View.VISIBLE); - messageText.setTextSize(TypedValue.COMPLEX_UNIT_SP, MessagesController.getInstance().fontSize); - messageText.setText(messageObject.messageText); - } else { - imageView.setVisibility(View.VISIBLE); + if (!photoSet) { + imageView.setVisibility(View.GONE); + messageText.setVisibility(View.VISIBLE); + messageText.setTextSize(TypedValue.COMPLEX_UNIT_SP, MessagesController.getInstance().fontSize); + messageText.setText(messageObject.messageText); + } else { + imageView.setVisibility(View.VISIBLE); + messageText.setVisibility(View.GONE); + } + } else if (messageObject.type == 4) { messageText.setVisibility(View.GONE); + messageText.setText(messageObject.messageText); + imageView.setVisibility(View.VISIBLE); + double lat = messageObject.messageOwner.media.geo.lat; + double lon = messageObject.messageOwner.media.geo._long; + String currentUrl = 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); + imageView.setImage(currentUrl, null, null); } } else if (messageObject.type == 2) { PopupAudioView cell = null; @@ -585,6 +598,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC }); } TextView messageText = (TextView)view.findViewById(R.id.message_text); + messageText.setTag(301); messageText.setTextSize(TypedValue.COMPLEX_UNIT_SP, MessagesController.getInstance().fontSize); messageText.setText(messageObject.messageText); } @@ -1006,7 +1020,12 @@ public class PopupNotificationActivity extends Activity implements NotificationC int count = messageContainer.getChildCount(); for (int a = 0; a < count; a++) { View view = messageContainer.getChildAt(a); - view.invalidate(); + if ((Integer)view.getTag() == 1) { + TextView textView = (TextView)view.findViewWithTag(301); + if (textView != null) { + textView.invalidate(); + } + } } } } else if (id == NotificationCenter.contactsDidLoaded) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 14ad761c..71921438 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -35,7 +35,9 @@ import org.telegram.android.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.LocaleController; import org.telegram.android.MessagesStorage; +import org.telegram.android.SecretChatHelper; import org.telegram.android.SendMessagesHelper; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.TLRPC; import org.telegram.android.ContactsController; @@ -57,11 +59,11 @@ import org.telegram.ui.Cells.UserCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.AvatarUpdater; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.AvatarUpdater; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.IdenticonDrawable; +import org.telegram.ui.Components.IdenticonDrawable; import java.util.ArrayList; import java.util.Collections; @@ -459,7 +461,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override public void onClick(DialogInterface dialogInterface, int i) { creatingChat = true; - MessagesController.getInstance().startSecretChat(getParentActivity(), MessagesController.getInstance().getUser(user_id)); + SecretChatHelper.getInstance().startSecretChat(getParentActivity(), MessagesController.getInstance().getUser(user_id)); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -484,7 +486,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else if (i == 1) { if(Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) { - android.text.ClipboardManager clipboard = (android.text.ClipboardManager)ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + android.text.ClipboardManager clipboard = (android.text.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); clipboard.setText("+" + user.phone); } else { android.content.ClipboardManager clipboard = (android.content.ClipboardManager)ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); @@ -766,6 +768,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. 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(); + } + } } else if (chat_id != 0) { if ((mask & MessagesController.UPDATE_MASK_CHAT_AVATAR) != 0 || (mask & MessagesController.UPDATE_MASK_CHAT_NAME) != 0 || (mask & MessagesController.UPDATE_MASK_CHAT_MEMBERS) != 0 || (mask & MessagesController.UPDATE_MASK_STATUS) != 0) { updateOnlineCount(); @@ -1283,7 +1290,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (i == settingsKeyRow) { IdenticonDrawable identiconDrawable = new IdenticonDrawable(); TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat((int)(dialog_id >> 32)); - identiconDrawable.setBytes(encryptedChat.auth_key); + identiconDrawable.setEncryptedChat(encryptedChat); textCell.setTextAndValueDrawable(LocaleController.getString("EncryptionKey", R.string.EncryptionKey), identiconDrawable); } } else if (type == 4) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index a56eab28..e569eedc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -30,6 +30,7 @@ import android.widget.ListView; import org.telegram.android.AndroidUtilities; import org.telegram.android.MessagesController; import org.telegram.android.MessagesStorage; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLog; import org.telegram.android.LocaleController; @@ -43,8 +44,8 @@ import org.telegram.ui.Cells.TextColorCell; import org.telegram.ui.Cells.TextDetailSettingsCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.ColorPickerView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.ColorPickerView; public class ProfileNotificationsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index b7e1bfc6..b67b3c5f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -42,6 +42,7 @@ import org.telegram.android.AndroidUtilities; import org.telegram.android.ContactsController; import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.android.MediaController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; import org.telegram.android.LocaleController; import org.telegram.messenger.FileLoader; @@ -70,11 +71,11 @@ import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.Views.AvatarDrawable; -import org.telegram.ui.Views.AvatarUpdater; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.AvatarUpdater; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.NumberPicker; +import org.telegram.ui.Components.NumberPicker; import java.io.File; import java.util.ArrayList; @@ -585,6 +586,8 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter showAlertDialog(builder); } else if (i == usernameRow) { presentFragment(new ChangeUsernameActivity()); + } else if (i == numberRow) { + presentFragment(new ChangePhoneHelpActivity()); } } }); @@ -986,7 +989,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter @Override public boolean isEnabled(int i) { - return i == textSizeRow || i == enableAnimationsRow || i == notificationRow || i == backgroundRow || + return i == textSizeRow || i == enableAnimationsRow || i == notificationRow || i == backgroundRow || i == numberRow || i == askQuestionRow || i == sendLogsRow || i == sendByEnterRow || i == privacyRow || i == wifiDownloadRow || i == mobileDownloadRow || i == clearLogsRow || i == roamingDownloadRow || i == languageRow || i == usernameRow || i == switchBackendButtonRow || i == telegramFaqRow || i == contactsSortRow || i == contactsReimportRow || i == saveToGalleryRow; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java index 4c9aca48..63d0da9c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java @@ -43,14 +43,15 @@ import com.googlecode.mp4parser.util.Path; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.android.MediaController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.VideoSeekBarView; -import org.telegram.ui.Views.VideoTimelineView; +import org.telegram.ui.Components.VideoSeekBarView; +import org.telegram.ui.Components.VideoTimelineView; import java.io.File; import java.util.List; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java index 50b3b8fc..5f0c6a45 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java @@ -32,6 +32,7 @@ import android.widget.ProgressBar; import org.telegram.android.AndroidUtilities; import org.telegram.android.ImageLoader; import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.messenger.ConnectionsManager; @@ -45,9 +46,9 @@ import org.telegram.messenger.Utilities; import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; -import org.telegram.ui.Views.BackupImageView; +import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.ActionBar.BaseFragment; -import org.telegram.ui.Views.HorizontalListView; +import org.telegram.ui.Components.HorizontalListView; import java.io.File; import java.io.FileOutputStream; diff --git a/TMessagesProj/src/main/res/drawable-hdpi/phone_change.png b/TMessagesProj/src/main/res/drawable-hdpi/phone_change.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd3a8e4bbef4bbee3e6f54714d3d08dd6a3f97a GIT binary patch literal 3363 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 L-n1)}od^B{0wIbw literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/phone_change.png b/TMessagesProj/src/main/res/drawable-mdpi/phone_change.png new file mode 100644 index 0000000000000000000000000000000000000000..99e036d89d046faf26f0336459c2bc8beb8cd2e1 GIT binary patch literal 2552 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/phone_change.png b/TMessagesProj/src/main/res/drawable-xhdpi/phone_change.png new file mode 100644 index 0000000000000000000000000000000000000000..770c9bd67225888cd5724ce728b9008b4703091a GIT binary patch literal 4188 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 Rsf;J=dfG->6&iLC{{^*)ooxUB literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/layout-ar/location_view_layout.xml b/TMessagesProj/src/main/res/layout-ar/location_view_layout.xml index b82488ea..a39c6a5e 100644 --- a/TMessagesProj/src/main/res/layout-ar/location_view_layout.xml +++ b/TMessagesProj/src/main/res/layout-ar/location_view_layout.xml @@ -19,7 +19,7 @@ android:background="@drawable/location_panel" android:id="@+id/location_bottom_view"> - - - + - - @@ -131,7 +131,7 @@ android:enabled="false" android:layout_gravity="bottom|right"/> - - + - + - \ No newline at end of file + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/layout/location_view_layout.xml b/TMessagesProj/src/main/res/layout/location_view_layout.xml index 9c34b9fe..d89e26eb 100644 --- a/TMessagesProj/src/main/res/layout/location_view_layout.xml +++ b/TMessagesProj/src/main/res/layout/location_view_layout.xml @@ -19,7 +19,7 @@ android:background="@drawable/location_panel" android:id="@+id/location_bottom_view"> - - diff --git a/TMessagesProj/src/main/res/layout/media_video_layout.xml b/TMessagesProj/src/main/res/layout/media_video_layout.xml index 810f77f3..17de40a5 100644 --- a/TMessagesProj/src/main/res/layout/media_video_layout.xml +++ b/TMessagesProj/src/main/res/layout/media_video_layout.xml @@ -3,7 +3,7 @@ android:layout_width="100dp" android:layout_height="100dp"> - diff --git a/TMessagesProj/src/main/res/layout/photo_picker_album_layout.xml b/TMessagesProj/src/main/res/layout/photo_picker_album_layout.xml index 1773bc96..1f966a1f 100644 --- a/TMessagesProj/src/main/res/layout/photo_picker_album_layout.xml +++ b/TMessagesProj/src/main/res/layout/photo_picker_album_layout.xml @@ -4,7 +4,7 @@ android:layout_height="100dp" android:layout_gravity="top"> - diff --git a/TMessagesProj/src/main/res/layout/photo_picker_photo_layout.xml b/TMessagesProj/src/main/res/layout/photo_picker_photo_layout.xml index a0a6f914..8c1440e1 100644 --- a/TMessagesProj/src/main/res/layout/photo_picker_photo_layout.xml +++ b/TMessagesProj/src/main/res/layout/photo_picker_photo_layout.xml @@ -4,7 +4,7 @@ android:layout_height="100dp" android:layout_gravity="top"> - diff --git a/TMessagesProj/src/main/res/layout/popup_image_layout.xml b/TMessagesProj/src/main/res/layout/popup_image_layout.xml index f9e1beb9..e1fbaccd 100644 --- a/TMessagesProj/src/main/res/layout/popup_image_layout.xml +++ b/TMessagesProj/src/main/res/layout/popup_image_layout.xml @@ -7,7 +7,7 @@ android:padding="10dp" android:background="@drawable/list_selector"> - - @@ -65,7 +65,7 @@ android:textCursorDrawable="@null" android:textColor="#000000"/> - - + - + - \ No newline at end of file + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/layout/settings_color_dialog_layout.xml b/TMessagesProj/src/main/res/layout/settings_color_dialog_layout.xml index 07548074..981b72c3 100644 --- a/TMessagesProj/src/main/res/layout/settings_color_dialog_layout.xml +++ b/TMessagesProj/src/main/res/layout/settings_color_dialog_layout.xml @@ -5,7 +5,7 @@ android:layout_height="match_parent" android:layout_gravity="center"> - - - - - لا يوجد وسائط حفظ في الجهاز تعديل الاسم - Priority - Default - Low - High - Max - Repeat Notifications + الأولوية + افتراضي + منخفض + مرتفع + القصوى + للأبد + إعادة الإشعارات + يمكنك تغيير رقم تيليجرام الخاص بك هنا. حسابك وجميع بياناتك التي في السحاب بما فيها رسائلك، الوسائط، جهات الاتصال وغيرها سيتم نقلها للرقم الجديد.هام:]]> جميع جهات الاتصال الخاصة بك في تيليجرام سيضاف لها رقمك الجديد]]>، في حال تواجد بها رقمك القديم ولم تقم بحظره في تيليجرام. + جميع جهات الاتصال الخاصة بك في تيليجرام سيضاف لها رقمك الجديد، في حال تواجد بها رقمك القديم ولم تقم بحظره في تيليجرام. + تغيير الرقم + الرقم الجديد + سيتم إرسال رسالة قصيرة تحتوي على رمز التفعيل الخاص إلى رقمك الجديد. + الرقم %1$s لديه حساب تيليجرام مسبقًا. يرجى حذف هذا الحساب قبل محاولة تغيير رقمك. + آخر لا توجد وسائط بعد diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index 04aa57a8..3f29a8f9 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -137,7 +137,7 @@ %1$s hat dich aus der Gruppe %2$s entfernt %1$s hat die Gruppe %2$s verlassen %1$s benutzt jetzt Telegram! - %1$s,\nWir haben eine Anmeldung von einem neuen Gerät am %2$s festgestellt.\n\nGerät: %3$s\nStandort: %4$s\n\nWenn du das nicht selbst gewesen bist, melde alle anderen Sitzungen in den Telegram Einstellungen unverzüglich ab.\n\nMit freundlichen Grüßen,\nDas Telegram Team + %1$s,\nWir haben eine Anmeldung von einem neuen Gerät am %2$s festgestellt.\n\nGerät: %3$s\nStandort: %4$s\n\nWenn du das nicht selbst gewesen bist, melde alle anderen Sitzungen in den Telegram Einstellungen unverzüglich ab.\n\nMit freundlichen Grüßen,\nDein Telegram Team %1$s hat das Profilbild geändert Beantworten %1$s antworten @@ -276,8 +276,16 @@ Standard Niedrig Hoch - Max - Wiederholen Benachrichtigungen + Max. + Niemals + Erneut benachrichtigen + Du kannst deine Telefonnummer hier ändern. Dein Konto und alle Daten in der Telegram-Cloud, also Nachrichten, Medien, Kontakte, etc. werden auf das neue Konto übertragen.\n\nWichtig:]]> Alle deine Kontakte erhalten deine neue Nummer]]> ihrem Telefonbuch hinzugefügt, sofern sie deine alte Nummer gespeichert hatten und du sie nicht blockiert hattest. + Deinen Kontakten wird deine neue Nummer ihrem Telefonbuch hinzugefügt, sofern sie deine alte Nummer gespeichert hatten und du sie nicht blockiert hattest. + NUMMER ÄNDERN + Neue Nummer + Der Bestätigungscode kommt per SMS an deine neue Nummer. + Die Telefonnummer %1$s ist bereits ein Telegram Konto. Bitte lösche es, bevor du mit der Übertragung auf das neue Konto startest. + Sonstige Noch keine geteilten Medien vorhanden diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 2f4b1ca5..cbd2463b 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -137,7 +137,7 @@ %1$s te expulsó del grupo %2$s %1$s dejó el grupo %2$s ¡%1$s se unió a Telegram! - %1$s,\nDetectamos un inicio de sesión en tu cuenta desde un nuevo dispositivo, el %2$s\n\nDispositivo: %3$s\nUbicación: %4$s\n\nSi no eras tú, puedes ir a Ajustes - Cerrar todas las otras sesiones.\n\nAtentamente,\nEl equipo de Telegram + %1$s,\nDetectamos un inicio de sesión en tu cuenta desde un nuevo dispositivo, el %2$s\n\nDispositivo: %3$s\nUbicación: %4$s\n\nSi no eras tú, puedes ir a Ajustes - Privacidad y seguirdad - Cerrar todas las otras sesiones.\n\nAtentamente,\nEl equipo de Telegram %1$s actualizó su foto de perfil Responder Responder a %1$s @@ -277,7 +277,15 @@ Baja Alta Máxima + Nunca Repetir notificaciones + Puedes cambiar tu número de Telegram aquí. Tu cuenta y todos tus datos de la nube — mensajes, archivos, grupos, contactos, etc., se moverán al nuevo número.\n\nImportante:]]> Todos tus contactos de Telegram tendrán tu nuevo número]]> añadido a sus agendas de contactos, siempre que hayan tenido tu número viejo y no los hayas bloqueado en Telegram. + Todos tus contactos de Telegram tendrán tu número nuevo añadido a sus agendas de contactos, siempre que hayan tenido tu número viejo y no los hayas bloqueado en Telegram. + CAMBIAR NÚMERO + Nuevo número + Enviaremos un SMS con el código de confirmación a tu nuevo número. + El número %1$s ya está vinculado a una cuenta de Telegram. Por favor, elimina esa cuenta antes de migrar al nuevo número. + Otras Aún no hay fotos ni vídeos diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 421a1c6f..8587d8f4 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -133,11 +133,11 @@ %1$s ha modificato il nome del gruppo %2$s %1$s ha modificato la foto del gruppo %2$s %1$s ha invitato %3$s nel gruppo %2$s - %1$s ha rimosso %3$s dal gruppo %2$s - %1$s ti ha rimosso dal gruppo %2$s + %1$s ha espulso %3$s dal gruppo %2$s + %1$s ti ha espulso dal gruppo %2$s %1$s ha lasciato il gruppo %2$s %1$s ha iniziato a usare Telegram! - %1$s,\nAbbiamo rilevato un accesso al tuo account da un nuovo dispositivo %2$s\n\nDispositivo: %3$s\nPosizione: %4$s\n\nSe non sei stato tu, puoi andare su Impostazioni - Termina tutte le sessioni.\n\nGrazie,\nil team di Telegram + %1$s,\nAbbiamo rilevato un accesso al tuo account da un nuovo dispositivo %2$s\n\nDispositivo: %3$s\nPosizione: %4$s\n\nSe non sei stato tu, puoi andare su Impostazioni - Privacy e Sicurezza - Termina tutte le sessioni.\n\nGrazie,\nil team di Telegram %1$s ha aggiornato la foto del profilo Rispondi Rispondi a %1$s @@ -277,7 +277,15 @@ Bassa Alta Massima + Mai Ripeti Notifiche + Puoi cambiare il tuo numero di telefono qui. Il tuo account e tutti i tuoi dati cloud — messaggi, file, contatti, etc. saranno spostati sul nuovo numero.\n\nImportante:]]> a tutti i tuoi contatti di Telegram verrà aggiunto il tuo nuovo numero]]> ai contatti, purché abbiano il tuo vecchio numero e tu non li abbia bloccati su Telegram. + Tutti i tuoi contatti Telegram avranno il tuo nuovo numero tra i loro contatti, purché abbiano il tuo vecchio numero e tu non li abbia bloccati su Telegram. + CAMBIA NUMERO + Nuovo numero + Invieremo un SMS con un codice di conferma al tuo nuovo numero. + Il numero %1$s è già connesso a un account Telegram. Per favore elimina quell\'account prima di migrare ad un nuovo numero. + Altro Nessun media condiviso @@ -354,21 +362,21 @@ Imposta OK - un1 ha rimosso un2 + un1 ha espulso un2 un1 ha lasciato il gruppo un1 ha aggiunto un2 un1 ha rimosso la foto del gruppo un1 ha cambiato la foto del gruppo un1 ha cambiato il nome del gruppo in un2 un1 ha creato il gruppo - Hai rimosso un2 + Hai espulso un2 Hai lasciato il gruppo Hai aggiunto un2 Hai rimosso la foto del gruppo Hai cambiato la foto del gruppo Hai cambiato il nome del gruppo in un2 Hai creato il gruppo - un1 ti ha rimosso + un1 ti ha espulso un1 ti ha aggiunto Questo messaggio non è supportato sulla tua versione di Telegram. Aggiorna l\'applicazione per visualizzarlo: http://telegram.org/update Foto @@ -378,8 +386,8 @@ File Audio Tu - Hai catturato la schermata! - un1 ha catturato la schermata! + Hai fatto uno screenshot! + un1 ha fatto uno screenshot! Numero di telefono non valido Codice scaduto, effettua di nuovo l\'accesso diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index f5dc781d..bd528a8a 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -277,7 +277,15 @@ 낮음 높음 최우선 - Repeat Notifications + 사용 안 함 + 알림 반복 + 텔레그램 가입 번호를 여기서 변경할 수 있습니다. 계정 및 클라우드에 저장된 메시지나 사진/동영상, 대화상대 등이 새 번호로 이동됩니다.\n\n주의:]]> 회원님의 옛 전화번호를 알고 있으며 회원님이 차단한 대화상대가 아니라면, 텔레그램 대화상대 모두의 연락처에 회원님의 새 전화번호]]>가 추가됩니다. + 회원님의 옛 전화번호를 알고 있으며 회원님이 차단한 대화상대가 아니라면, 텔레그램 대화상대 모두의 연락처에 회원님의 새 전화번호가 추가됩니다. + 번호 변경 + 새 번호 + 인증코드 메시지를 새 번호로 전송하겠습니다. + The number %1$s is already connected to a Telegram account. Please delete that account before migrating to the new number. + 기타 공유한 미디어가 없습니다 diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index 37a238a2..b123ab9c 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -14,9 +14,9 @@ Onjuist landnummer Je code - We hebben een sms met een activatiecode verzonden naar je telefoon + We hebben een sms-bericht met een activatiecode verzonden naar je telefoon We bellen je over %1$d:%2$02d - We bellen je… + We bellen je Code Verkeerd nummer? Geen code ontvangen? @@ -33,24 +33,24 @@ Nieuwe groep gisteren Geen resultaten - Nog geen gesprekken… + Nog geen chats Begin een gesprek door op de\nopstellen-knop rechtsboven te drukken\nof druk op de menu knop voor meer opties. - Wachten op netwerk… - Verbinden… - Bijwerken… + Wachten op netwerk + Verbinden + Bijwerken Nieuwe geheime chat - Wachten tot %s online komt… + Wachten tot %s online komt Geheime chat geannuleerd - Encryptiesleutels uitwisselen… - Geheime chat gestart met %s + Encryptiesleutels uitwisselen + %s neemt deel aan je geheime chat. Toegevoegd aan de geheime chat. Geschiedenis wissen - Verwijderen en verlaten - Gesprek verwijderen + Verwijder en verlaat + Chat verwijderen Verwijderd account - Kies een gesprek + Kies een chat Druk en houd ingedrukt - %1$s gebruikt een oudere versie van Telegram, dus worden geheime foto\'s weergegeven in de compatibiliteitsmodus.\n\nZodra %2$s Telegram updatet werken foto\'s met timers voor 1 minuut of minder in de \'Druk en houd ingedrukt\'-modus en krijg je een bericht wanneer de andere partij een schermafbeelding maakt. + %1$s gebruikt een oudere versie van Telegram, dus worden geheime foto\'s weergegeven in de compatibiliteitsmodus.\n\nZodra %2$s Telegram updatet werken foto\'s met timers voor 1 minuut of minder in de \'Druk en houd ingedrukt\'-modus en krijg je een bericht wanneer de andere partij een schermafdruk maakt. BERICHTEN Nieuwe verzendlijst @@ -63,27 +63,27 @@ Vrij: %1$s van %2$s Onbekende fout Toegangsfout - Nog geen bestanden… + Nog geen bestanden Bestanden mogen maximaal %1$s zijn Geen opslagmedium gevonden USB-overdracht actief Interne opslag Externe opslag - Systeem map + Systeemmap SD-kaart Map onzichtbaar - aan het typen… - is aan het typen… - zijn aan het typen… + aan het typen + is aan het typen + zijn aan het typen Heb je een vraag\nover Telegram? Foto maken Galerij Locatie Video - Document - Nog geen berichten hier… + Bestand + Nog geen berichten Doorgestuurd bericht Van Niets recents @@ -94,14 +94,14 @@ %s heeft je uitgenodigd voor een geheime chat. Je hebt %s uitgenodigd voor een geheime chat. Geheime chat functies: - End-to-end encryptie + End-to-end-encryptie Geen serveropslag Zelfvernietigingstimers Doorstuurbescherming Je bent verwijderd uit deze groep Je hebt deze groep verlaten Deze groep verwijderen - Verwijder dit gesprek + Chat verwijderen SLEEP OM TE ANNULEREN Opslaan in Downloads Vertaling toepassen @@ -119,7 +119,7 @@ %1$s heeft je een video gestuurd %1$s heeft een contact met je gedeeld %1$s heeft je een locatie gestuurd - %1$s heeft je een document gestuurd + %1$s heeft je een bestand gestuurd %1$s heeft je een geluidsbestand gestuurd %1$s @ %2$s: %3$s %1$s heeft een bericht gestuurd naar de groep %2$s @@ -127,7 +127,7 @@ %1$s heeft een video gestuurd naar de groep %2$s %1$s heeft een contact gedeeld met de groep %2$s %1$s heeft een locatie gestuurd naar de groep %2$s - %1$s heeft een document gestuurd naar de groep %2$s + %1$s heeft een bestand gestuurd naar de groep %2$s %1$s heeft een geluidsbestand gestuurd naar de groep %2$s %1$s heeft je uitgenodigd voor de groep %2$s %1$s heeft de naam van de groep %2$s gewijzigd @@ -137,14 +137,14 @@ %1$s heeft je verwijderd uit de groep %2$s %1$s heeft de groep %2$s verlaten %1$s heeft nu Telegram! - %1$s,\nEr is op je account ingelogd vanaf een nieuw apparaat op %2$s\n\nApparaat: %3$s\nLocatie: %4$s\n\nAls jij dit niet was, kun je alle sessies beëindigen via Instellingen – Beëindig alle andere sessies.\n\nBedankt,\nHet Telegram-team + %1$s,\nEr is op je account ingelogd vanaf een nieuw apparaat op %2$s\n\nApparaat: %3$s\nLocatie: %4$s\n\nAls jij dit niet was, kun je alle sessies beëindigen via Instellingen - Privacy en veiligheid - Beëindig alle andere sessies.\n\nBedankt,\nHet Telegram-team %1$s heeft zijn/haar profielfoto gewijzigd Antwoord Antwoord op %1$s Antwoord op %1$s %1$s %2$s - Kies een contact + Contact kiezen Nog geen contacten Hey! Zullen we overstappen op Telegram? http://telegram.org/dl2 vandaag om @@ -160,8 +160,8 @@ lang geleden gezien Nieuw bericht - Bericht verzenden naar… - Groepsnaam... + Bericht versturen naar + Groepsnaam Groepsnaam %1$d/%2$d deelnemers @@ -175,9 +175,9 @@ Delen Toevoegen Contact toevoegen - Blokkeren - Bewerken - Verwijderen + Blokkeer + Wijzig + Verwijder Thuis Mobiel Werk @@ -188,7 +188,7 @@ Encryptiesleutel Zelfvernietigingstimer Uit - Dit is een weergave van de encryptiesleutel voor deze geheime chat met ]]>%1$s]]>.
]]>Als deze afbeelding er bij ]]>%2$s]]> hetzelfde uitziet, is jullie gesprek 200%% beveiligd.
]]>Lees meer op telegram.org.
+ Dit is een weergave van de encryptiesleutel voor deze geheime chat met ]]>%1$s]]>.
]]>Als deze afbeelding er bij ]]>%2$s]]> hetzelfde uitziet, is jullie chat 200%% beveiligd.
]]>Lees meer op telegram.org.
Onbekend Info Telefoon @@ -200,17 +200,17 @@ Je naam moet minimaal 5 tekens hebben. Je naam mag niet langer zijn dan 32 tekens. Sorry, begincijfers zijn niet toegestaan. - Je kan een gebruikersnaam kiezen voor ]]>Telegram]]>. Hiermee kunnen anderen je vinden en contact met je opnemen zonder je telefoonnummer te weten.
]]>Je mag ]]>a–z]]>, ]]>0–9]]> en liggend streepje gebruiken. De minimale lengte is ]]>5]]> tekens.
+ Je kan een gebruikersnaam kiezen voor ]]>Telegram]]>. Hiermee kunnen anderen je vinden en contact met je opnemen zonder je telefoonnummer te weten.
]]>Je mag ]]>a–z]]>, ]]>0–9]]> en liggend streepje gebruiken. De minimale lengte is ]]>5]]> tekens.
Gebruikersnaam controleren. %1$s is beschikbaar. Geen Er is een fout opgetreden. - Alle meldingsinstellingen herstellen + Meldingen gereset Tekstgrootte berichten Een vraag stellen Animaties - Deblokkeren + Deblokkeer Houd een gebruiker ingedrukt om hem/haar te deblokkeren. Geen geblokkeerde gebruikers Berichtmeldingen @@ -224,7 +224,7 @@ Trillen Voorvertoningen Resetten - Alle meldingen resetten + Meldingen resetten Aangepaste meldingsinstellingen wissen voor contacten en groepen. Meldingen en geluiden Geblokkeerde gebruikers @@ -234,7 +234,7 @@ Ondersteuning Achtergrond kiezen Berichten - Verzenden met Enter + Versturen met Enter Beëindig alle andere sessies Gebeurtenissen Contact lid van Telegram @@ -244,17 +244,17 @@ Vraag een vrijwilliger Veelgestelde vragen https://telegram.org/faq - Verwijder vertaling? + Vertaling verwijderen? Ongeldig vertalingsbestand Inschakelen - Uitschakelen + Uitgeschakeld Meldingenservice - Als Google Play Services genoeg voor je is om meldingen te ontvangen kun je de Meldingenservice uitschakelen. We raden echter aan dit ingeschakeld te laten om de app in de achtergrond te laten draaien en directe meldingen te ontvangen. + Als Google Play Services genoeg voor je is om meldingen te ontvangen kun je de meldingenservice uitschakelen. We raden echter aan dit ingeschakeld te laten om de app in de achtergrond te laten draaien en directe meldingen te ontvangen. Sorteren op Importeer contacten Voornaam Achternaam - LED kleur + LED-kleur Pop-up meldingen Geen pop-up Alleen bij scherm aan @@ -263,7 +263,7 @@ Badgenummer Kort Lang - Systeem standaard + Standaardinstelling Standaardinstelling Automatisch media downloaden Bij mobiele verbinding @@ -271,13 +271,21 @@ Bij roaming Geen media Opslaan in galerij - Naam bewerken + Naam wijzigen Prioriteit Standaard Laag Hoog Max + Nooit Meldingen herhalen + Je kan je telefoonnummer hier wijzigen. Al je clouddata — berichten, bestanden, groepen, contacten, etc. zullen worden gekopieërd naar je nieuwe nummer.\n\nLet op:]]> al je Telegram-contacten krijgen je nieuwe nummer]]> in hun adresboek, ervan uitgaande dat ze je oude nummer hadden en je hen niet had geblokkeerd in Telegram. + Al je Telegram-contacten krijgen je nieuwe nummer in hun adresboek, ervan uitgaande dat ze je oude nummer hadden en je hen niet had geblokkeerd in Telegram. + NUMMER WIJZIGEN + Nieuw nummer + We sturen een sms-bericht met verificatiecode naar je nieuwe nummer. + Aan telefoonnummer %1$s is al een Telegram-account gekoppeld. Verwijder het account om te kunnen migreren naar het nieuwe nummer. + Overig Nog geen media gedeeld @@ -286,7 +294,7 @@ Hybride m hiervandaan km hiervandaan - Locatie verzenden + Locatie versturen Locatie delen Alle media weergeven @@ -332,7 +340,7 @@ Video bewerken Originele video Bewerkte video - Video versturen... + Video versturen Video comprimeren Volgende @@ -341,17 +349,17 @@ Openen Annuleren Toevoegen - Bewerken - Verzenden + Wijzig + Stuur Bellen - Kopiëren - Verwijderen + Kopieer + Verwijder Doorsturen Opnieuw proberen Van camera Uit galerij Foto verwijderen - Instellen + Stel in OK un1 heeft un2 verwijderd @@ -375,11 +383,11 @@ Video Locatie Contact - Document + Bestand Geluidsbestand Jij - Je hebt een schermafbeelding gemaakt! - un1 maakte een schermafbeelding! + Schermafdruk gemaakt! + un1 heeft een schermafdruk gemaakt! Ongeldig telefoonnummer Code verlopen. Log opnieuw in. @@ -387,7 +395,7 @@ Ongeldige code Ongeldige voornaam Ongeldige achternaam - Bezig met laden… + Bezig met laden Je hebt geen mediaspeler. Installeer een mediaspeler om door te gaan. Mail ons op sms@telegram.org en vertel ons over je probleem. Je hebt geen apps die bestandstype \'%1$s\' kunnen verwerken, gelieve een compatibele app te installeren @@ -395,21 +403,21 @@ Weet je het zeker? %1$s toevoegen aan de groep?\n\nAantal recente berichten om door te sturen: Berichten doorsturen naar %1$s? - Berichten naar %1$s verzenden? + Berichten naar %1$s versturen? Weet je zeker dat je wilt uitloggen?\n\nTelegram kun je naadloos op al je apparaten tegelijkertijd gebruiken.\n\nLet op! Als je uitlogt worden al je geheime chats verwijderd. Alle apparaten behalve het huidige apparaat uitloggen? Echt alles verwijderen en de groep verlaten? - Gesprek echt verwijderen? + Chat echt verwijderen? Weet je zeker dat je je contactinformatie wilt delen? Weet je zeker dat je deze persoon wilt blokkeren? Weet je zeker dat je deze persoon wilt deblokkeren? - Contactpersoon echt verwijderen? + Contact echt verwijderen? Weet je zeker dat je een geheime chat wilt starten? Weet je zeker dat je de registratie wilt annuleren? Geschiedenis echt wissen? %1$s echt verwijderen? - Berichten naar %1$s verzenden? - Berichten naar %1$s doorsturen? + Berichten naar %1$s versturen? + Berichten doorsturen naar %1$s? Sorry, deze functie is momenteel niet beschikbaar in jouw land. Telegram @@ -423,7 +431,7 @@ Telegram]]> bezorgt berichten sneller dan]]>elke andere applicatie. Telegram]]> is altijd gratis. Geen advertenties.]]>Geen abonnementskosten. Telegram]]> beveiligd je berichten]]>tegen aanvallen van hackers. - Telegram]]> beperkt je niet in de grootte van]]>je media of gesprekken. + Telegram]]> beperkt je niet in de grootte van]]>je media of chats. Telegram]]> biedt toegang tot je berichten]]>vanaf meerdere apparaten. Telegram]]> berichten zijn sterk versleuteld]]>en kunnen zichzelf vernietigen. Begin met chatten @@ -458,12 +466,12 @@ %1$d berichten %1$d berichten %1$d berichten - van geen enkel contactpersoon - van %1$d contactpersoon - van %1$d contactpersonen - van %1$d contactpersonen - van %1$d contactpersonen - van %1$d contactpersonen + van geen enkel contact + van %1$d contacten + van %1$d contacten + van %1$d contacten + van %1$d contacten + van %1$d contacten %1$d seconden %1$d seconde %1$d seconden @@ -476,12 +484,12 @@ %1$d minuten %1$d minuten %1$d minuten - %1$d uren + %1$d uur %1$d uur - %1$d uren - %1$d uren - %1$d uren - %1$d uren + %1$d uur + %1$d uur + %1$d uur + %1$d uur %1$d dagen %1$d dag %1$d dagen @@ -500,12 +508,12 @@ %1$d maanden %1$d maanden %1$d maanden - %1$d jaren + %1$d jaar %1$d jaar - %1$d jaren - %1$d jaren - %1$d jaren - %1$d jaren + %1$d jaar + %1$d jaar + %1$d jaar + %1$d jaar %1$d gebruikers %1$d gebruiker %1$d gebruikers diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index 3804be3b..4c80221c 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -106,7 +106,7 @@ Salvar em downloads Aplicar arquivo de localização Anexo não suportado - Tempo de autodestruição + Definir timer de autodestruição %1$s estabeleceu o tempo de autodestruição para %2$s Você estabeleceu o tempo de autodestruição para %1$s @@ -137,7 +137,7 @@ %1$s removeu você do grupo %2$s %1$s saiu do grupo %2$s %1$s entrou para o Telegram! - %1$s,\nNós detectamos um login na sua conta de um novo dispositivo %2$s\n\nDispositivo: %3$s\nLocalização: %4$s\nSe não foi você, você pode ir em Configurações - Terminar todas as sessões.\n\nAtenciosamente,\nTime do Telegram + %1$s,\nDetectamos um acesso à sua conta de um novo dispositivo em %2$s\n\nDispositivo: %3$s\nLocalização: %4$s\n\nCaso não tenha sido você, vá em Configurações – Privacidade e Segurança – Terminar todas as outras sessões.\n\nObrigado,\nEquipe Telegram %1$s atualizou a foto do perfil Responder Responder para %1$s @@ -157,7 +157,7 @@ visto recentemente visto na última semana visto no último mês - visto há muito tempo atrás + visto há muito tempo Nova Mensagem Enviar mensagem para... @@ -272,12 +272,20 @@ Sem mídia Salvar na galeria Editar nome - Priority - Default - Low - High - Max - Repeat Notifications + Prioridade + Padrão + Baixa + Alta + Máxima + Nunca + Repetir Notificações + Você pode trocar seu número do Telegram aqui. Sua conta e todos os seus dados — mensagens, mídia, contatos, etc. serão movidos para o novo número.\n\nImportante:]]> todos os contatos do Telegram terão seu novo número]]> adicionado às suas lista de contatos, desde que eles tenham seu antigo número e você não os tenha bloqueado no Telegram. + Todos os contatos do Telegram terão seu novo número adicionado às suas listas de contatos, desde que eles tenham seu antigo número e você não os tenha bloqueado no Telegram. + TROCAR NÚMERO + Novo número + Vamos enviar uma SMS com um código de confirmação para o seu novo número. + O número %1$s já possui uma conta do Telegram. Por favor, delete esta conta antes de migrar para o novo número. + Outro Ainda não há mídia compartilhada @@ -316,7 +324,7 @@ Alterar quem pode ver o seu Último Acesso. Quem pode ver o seu Último Acesso? Adicionar exceções - Importante: você não será capaz de ver quando foi o Último Acesso para as pessoas com quem você não compartilha quando foi seu Último Acesso. Você visualizará a última vez visto aproximada. (recentemente, dentro de uma semana, dentro de um mês). + Importante: você não será capaz de ver quando foi o Último Acesso das pessoas com quem você não compartilha quando foi seu Último Acesso. Você visualizará o Último acesso aproximado (recentemente, dentro de uma semana, dentro de um mês). Sempre Mostrar Para Nunca Mostrar Para Estas configurações irão substituir os valores anteriores. diff --git a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml index 3aa9c825..33d3bb7f 100644 --- a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml @@ -106,7 +106,7 @@ Salvar em downloads Aplicar arquivo de localização Anexo não suportado - Tempo de autodestruição + Definir timer de autodestruição %1$s estabeleceu o tempo de autodestruição para %2$s Você estabeleceu o tempo de autodestruição para %1$s @@ -137,7 +137,7 @@ %1$s removeu você do grupo %2$s %1$s saiu do grupo %2$s %1$s entrou para o Telegram! - %1$s,\nNós detectamos um login na sua conta de um novo dispositivo %2$s\n\nDispositivo: %3$s\nLocalização: %4$s\nSe não foi você, você pode ir em Configurações - Terminar todas as sessões.\n\nAtenciosamente,\nTime do Telegram + %1$s,\nDetectamos um acesso à sua conta de um novo dispositivo em %2$s\n\nDispositivo: %3$s\nLocalização: %4$s\n\nCaso não tenha sido você, vá em Configurações – Privacidade e Segurança – Terminar todas as outras sessões.\n\nObrigado,\nEquipe Telegram %1$s atualizou a foto do perfil Responder Responder para %1$s @@ -157,7 +157,7 @@ visto recentemente visto na última semana visto no último mês - visto há muito tempo atrás + visto há muito tempo Nova Mensagem Enviar mensagem para... @@ -272,12 +272,20 @@ Sem mídia Salvar na galeria Editar nome - Priority - Default - Low - High - Max - Repeat Notifications + Prioridade + Padrão + Baixa + Alta + Máxima + Nunca + Repetir Notificações + Você pode trocar seu número do Telegram aqui. Sua conta e todos os seus dados — mensagens, mídia, contatos, etc. serão movidos para o novo número.\n\nImportante:]]> todos os contatos do Telegram terão seu novo número]]> adicionado às suas lista de contatos, desde que eles tenham seu antigo número e você não os tenha bloqueado no Telegram. + Todos os contatos do Telegram terão seu novo número adicionado às suas listas de contatos, desde que eles tenham seu antigo número e você não os tenha bloqueado no Telegram. + TROCAR NÚMERO + Novo número + Vamos enviar uma SMS com um código de confirmação para o seu novo número. + O número %1$s já possui uma conta do Telegram. Por favor, delete esta conta antes de migrar para o novo número. + Outro Ainda não há mídia compartilhada @@ -316,7 +324,7 @@ Alterar quem pode ver o seu Último Acesso. Quem pode ver o seu Último Acesso? Adicionar exceções - Importante: você não será capaz de ver quando foi o Último Acesso para as pessoas com quem você não compartilha quando foi seu Último Acesso. Você visualizará a última vez visto aproximada. (recentemente, dentro de uma semana, dentro de um mês). + Importante: você não será capaz de ver quando foi o Último Acesso das pessoas com quem você não compartilha quando foi seu Último Acesso. Você visualizará o Último acesso aproximado (recentemente, dentro de uma semana, dentro de um mês). Sempre Mostrar Para Nunca Mostrar Para Estas configurações irão substituir os valores anteriores. diff --git a/TMessagesProj/src/main/res/values-v21/styles.xml b/TMessagesProj/src/main/res/values-v21/styles.xml index 87fc512c..97ee0af7 100644 --- a/TMessagesProj/src/main/res/values-v21/styles.xml +++ b/TMessagesProj/src/main/res/values-v21/styles.xml @@ -44,6 +44,7 @@ @null false true + #99000000