From 300659e30cc3a7c6e4fe5a0b1aa2e4ed0741208b Mon Sep 17 00:00:00 2001 From: DrKLO Date: Thu, 19 Mar 2015 02:09:45 +0300 Subject: [PATCH] Update to 2.6.0 Replies Mentions Hashtags New messages forward logic Blur in photo editor --- TMessagesProj/build.gradle | 14 +- .../jawnae/pyronet/PyroClientListener.java | 12 +- .../telegram/android/AndroidUtilities.java | 2 - .../org/telegram/android/ImageReceiver.java | 4 +- .../org/telegram/android/MediaController.java | 40 +- .../org/telegram/android/MessageObject.java | 160 ++- .../telegram/android/MessagesController.java | 798 +++++++----- .../org/telegram/android/MessagesStorage.java | 188 ++- .../telegram/android/NotificationCenter.java | 3 +- .../android/NotificationsController.java | 120 +- .../telegram/android/SendMessagesHelper.java | 340 +++-- .../telegram/android/WearReplyReceiver.java | 2 +- .../android/query/ReplyMessageQuery.java | 185 +++ .../org/telegram/android/volley/Cache.java | 14 +- .../org/telegram/android/volley/Network.java | 2 +- .../telegram/android/volley/RequestQueue.java | 2 +- .../org/telegram/android/volley/Response.java | 4 +- .../android/volley/ResponseDelivery.java | 6 +- .../telegram/android/volley/RetryPolicy.java | 6 +- .../android/volley/toolbox/Authenticator.java | 4 +- .../android/volley/toolbox/HttpStack.java | 2 +- .../android/volley/toolbox/HurlStack.java | 2 +- .../android/volley/toolbox/ImageLoader.java | 6 +- .../messenger/ConnectionsManager.java | 5 +- .../telegram/messenger/FileLoadOperation.java | 8 +- .../org/telegram/messenger/FileLoader.java | 16 +- .../messenger/FileUploadOperation.java | 8 +- .../org/telegram/messenger/TLClassStore.java | 21 +- .../java/org/telegram/messenger/TLRPC.java | 757 +++++++----- .../org/telegram/messenger/TcpConnection.java | 10 +- .../org/telegram/ui/ActionBar/ActionBar.java | 11 +- .../ui/ActionBar/ActionBarLayout.java | 14 +- .../telegram/ui/ActionBar/ActionBarMenu.java | 18 +- .../ui/ActionBar/ActionBarMenuItem.java | 11 +- .../ui/ActionBar/ActionBarPopupWindow.java | 4 +- .../telegram/ui/ActionBar/BaseFragment.java | 2 +- .../ui/ActionBar/DrawerLayoutContainer.java | 10 +- .../ui/Adapters/DialogsSearchAdapter.java | 25 +- .../telegram/ui/Adapters/MentionsAdapter.java | 186 +++ .../telegram/ui/Adapters/StickersAdapter.java | 7 +- .../org/telegram/ui/Animation/Animator10.java | 4 +- .../telegram/ui/Animation/TypeEvaluator.java | 2 +- .../telegram/ui/Animation/ValueAnimator.java | 2 +- .../org/telegram/ui/Cells/ChatActionCell.java | 16 +- .../org/telegram/ui/Cells/ChatAudioCell.java | 33 +- .../org/telegram/ui/Cells/ChatBaseCell.java | 253 +++- .../telegram/ui/Cells/ChatContactCell.java | 20 +- .../org/telegram/ui/Cells/ChatMediaCell.java | 62 +- .../telegram/ui/Cells/ChatMessageCell.java | 14 +- .../org/telegram/ui/Cells/DialogCell.java | 2 +- .../org/telegram/ui/Cells/MentionCell.java | 99 ++ .../telegram/ui/Cells/PhotoEditToolCell.java | 6 + .../ui/Cells/PhotoPickerAlbumsCell.java | 12 +- .../ui/Cells/PhotoPickerSearchCell.java | 4 +- .../ui/Cells/SharedPhotoVideoCell.java | 7 +- .../java/org/telegram/ui/ChatActivity.java | 1094 +++++++++++++---- .../ui/Components/AvatarDrawable.java | 14 +- .../telegram/ui/Components/AvatarUpdater.java | 11 +- .../ui/Components/ChatActivityEnterView.java | 301 ++++- .../ui/Components/ClippingImageView.java | 4 +- .../ui/Components/ColorPickerView.java | 4 +- .../org/telegram/ui/Components/EmojiView.java | 6 +- .../ui/Components/ForegroundDetector.java | 4 +- .../ui/Components/HorizontalListView.java | 6 +- .../ui/Components/LayoutListView.java | 43 +- .../telegram/ui/Components/NumberPicker.java | 10 +- .../ui/Components/PagerSlidingTabStrip.java | 2 +- .../telegram/ui/Components/PasscodeView.java | 4 +- .../telegram/ui/Components/PhotoCropView.java | 4 +- .../ui/Components/PhotoEditorSeekBar.java | 4 +- .../ui/Components/PhotoFilterBlurControl.java | 499 ++++++++ .../PhotoFilterLinearBlurControl.java | 417 ------- .../ui/Components/PhotoFilterView.java | 762 +++++++++--- ...ilterRadialBlurControl.java => Point.java} | 13 +- .../java/org/telegram/ui/Components/Rect.java | 23 + .../ui/Components/RecyclerListView.java | 2 +- .../org/telegram/ui/Components/SeekBar.java | 4 +- .../java/org/telegram/ui/Components/Size.java | 23 + .../SizeNotifierRelativeLayout.java | 19 +- .../ui/Components/SlidingTabView.java | 4 +- .../ui/Components/VideoSeekBarView.java | 4 +- .../ui/Components/VideoTimelineView.java | 6 +- .../org/telegram/ui/ContactAddActivity.java | 3 + .../org/telegram/ui/ContactsActivity.java | 11 +- .../telegram/ui/CountrySelectActivity.java | 8 +- .../telegram/ui/DocumentSelectActivity.java | 8 +- .../org/telegram/ui/GroupCreateActivity.java | 4 +- .../telegram/ui/LanguageSelectActivity.java | 4 +- .../telegram/ui/LastSeenUsersActivity.java | 4 +- .../java/org/telegram/ui/LaunchActivity.java | 60 +- .../org/telegram/ui/LocationActivity.java | 11 +- .../java/org/telegram/ui/MediaActivity.java | 46 +- .../org/telegram/ui/MessagesActivity.java | 142 ++- .../ui/NotificationsSettingsActivity.java | 6 +- .../telegram/ui/PhotoAlbumPickerActivity.java | 11 +- .../org/telegram/ui/PhotoCropActivity.java | 2 +- .../org/telegram/ui/PhotoPickerActivity.java | 9 +- .../java/org/telegram/ui/PhotoViewer.java | 55 +- .../ui/PopupNotificationActivity.java | 13 +- .../java/org/telegram/ui/ProfileActivity.java | 5 +- .../ui/ProfileNotificationsActivity.java | 2 +- .../org/telegram/ui/SecretPhotoViewer.java | 4 +- .../org/telegram/ui/SettingsActivity.java | 3 + .../org/telegram/ui/VideoEditorActivity.java | 14 +- .../main/res/drawable-hdpi/blur_linear.png | Bin 0 -> 974 bytes .../res/drawable-hdpi/blur_linear_active.png | Bin 0 -> 1004 bytes .../src/main/res/drawable-hdpi/blur_off.png | Bin 0 -> 1029 bytes .../res/drawable-hdpi/blur_off_active.png | Bin 0 -> 1064 bytes .../main/res/drawable-hdpi/blur_radial.png | Bin 0 -> 1485 bytes .../res/drawable-hdpi/blur_radial_active.png | Bin 0 -> 1707 bytes .../main/res/drawable-hdpi/delete_reply.png | Bin 0 -> 1241 bytes .../main/res/drawable-hdpi/forward_blue.png | Bin 0 -> 1220 bytes .../res/drawable-hdpi/ic_ab_fwd_forward.png | Bin 1399 -> 1216 bytes .../main/res/drawable-hdpi/ic_ab_reply.png | Bin 0 -> 1458 bytes .../src/main/res/drawable-hdpi/reply.png | Bin 0 -> 1419 bytes .../main/res/drawable-hdpi/system_blue.9.png | Bin 242 -> 1127 bytes .../src/main/res/drawable-hdpi/tool_blur.png | Bin 0 -> 1218 bytes .../main/res/drawable-mdpi/blur_linear.png | Bin 0 -> 958 bytes .../res/drawable-mdpi/blur_linear_active.png | Bin 0 -> 978 bytes .../src/main/res/drawable-mdpi/blur_off.png | Bin 0 -> 994 bytes .../res/drawable-mdpi/blur_off_active.png | Bin 0 -> 1011 bytes .../main/res/drawable-mdpi/blur_radial.png | Bin 0 -> 1265 bytes .../res/drawable-mdpi/blur_radial_active.png | Bin 0 -> 1387 bytes .../main/res/drawable-mdpi/delete_reply.png | Bin 0 -> 1141 bytes .../main/res/drawable-mdpi/forward_blue.png | Bin 0 -> 1070 bytes .../res/drawable-mdpi/ic_ab_fwd_forward.png | Bin 1264 -> 0 bytes .../main/res/drawable-mdpi/ic_ab_reply.png | Bin 0 -> 1272 bytes .../src/main/res/drawable-mdpi/reply.png | Bin 0 -> 1250 bytes .../main/res/drawable-mdpi/system_blue.9.png | Bin 182 -> 1052 bytes .../src/main/res/drawable-mdpi/tool_blur.png | Bin 0 -> 1083 bytes .../main/res/drawable-xhdpi/blur_linear.png | Bin 0 -> 990 bytes .../res/drawable-xhdpi/blur_linear_active.png | Bin 0 -> 1002 bytes .../src/main/res/drawable-xhdpi/blur_off.png | Bin 0 -> 1087 bytes .../res/drawable-xhdpi/blur_off_active.png | Bin 0 -> 1103 bytes .../main/res/drawable-xhdpi/blur_radial.png | Bin 0 -> 1717 bytes .../res/drawable-xhdpi/blur_radial_active.png | Bin 0 -> 1990 bytes .../main/res/drawable-xhdpi/delete_reply.png | Bin 0 -> 1356 bytes .../main/res/drawable-xhdpi/forward_blue.png | Bin 0 -> 1299 bytes .../res/drawable-xhdpi/ic_ab_fwd_forward.png | Bin 1536 -> 1317 bytes .../main/res/drawable-xhdpi/ic_ab_reply.png | Bin 0 -> 1616 bytes .../src/main/res/drawable-xhdpi/reply.png | Bin 0 -> 1567 bytes .../main/res/drawable-xhdpi/system_blue.9.png | Bin 290 -> 1204 bytes .../src/main/res/drawable-xhdpi/tool_blur.png | Bin 0 -> 1203 bytes .../main/res/drawable-xxhdpi/blur_linear.png | Bin 0 -> 1045 bytes .../drawable-xxhdpi/blur_linear_active.png | Bin 0 -> 1079 bytes .../src/main/res/drawable-xxhdpi/blur_off.png | Bin 0 -> 1221 bytes .../res/drawable-xxhdpi/blur_off_active.png | Bin 0 -> 1231 bytes .../main/res/drawable-xxhdpi/blur_radial.png | Bin 0 -> 2285 bytes .../drawable-xxhdpi/blur_radial_active.png | Bin 0 -> 2652 bytes .../main/res/drawable-xxhdpi/delete_reply.png | Bin 0 -> 1495 bytes .../main/res/drawable-xxhdpi/forward_blue.png | Bin 0 -> 1542 bytes .../res/drawable-xxhdpi/ic_ab_fwd_forward.png | Bin 1904 -> 1536 bytes .../main/res/drawable-xxhdpi/ic_ab_reply.png | Bin 0 -> 1936 bytes .../src/main/res/drawable-xxhdpi/reply.png | Bin 0 -> 1904 bytes .../res/drawable-xxhdpi/system_blue.9.png | Bin 388 -> 1309 bytes .../main/res/drawable-xxhdpi/tool_blur.png | Bin 0 -> 1348 bytes .../src/main/res/layout/messages_list.xml | 2 + .../src/main/res/values-ar/strings.xml | 86 +- .../src/main/res/values-de/strings.xml | 68 +- .../src/main/res/values-es/strings.xml | 82 +- .../src/main/res/values-it/strings.xml | 74 +- .../src/main/res/values-ko/strings.xml | 66 +- .../src/main/res/values-nl/strings.xml | 68 +- .../src/main/res/values-pt-rBR/strings.xml | 74 +- .../src/main/res/values-pt-rPT/strings.xml | 74 +- TMessagesProj/src/main/res/values/strings.xml | 66 +- 166 files changed, 5702 insertions(+), 2235 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/android/query/ReplyMessageQuery.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java delete mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterLinearBlurControl.java rename TMessagesProj/src/main/java/org/telegram/ui/Components/{PhotoFilterRadialBlurControl.java => Point.java} (61%) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/blur_linear_active.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/blur_off.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/blur_off_active.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/blur_radial_active.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/delete_reply.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/forward_blue.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/reply.png mode change 100644 => 100755 TMessagesProj/src/main/res/drawable-hdpi/system_blue.9.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/tool_blur.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/blur_linear_active.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/blur_off.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/blur_off_active.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/blur_radial_active.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/delete_reply.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/forward_blue.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_ab_fwd_forward.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/reply.png mode change 100644 => 100755 TMessagesProj/src/main/res/drawable-mdpi/system_blue.9.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/tool_blur.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/blur_linear_active.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/blur_off.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/blur_off_active.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/blur_radial_active.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/delete_reply.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/forward_blue.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_ab_reply.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/reply.png mode change 100644 => 100755 TMessagesProj/src/main/res/drawable-xhdpi/system_blue.9.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/tool_blur.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear_active.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/blur_off_active.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial_active.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/delete_reply.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/forward_blue.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/reply.png mode change 100644 => 100755 TMessagesProj/src/main/res/drawable-xxhdpi/system_blue.9.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/tool_blur.png diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 910597bbc..f921874f2 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:1.1.0' + classpath 'com.android.tools.build:gradle:1.1.3' } } apply plugin: 'com.android.application' @@ -13,7 +13,7 @@ repositories { } dependencies { - compile 'com.android.support:support-v4:21.0.+' + compile 'com.android.support:support-v4:22.0.+' compile 'com.google.android.gms:play-services:3.2.+' compile 'net.hockeyapp.android:HockeySDK:3.5.+' compile 'com.googlecode.mp4parser:isoparser:1.0.+' @@ -21,8 +21,8 @@ dependencies { } android { - compileSdkVersion 21 - buildToolsVersion '21.1.2' + compileSdkVersion 22 + buildToolsVersion '22.0.0' compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 @@ -81,8 +81,8 @@ android { defaultConfig { minSdkVersion 8 - targetSdkVersion 21 - versionCode 458 - versionName "2.5.2" + targetSdkVersion 22 + versionCode 466 + versionName "2.6.0" } } diff --git a/TMessagesProj/src/main/java/jawnae/pyronet/PyroClientListener.java b/TMessagesProj/src/main/java/jawnae/pyronet/PyroClientListener.java index 117cb1b83..a24913a13 100755 --- a/TMessagesProj/src/main/java/jawnae/pyronet/PyroClientListener.java +++ b/TMessagesProj/src/main/java/jawnae/pyronet/PyroClientListener.java @@ -22,17 +22,17 @@ import java.io.IOException; import java.nio.ByteBuffer; public interface PyroClientListener { - public void connectedClient(PyroClient client); + void connectedClient(PyroClient client); - public void unconnectableClient(PyroClient client, Exception cause); + void unconnectableClient(PyroClient client, Exception cause); - public void droppedClient(PyroClient client, IOException cause); + void droppedClient(PyroClient client, IOException cause); - public void disconnectedClient(PyroClient client); + void disconnectedClient(PyroClient client); // - public void receivedData(PyroClient client, ByteBuffer data); + void receivedData(PyroClient client, ByteBuffer data); - public void sentData(PyroClient client, int bytes); + void sentData(PyroClient client, int bytes); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java index 6e69b4411..97f72977d 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java @@ -169,8 +169,6 @@ public class AndroidUtilities { } InputMethodManager inputManager = (InputMethodManager)view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); - - ((InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(view, 0); } public static boolean isKeyboardShowed(View view) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java index 6ecff83d1..fa79c264b 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ImageReceiver.java @@ -29,8 +29,8 @@ import org.telegram.messenger.Utilities; public class ImageReceiver implements NotificationCenter.NotificationCenterDelegate { - public static interface ImageReceiverDelegate { - public void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb); + public interface ImageReceiverDelegate { + void didSetImage(ImageReceiver imageReceiver, boolean set, boolean thumb); } private View parentView; diff --git a/TMessagesProj/src/main/java/org/telegram/android/MediaController.java b/TMessagesProj/src/main/java/org/telegram/android/MediaController.java index 0207db4ee..0fd27e2ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MediaController.java @@ -87,12 +87,12 @@ public class MediaController implements NotificationCenter.NotificationCenterDel public static int[] readArgs = new int[3]; - public static interface FileDownloadProgressListener { - public void onFailedDownload(String fileName); - public void onSuccessDownload(String fileName); - public void onProgressDownload(String fileName, float progress); - public void onProgressUpload(String fileName, float progress, boolean isEncrypted); - public int getObserverTag(); + public interface FileDownloadProgressListener { + void onFailedDownload(String fileName); + void onSuccessDownload(String fileName); + void onProgressDownload(String fileName, float progress); + void onProgressUpload(String fileName, float progress, boolean isEncrypted); + int getObserverTag(); } private class AudioBuffer { @@ -234,6 +234,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel private long recordStartTime; private long recordTimeCount; private long recordDialogId; + private MessageObject recordReplyingMessageObject; private DispatchQueue fileDecodingQueue; private DispatchQueue playerQueue; private ArrayList usedPlayerBuffers = new ArrayList<>(); @@ -509,7 +510,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel lastProgress = progress; playingMessageObject.audioProgress = value; playingMessageObject.audioProgressSec = lastProgress / 1000; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioProgressDidChanged, playingMessageObject.messageOwner.id, value); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioProgressDidChanged, playingMessageObject.getId(), value); } catch (Exception e) { FileLog.e("tmessages", e); } @@ -977,7 +978,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } else if (id == NotificationCenter.messagesDeleted) { if (playingMessageObject != null) { ArrayList markAsDeletedMessages = (ArrayList)args[0]; - if (markAsDeletedMessages.contains(playingMessageObject.messageOwner.id)) { + if (markAsDeletedMessages.contains(playingMessageObject.getId())) { clenupPlayer(false); } } @@ -1187,7 +1188,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel playingMessageObject.audioProgressSec = 0; playingMessageObject = null; if (notify) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidReset, lastFile.messageOwner.id); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidReset, lastFile.getId()); } } } @@ -1227,7 +1228,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } public boolean seekToProgress(MessageObject messageObject, float progress) { - if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) { + if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.getId() != messageObject.getId()) { return false; } try { @@ -1249,7 +1250,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (messageObject == null) { return false; } - if ((audioTrackPlayer != null || audioPlayer != null) && playingMessageObject != null && messageObject.messageOwner.id == playingMessageObject.messageOwner.id) { + if ((audioTrackPlayer != null || audioPlayer != null) && playingMessageObject != null && messageObject.getId() == playingMessageObject.getId()) { if (isPaused) { resumeAudio(messageObject); } @@ -1412,7 +1413,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel public boolean pauseAudio(MessageObject messageObject) { stopProximitySensor(); - if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) { + if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.getId() != messageObject.getId()) { return false; } try { @@ -1432,7 +1433,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel public boolean resumeAudio(MessageObject messageObject) { startProximitySensor(); - if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id) { + if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.getId() != messageObject.getId()) { return false; } try { @@ -1451,14 +1452,14 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } public boolean isPlayingAudio(MessageObject messageObject) { - return !(audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.messageOwner.id != messageObject.messageOwner.id); + return !(audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.getId() != messageObject.getId()); } public boolean isAudioPaused() { return isPaused; } - public void startRecording(final long dialog_id) { + public void startRecording(final long dialog_id, final MessageObject reply_to_msg) { clenupPlayer(true); try { @@ -1505,6 +1506,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel recordStartTime = System.currentTimeMillis(); recordTimeCount = 0; recordDialogId = dialog_id; + recordReplyingMessageObject = reply_to_msg; fileBuffer.rewind(); audioRecorder.startRecording(); @@ -1557,11 +1559,11 @@ public class MediaController implements NotificationCenter.NotificationCenterDel long duration = recordTimeCount; audioToSend.duration = (int) (duration / 1000); if (duration > 700) { - SendMessagesHelper.getInstance().sendMessage(audioToSend, recordingAudioFileToSend.getAbsolutePath(), recordDialogId); + SendMessagesHelper.getInstance().sendMessage(audioToSend, recordingAudioFileToSend.getAbsolutePath(), recordDialogId, recordReplyingMessageObject); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidSent); } else { recordingAudioFileToSend.delete(); } - NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidSent); } }); } @@ -1739,7 +1741,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel return null; } - if (currentGifDrawable != null && currentGifMessageObject != null && messageObject.messageOwner.id == currentGifMessageObject.messageOwner.id) { + if (currentGifDrawable != null && currentGifMessageObject != null && messageObject.getId() == currentGifMessageObject.getId()) { currentMediaCell = cell; currentGifDrawable.parentView = new WeakReference(cell); return currentGifDrawable; @@ -1788,7 +1790,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel return; } - if (currentGifMessageObject != null && messageObject.messageOwner.id == currentGifMessageObject.messageOwner.id) { + if (currentGifMessageObject != null && messageObject.getId() == currentGifMessageObject.getId()) { if (currentGifDrawable != null) { currentGifDrawable.stop(); currentGifDrawable.recycle(); diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java index 86db4605c..5d21bdf81 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java @@ -30,6 +30,8 @@ import java.util.AbstractMap; import java.util.ArrayList; import java.util.Calendar; import java.util.GregorianCalendar; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class MessageObject { @@ -39,6 +41,7 @@ public class MessageObject { public TLRPC.Message messageOwner; public CharSequence messageText; + public MessageObject replyMessageObject; public int type; public int contentType; public String dateKey; @@ -76,6 +79,10 @@ public class MessageObject { messageOwner = message; + if (message.replyMessage != null) { + replyMessageObject = new MessageObject(message.replyMessage, users, false); + } + if (message instanceof TLRPC.TL_messageService) { if (message.action != null) { TLRPC.User fromUser = null; @@ -279,9 +286,19 @@ public class MessageObject { messageText = LocaleController.getString("UnsuppotedMedia", R.string.UnsuppotedMedia); } else if (message.media instanceof TLRPC.TL_messageMediaDocument) { if (isSticker()) { - messageText = LocaleController.getString("AttachSticker", R.string.AttachSticker); + String sch = getStrickerChar(); + if (sch != null && sch.length() > 0) { + messageText = String.format("%s %s", sch, LocaleController.getString("AttachSticker", R.string.AttachSticker)); + } else { + messageText = LocaleController.getString("AttachSticker", R.string.AttachSticker); + } } else { - messageText = LocaleController.getString("AttachDocument", R.string.AttachDocument); + String name = FileLoader.getDocumentFileName(message.media.document); + if (name != null && name.length() > 0) { + messageText = name; + } else { + messageText = LocaleController.getString("AttachDocument", R.string.AttachDocument); + } } } else if (message.media instanceof TLRPC.TL_messageMediaAudio) { messageText = LocaleController.getString("AttachAudio", R.string.AttachAudio); @@ -291,7 +308,7 @@ public class MessageObject { } messageText = Emoji.replaceEmoji(messageText, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20)); - if (message instanceof TLRPC.TL_message || message instanceof TLRPC.TL_messageForwarded) { + if (message instanceof TLRPC.TL_message || message instanceof TLRPC.TL_messageForwarded_old2) { if (message.media == null || message.media instanceof TLRPC.TL_messageMediaEmpty) { contentType = type = 0; } else if (message.media != null && message.media instanceof TLRPC.TL_messageMediaPhoto) { @@ -487,6 +504,9 @@ public class MessageObject { } else if (!(c != ' ' && digitsInRow > 0)) { digitsInRow = 0; } + if ((c == '@' || c == '#') && i == 0 || i != 0 && message.charAt(i - 1) == ' ') { + return true; + } if (c == ':') { if (schemeSequence == 0) { schemeSequence = 1; @@ -531,6 +551,22 @@ public class MessageObject { } else { Linkify.addLinks((Spannable) messageText, Linkify.WEB_URLS); } + + try { + Pattern pattern = Pattern.compile("(^|\\s)@[a-zA-Z\\d_]{5,32}|(^|\\s)#[\\w@\\.]+"); + Matcher matcher = pattern.matcher(messageText); + while (matcher.find()) { + int start = matcher.start(); + int end = matcher.end(); + if (messageText.charAt(start) != '@' && messageText.charAt(start) != '#') { + start++; + } + URLSpanNoUnderline url = new URLSpanNoUnderline(messageText.subSequence(start, end).toString()); + ((Spannable) messageText).setSpan(url, start, end, 0); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } } int maxWidth; @@ -703,6 +739,10 @@ public class MessageObject { messageOwner.flags &= ~TLRPC.MESSAGE_FLAG_UNREAD; } + public int getId() { + return messageOwner.id; + } + public boolean isSecretPhoto() { return messageOwner instanceof TLRPC.TL_message_secret && messageOwner.media instanceof TLRPC.TL_messageMediaPhoto && messageOwner.ttl != 0 && messageOwner.ttl <= 60; } @@ -791,7 +831,121 @@ public class MessageObject { return false; } + public String getStrickerChar() { + if (messageOwner.media != null && messageOwner.media.document != null) { + for (TLRPC.DocumentAttribute attribute : messageOwner.media.document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeSticker) { + return attribute.alt; + } + } + } + return null; + } + + public int getApproximateHeight() { + if (type == 0) { + return textHeight; + } else if (contentType == 2) { + return AndroidUtilities.dp(68); + } else if (contentType == 3) { + return AndroidUtilities.dp(71); + } else if (type == 9) { + return AndroidUtilities.dp(100); + } else if (type == 4) { + return AndroidUtilities.dp(114); + } else if (type == 13) { + float maxHeight = AndroidUtilities.displaySize.y * 0.4f; + float maxWidth; + if (AndroidUtilities.isTablet()) { + maxWidth = AndroidUtilities.getMinTabletSide() * 0.5f; + } else { + maxWidth = AndroidUtilities.displaySize.x * 0.5f; + } + int photoHeight = 0; + int photoWidth = 0; + for (TLRPC.DocumentAttribute attribute : messageOwner.media.document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeImageSize) { + photoWidth = attribute.w; + photoHeight = attribute.h; + break; + } + } + if (photoWidth == 0) { + photoHeight = (int) maxHeight; + photoWidth = photoHeight + AndroidUtilities.dp(100); + } + if (photoHeight > maxHeight) { + photoWidth *= maxHeight / photoHeight; + photoHeight = (int)maxHeight; + } + if (photoWidth > maxWidth) { + photoHeight *= maxWidth / photoWidth; + } + return photoHeight + AndroidUtilities.dp(14); + } else { + int photoHeight = 0; + int photoWidth = 0; + + if (AndroidUtilities.isTablet()) { + photoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); + } else { + photoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); + } + photoHeight = photoWidth + AndroidUtilities.dp(100); + if (photoWidth > AndroidUtilities.getPhotoSize()) { + photoWidth = AndroidUtilities.getPhotoSize(); + } + if (photoHeight > AndroidUtilities.getPhotoSize()) { + photoHeight = AndroidUtilities.getPhotoSize(); + } + TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photoThumbs, AndroidUtilities.getPhotoSize()); + + if (currentPhotoObject != null) { + float scale = (float) currentPhotoObject.w / (float) photoWidth; + int w = (int) (currentPhotoObject.w / scale); + int h = (int) (currentPhotoObject.h / scale); + if (w == 0) { + w = AndroidUtilities.dp(100); + } + if (h == 0) { + h = AndroidUtilities.dp(100); + } + if (h > photoHeight) { + float scale2 = h; + h = photoHeight; + scale2 /= h; + w = (int) (w / scale2); + } else if (h < AndroidUtilities.dp(120)) { + h = AndroidUtilities.dp(120); + float hScale = (float) currentPhotoObject.h / h; + if (currentPhotoObject.w / hScale < photoWidth) { + w = (int) (currentPhotoObject.w / hScale); + } + } + if (isSecretPhoto()) { + if (AndroidUtilities.isTablet()) { + w = h = (int) (AndroidUtilities.getMinTabletSide() * 0.5f); + } else { + w = h = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f); + } + } + + photoWidth = w; + photoHeight = h; + } + return photoHeight + AndroidUtilities.dp(14); + } + } + public boolean isSticker() { return isStickerMessage(messageOwner); } + + public boolean isForwarded() { + return (messageOwner.flags & TLRPC.MESSAGE_FLAG_FWD) != 0; + } + + public boolean isReply() { + return !(replyMessageObject != null && replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty) && messageOwner.reply_to_msg_id != 0 && (messageOwner.flags & TLRPC.MESSAGE_FLAG_REPLY) != 0; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java index a7c97325a..e58779679 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java @@ -44,6 +44,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter 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); + private ConcurrentHashMap usersByUsernames = new ConcurrentHashMap<>(100, 1.0f, 2); public ArrayList dialogs = new ArrayList<>(); public ArrayList dialogsServerOnly = new ArrayList<>(); @@ -58,8 +59,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter public boolean loadingBlockedUsers = false; public ArrayList blockedUsers = new ArrayList<>(); - private ArrayList updatesQueue = new ArrayList<>(); - private long updatesStartWaitTime = 0; + private ArrayList updatesQueueSeq = new ArrayList<>(); + private ArrayList updatesQueuePts = new ArrayList<>(); + private ArrayList updatesQueueQts = new ArrayList<>(); + private long updatesStartWaitTimeSeq = 0; + private long updatesStartWaitTimePts = 0; + private long updatesStartWaitTimeQts = 0; private ArrayList loadingFullUsers = new ArrayList<>(); private ArrayList loadedFullUsers = new ArrayList<>(); private ArrayList loadingFullChats = new ArrayList<>(); @@ -94,7 +99,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter public int groupBigSize; private ArrayList disabledFeatures = new ArrayList<>(); - private class UserActionUpdates extends TLRPC.Updates { + private class UserActionUpdatesSeq extends TLRPC.Updates { + + } + + private class UserActionUpdatesPts extends TLRPC.Updates { } @@ -211,7 +220,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (fragment.getParentActivity() != null) { AlertDialog.Builder builder = new AlertDialog.Builder(fragment.getParentActivity()); builder.setTitle("Oops!"); - builder.setPositiveButton(R.string.OK, null); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(disabledFeature.description); fragment.showAlertDialog(builder); } @@ -367,6 +376,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialogs.clear(); dialogsServerOnly.clear(); users.clear(); + usersByUsernames.clear(); chats.clear(); dialogMessage.clear(); printingUsers.clear(); @@ -374,7 +384,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter onlinePrivacy.clear(); totalDialogsCount = 0; lastPrintingStringCount = 0; - updatesQueue.clear(); + updatesQueueSeq.clear(); + updatesQueuePts.clear(); + updatesQueueQts.clear(); blockedUsers.clear(); sendingTypings.clear(); loadingFullUsers.clear(); @@ -383,7 +395,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter loadingFullChats.clear(); loadedFullChats.clear(); - updatesStartWaitTime = 0; + updatesStartWaitTimeSeq = 0; + updatesStartWaitTimePts = 0; + updatesStartWaitTimeQts = 0; currentDeletingTaskTime = 0; currentDeletingTaskMids = null; gettingNewDeleteTask = false; @@ -413,6 +427,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter return users.get(id); } + public TLRPC.User getUser(String username) { + return usersByUsernames.get(username); + } + + public ConcurrentHashMap getUsers() { + return users; + } + public TLRPC.Chat getChat(Integer id) { return chats.get(id); } @@ -448,6 +470,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter } fromCache = fromCache && user.id / 1000 != 333 && user.id != 777000; TLRPC.User oldUser = users.get(user.id); + if (oldUser != null && oldUser.username != null && oldUser.username.length() > 0) { + usersByUsernames.remove(oldUser.username); + } + if (user.username != null && user.username.length() > 0) { + usersByUsernames.put(user.username, user); + } if (!fromCache) { users.put(user.id, user); if (user.id == UserConfig.getClientUserId()) { @@ -658,28 +686,42 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } - protected void processNewDifferenceParams(int seq, int pts, int date) { - if (MessagesStorage.lastSeqValue + 1 == seq) { - if (seq != -1) { - MessagesStorage.lastSeqValue = seq; - } - if (date != -1) { - MessagesStorage.lastDateValue = date; - } - if (pts != -1) { + protected void processNewDifferenceParams(int seq, int pts, int date, int pts_count) { + if (pts != -1) { + if (MessagesStorage.lastPtsValue + pts_count == pts) { MessagesStorage.lastPtsValue = pts; - } - MessagesStorage.getInstance().saveDiffParams(MessagesStorage.lastSeqValue, MessagesStorage.lastPtsValue, MessagesStorage.lastDateValue, MessagesStorage.lastQtsValue); - } else if (MessagesStorage.lastSeqValue != seq) { - if (gettingDifference || updatesStartWaitTime == 0 || updatesStartWaitTime != 0 && updatesStartWaitTime + 1500 > System.currentTimeMillis()) { - if (updatesStartWaitTime == 0) { - updatesStartWaitTime = System.currentTimeMillis(); + MessagesStorage.getInstance().saveDiffParams(MessagesStorage.lastSeqValue, MessagesStorage.lastPtsValue, MessagesStorage.lastDateValue, MessagesStorage.lastQtsValue); + } else if (MessagesStorage.lastPtsValue == pts) { + if (gettingDifference || updatesStartWaitTimePts == 0 || updatesStartWaitTimePts != 0 && updatesStartWaitTimePts + 1500 > System.currentTimeMillis()) { + if (updatesStartWaitTimePts == 0) { + updatesStartWaitTimePts = System.currentTimeMillis(); + } + UserActionUpdatesPts updates = new UserActionUpdatesPts(); + updates.seq = seq; + updatesQueuePts.add(updates); + } else { + getDifference(); + } + } + } + if (seq != -1) { + if (MessagesStorage.lastSeqValue + 1 == seq) { + MessagesStorage.lastSeqValue = seq; + if (date != -1) { + MessagesStorage.lastDateValue = date; + } + MessagesStorage.getInstance().saveDiffParams(MessagesStorage.lastSeqValue, MessagesStorage.lastPtsValue, MessagesStorage.lastDateValue, MessagesStorage.lastQtsValue); + } else if (MessagesStorage.lastSeqValue != seq) { + if (gettingDifference || updatesStartWaitTimeSeq == 0 || updatesStartWaitTimeSeq != 0 && updatesStartWaitTimeSeq + 1500 > System.currentTimeMillis()) { + if (updatesStartWaitTimeSeq == 0) { + updatesStartWaitTimeSeq = System.currentTimeMillis(); + } + UserActionUpdatesSeq updates = new UserActionUpdatesSeq(); + updates.seq = seq; + updatesQueueSeq.add(updates); + } else { + getDifference(); } - UserActionUpdates updates = new UserActionUpdates(); - updates.seq = seq; - updatesQueue.add(updates); - } else { - getDifference(); } } } @@ -825,7 +867,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (user == null) { return; } - blockedUsers.remove((Integer)user.id); + blockedUsers.remove((Integer) user.id); req.id = MessagesController.getInputUser(user); NotificationCenter.getInstance().postNotificationName(NotificationCenter.blockedUsersDidLoaded); ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { @@ -924,7 +966,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter ArrayList users = new ArrayList<>(); users.add(user); MessagesStorage.getInstance().putUsersAndChats(users, null, false, true); - user.photo = (TLRPC.UserProfilePhoto)response; + user.photo = (TLRPC.UserProfilePhoto) response; AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { @@ -1004,7 +1046,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { @Override public void run(TLObject response, TLRPC.TL_error error) { - + if (error == null) { + TLRPC.TL_messages_affectedMessages res = (TLRPC.TL_messages_affectedMessages) response; + processNewDifferenceParams(-1, res.pts, -1, res.pts_count); + } } }); } @@ -1075,7 +1120,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (res.offset > 0) { deleteDialog(did, res.offset, onlyHistory); } - processNewDifferenceParams(res.seq, res.pts, -1); + processNewDifferenceParams(-1, res.pts, -1, res.pts_count); } } }); @@ -1161,9 +1206,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); } - if (updatesStartWaitTime != 0 && updatesStartWaitTime + 1500 < currentTime) { - FileLog.e("tmessages", "UPDATES WAIT TIMEOUT - CHECK QUEUE"); - processUpdatesQueue(0); + for (int a = 0; a < 3; a++) { + if (getUpdatesStartTime(a) != 0 && getUpdatesStartTime(a) + 1500 < currentTime) { + FileLog.e("tmessages", a + " QUEUE UPDATES WAIT TIMEOUT - CHECK QUEUE"); + processUpdatesQueue(a, 0); + } } } if (!onlinePrivacy.isEmpty()) { @@ -1389,8 +1436,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter Utilities.stageQueue.postRunnable(new Runnable() { @Override public void run() { - int lower_id = (int)dialog_id; - int high_id = (int)(dialog_id >> 32); + int lower_id = (int) dialog_id; + int high_id = (int) (dialog_id >> 32); if (!isCache) { ImageLoader.saveMessagesThumbs(messagesRes.messages); } @@ -1562,7 +1609,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (oldMsg != null && oldMsg.deleted || value.top_message > currentDialog.top_message) { dialogs_dict.put(key, value); if (oldMsg != null) { - dialogMessage.remove(oldMsg.messageOwner.id); + dialogMessage.remove(oldMsg.getId()); } dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message)); } @@ -1570,7 +1617,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessageObject newMsg = new_dialogMessage.get(value.top_message); if (oldMsg.deleted || newMsg == null || newMsg.messageOwner.date > oldMsg.messageOwner.date) { dialogs_dict.put(key, value); - dialogMessage.remove(oldMsg.messageOwner.id); + dialogMessage.remove(oldMsg.getId()); dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message)); } } @@ -1593,8 +1640,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } }); for (TLRPC.TL_dialog d : dialogs) { - int high_id = (int)(d.id >> 32); - if ((int)d.id != 0 && high_id != 1) { + int high_id = (int) (d.id >> 32); + if ((int) d.id != 0 && high_id != 1) { dialogsServerOnly.add(d); } } @@ -1602,7 +1649,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter NotificationsController.getInstance().processDialogsUpdateRead(dialogsToUpdate); } }); - } + } }); } @@ -1636,7 +1683,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } if (dialogsRes instanceof TLRPC.TL_messages_dialogsSlice) { - TLRPC.TL_messages_dialogsSlice slice = (TLRPC.TL_messages_dialogsSlice)dialogsRes; + TLRPC.TL_messages_dialogsSlice slice = (TLRPC.TL_messages_dialogsSlice) dialogsRes; new_totalDialogsCount = slice.count; } else { new_totalDialogsCount = dialogsRes.dialogs.size(); @@ -1698,7 +1745,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (oldMsg == null || currentDialog.top_message > 0) { if (oldMsg != null && oldMsg.deleted || value.top_message > currentDialog.top_message) { if (oldMsg != null) { - dialogMessage.remove(oldMsg.messageOwner.id); + dialogMessage.remove(oldMsg.getId()); } dialogs_dict.put(key, value); dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message)); @@ -1706,7 +1753,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else { MessageObject newMsg = new_dialogMessage.get(value.top_message); if (oldMsg.deleted || newMsg == null || newMsg.messageOwner.date > oldMsg.messageOwner.date) { - dialogMessage.remove(oldMsg.messageOwner.id); + dialogMessage.remove(oldMsg.getId()); dialogs_dict.put(key, value); dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message)); } @@ -1730,8 +1777,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter } }); for (TLRPC.TL_dialog d : dialogs) { - int high_id = (int)(d.id >> 32); - if ((int)d.id != 0 && high_id != 1) { + int high_id = (int) (d.id >> 32); + if ((int) d.id != 0 && high_id != 1) { dialogsServerOnly.add(d); } } @@ -1792,7 +1839,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter } req.max_id = max_positive_id; req.offset = offset; - req.read_contents = true; if (offset == 0) { MessagesStorage.getInstance().processPendingRead(dialog_id, max_positive_id, max_date, false); MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { @@ -1832,7 +1878,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter if (res.offset > 0) { markDialogAsRead(dialog_id, 0, max_positive_id, res.offset, max_date, was, popup); } - processNewDifferenceParams(res.seq, res.pts, -1); + processNewDifferenceParams(-1, res.pts, -1, res.pts_count); } } }); @@ -1982,7 +2028,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter final ArrayList messages = new ArrayList<>(); messages.add(res.message); MessagesStorage.getInstance().putMessages(messages, true, true, false, 0); - processNewDifferenceParams(res.seq, res.pts, -1); + + if (res instanceof TLRPC.TL_messages_statedMessage) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, res.message.date, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_statedMessageLink) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.message.date, res.pts_count); + } } }); } @@ -2041,7 +2092,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter final ArrayList messages = new ArrayList<>(); messages.add(res.message); MessagesStorage.getInstance().putMessages(messages, true, true, false, 0); - processNewDifferenceParams(res.seq, res.pts, -1); + + if (res instanceof TLRPC.TL_messages_statedMessage) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, res.message.date, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_statedMessageLink) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.message.date, res.pts_count); + } } }); } else { @@ -2130,7 +2186,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter messages.add(res.message); MessagesStorage.getInstance().putMessages(messages, true, true, false, 0); } - processNewDifferenceParams(res.seq, res.pts, -1); + + if (res instanceof TLRPC.TL_messages_statedMessage) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, res.message.date, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_statedMessageLink) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.message.date, res.pts_count); + } } }); } else { @@ -2192,7 +2253,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter final ArrayList messages = new ArrayList<>(); messages.add(res.message); MessagesStorage.getInstance().putMessages(messages, true, true, false, 0); - processNewDifferenceParams(res.seq, res.pts, -1); + + if (res instanceof TLRPC.TL_messages_statedMessage) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, res.message.date, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_statedMessageLink) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.message.date, res.pts_count); + } } }); } else { @@ -2244,7 +2310,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter }); MessagesStorage.getInstance().putMessages(messages, true, true, false, 0); - processNewDifferenceParams(res.seq, res.pts, -1); + + if (res instanceof TLRPC.TL_messages_statedMessage) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, res.message.date, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_statedMessageLink) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.message.date, res.pts_count); + } } }); } @@ -2356,7 +2427,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.lastPtsValue = res.pts; MessagesStorage.lastSeqValue = res.seq; MessagesStorage.lastQtsValue = res.qts; - processUpdatesQueue(2); + for (int a = 0; a < 3; a++) { + processUpdatesQueue(a, 2); + } MessagesStorage.getInstance().saveDiffParams(MessagesStorage.lastSeqValue, MessagesStorage.lastPtsValue, MessagesStorage.lastDateValue, MessagesStorage.lastQtsValue); } else { if (error.code != 401) { @@ -2375,8 +2448,61 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } - private void processUpdatesQueue(int state) { - if (!updatesQueue.isEmpty()) { + private void setUpdatesStartTime(int type, long time) { + if (type == 0) { + updatesStartWaitTimeSeq = time; + } else if (type == 1) { + updatesStartWaitTimePts = time; + } else if (type == 2) { + updatesStartWaitTimeQts = time; + } + } + + public long getUpdatesStartTime(int type) { + if (type == 0) { + return updatesStartWaitTimeSeq; + } else if (type == 1) { + return updatesStartWaitTimePts; + } else if (type == 2) { + return updatesStartWaitTimeQts; + } + return 0; + } + + private int isValidUpdate(TLRPC.Updates updates, int type) { + if (type == 0) { + int seq = getUpdateSeq(updates); + if (MessagesStorage.lastSeqValue + 1 == seq || MessagesStorage.lastSeqValue == seq) { + return 0; + } else if (MessagesStorage.lastSeqValue < seq) { + return 1; + } else { + return 2; + } + } else if (type == 1) { + if (updates.pts <= MessagesStorage.lastPtsValue) { + return 2; + } else if (MessagesStorage.lastPtsValue + updates.pts_count == updates.pts) { + return 0; + } else { + return 1; + } + } else if (type == 2) { + if (updates.qts <= MessagesStorage.lastQtsValue) { + return 2; + } else if (MessagesStorage.lastQtsValue + 1 == updates.qts) { + return 0; + } else { + return 1; + } + } + return 0; + } + + private boolean processUpdatesQueue(int type, int state) { + ArrayList updatesQueue = null; + if (type == 0) { + updatesQueue = updatesQueueSeq; Collections.sort(updatesQueue, new Comparator() { @Override public int compare(TLRPC.Updates updates, TLRPC.Updates updates2) { @@ -2390,32 +2516,66 @@ public class MessagesController implements NotificationCenter.NotificationCenter return -1; } }); + } else if (type == 1) { + updatesQueue = updatesQueuePts; + Collections.sort(updatesQueue, new Comparator() { + @Override + public int compare(TLRPC.Updates updates, TLRPC.Updates updates2) { + if (updates.pts == updates2.pts) { + return 0; + } else if (updates.pts > updates2.pts) { + return 1; + } + return -1; + } + }); + } else if (type == 2) { + updatesQueue = updatesQueueQts; + Collections.sort(updatesQueue, new Comparator() { + @Override + public int compare(TLRPC.Updates updates, TLRPC.Updates updates2) { + if (updates.qts == updates2.qts) { + return 0; + } else if (updates.qts > updates2.qts) { + return 1; + } + return -1; + } + }); + } + if (!updatesQueue.isEmpty()) { boolean anyProceed = false; if (state == 2) { TLRPC.Updates updates = updatesQueue.get(0); - MessagesStorage.lastSeqValue = getUpdateSeq(updates); + if (type == 0) { + MessagesStorage.lastSeqValue = getUpdateSeq(updates); + } else if (type == 1) { + MessagesStorage.lastPtsValue = updates.pts; + } else if (type == 2) { + MessagesStorage.lastQtsValue = updates.qts; + } } for (int a = 0; a < updatesQueue.size(); a++) { TLRPC.Updates updates = updatesQueue.get(a); - int seq = getUpdateSeq(updates); - if (MessagesStorage.lastSeqValue + 1 == seq || MessagesStorage.lastSeqValue == seq) { + int updateState = isValidUpdate(updates, type); + if (updateState == 0) { processUpdates(updates, true); anyProceed = true; updatesQueue.remove(a); a--; - } else if (MessagesStorage.lastSeqValue < seq) { - if (updatesStartWaitTime != 0 && (anyProceed || updatesStartWaitTime + 1500 > System.currentTimeMillis())) { + } else if (updateState == 1) { + if (getUpdatesStartTime(type) != 0 && (anyProceed || getUpdatesStartTime(type) + 1500 > System.currentTimeMillis())) { FileLog.e("tmessages", "HOLE IN UPDATES QUEUE - will wait more time"); if (anyProceed) { - updatesStartWaitTime = System.currentTimeMillis(); + setUpdatesStartTime(type, System.currentTimeMillis()); } - return; + return false; } else { FileLog.e("tmessages", "HOLE IN UPDATES QUEUE - getDifference"); - updatesStartWaitTime = 0; + setUpdatesStartTime(type, 0); updatesQueue.clear(); getDifference(); - return; + return false; } } else { updatesQueue.remove(a); @@ -2424,29 +2584,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter } updatesQueue.clear(); FileLog.e("tmessages", "UPDATES QUEUE PROCEED - OK"); - updatesStartWaitTime = 0; - if (state == 1) { - final int stateCopy = ConnectionsManager.getInstance().getConnectionState(); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.didUpdatedConnectionState, stateCopy); - } - }); - } - } else { - if (state == 1) { - final int stateCopy = ConnectionsManager.getInstance().getConnectionState(); - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.didUpdatedConnectionState, stateCopy); - } - }); - } else { - updatesStartWaitTime = 0; - } } + setUpdatesStartTime(type, 0); + return true; } public void getDifference() { @@ -2635,7 +2775,21 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.lastPtsValue = res.state.pts; MessagesStorage.lastQtsValue = res.state.qts; ConnectionsManager.getInstance().setConnectionState(0); - processUpdatesQueue(1); + boolean done = true; + for (int a = 0; a < 3; a++) { + if (!processUpdatesQueue(a, 1)) { + done = false; + } + } + if (done) { + final int stateCopy = ConnectionsManager.getInstance().getConnectionState(); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.didUpdatedConnectionState, stateCopy); + } + }); + } } else if (res instanceof TLRPC.TL_updates_differenceSlice) { MessagesStorage.lastDateValue = res.intermediate_state.date; MessagesStorage.lastPtsValue = res.intermediate_state.pts; @@ -2646,7 +2800,21 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.lastSeqValue = res.seq; MessagesStorage.lastDateValue = res.date; ConnectionsManager.getInstance().setConnectionState(0); - processUpdatesQueue(1); + boolean done = true; + for (int a = 0; a < 3; a++) { + if (!processUpdatesQueue(a, 1)) { + done = false; + } + } + if (done) { + final int stateCopy = ConnectionsManager.getInstance().getConnectionState(); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.didUpdatedConnectionState, stateCopy); + } + }); + } } MessagesStorage.getInstance().saveDiffParams(MessagesStorage.lastSeqValue, MessagesStorage.lastPtsValue, MessagesStorage.lastDateValue, MessagesStorage.lastQtsValue); FileLog.e("tmessages", "received difference with date = " + MessagesStorage.lastDateValue + " pts = " + MessagesStorage.lastPtsValue + " seq = " + MessagesStorage.lastSeqValue); @@ -2673,124 +2841,99 @@ public class MessagesController implements NotificationCenter.NotificationCenter public void processUpdates(final TLRPC.Updates updates, boolean fromQueue) { boolean needGetDiff = false; boolean needReceivedQueue = false; - boolean addedToQueue = false; boolean updateStatus = false; if (updates instanceof TLRPC.TL_updateShort) { ArrayList arr = new ArrayList<>(); arr.add(updates.update); processUpdateArray(arr, null, null); - } else if (updates instanceof TLRPC.TL_updateShortChatMessage) { - TLRPC.User user = getUser(updates.from_id); - if (user != null && user.status != null && user.status.expires <= 0) { - onlinePrivacy.put(user.id, ConnectionsManager.getInstance().getCurrentTime()); - updateStatus = true; - } - boolean missingData = getChat(updates.chat_id) == null || user == null; - if (missingData) { - needGetDiff = true; - } else { - if (MessagesStorage.lastSeqValue + 1 == updates.seq) { - TLRPC.TL_message message = new TLRPC.TL_message(); - message.from_id = updates.from_id; - message.id = updates.id; - message.to_id = new TLRPC.TL_peerChat(); - message.to_id.chat_id = updates.chat_id; - message.message = updates.message; - message.date = updates.date; - message.flags = TLRPC.MESSAGE_FLAG_UNREAD; - message.media = new TLRPC.TL_messageMediaEmpty(); - MessagesStorage.lastSeqValue = updates.seq; - MessagesStorage.lastPtsValue = updates.pts; - final MessageObject obj = new MessageObject(message, null, true); - final ArrayList objArr = new ArrayList<>(); - objArr.add(obj); - ArrayList arr = new ArrayList<>(); - arr.add(message); - final boolean printUpdate = updatePrintingUsersWithNewMessages(-updates.chat_id, objArr); - if (printUpdate) { - updatePrintingStrings(); - } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (printUpdate) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_USER_PRINT); - } + } else if (updates instanceof TLRPC.TL_updateShortChatMessage || updates instanceof TLRPC.TL_updateShortMessage) { + TLRPC.User user = getUser(updates.user_id); + TLRPC.User user2 = null; - updateInterfaceWithMessages(-updates.chat_id, objArr); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); - } - }); - MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { - @Override - public void run() { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (!obj.isFromMe() && obj.isUnread()) { - NotificationsController.getInstance().processNewMessages(objArr, true); - } - } - }); - } - }); - MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); - } else if (MessagesStorage.lastSeqValue != updates.seq) { - FileLog.e("tmessages", "need get diff TL_updateShortChatMessage, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq); - if (gettingDifference || updatesStartWaitTime == 0 || updatesStartWaitTime != 0 && updatesStartWaitTime + 1500 > System.currentTimeMillis()) { - if (updatesStartWaitTime == 0) { - updatesStartWaitTime = System.currentTimeMillis(); - } - FileLog.e("tmessages", "add TL_updateShortChatMessage to queue"); - updatesQueue.add(updates); - addedToQueue = true; - } else { - needGetDiff = true; - } - } + boolean needFwdUser = false; + if (updates.fwd_from_id != 0) { + user2 = getUser(updates.fwd_from_id); + needFwdUser = true; + } + + boolean missingData = false; + if (updates instanceof TLRPC.TL_updateShortMessage) { + missingData = user == null || needFwdUser && user2 == null; + } else { + missingData = getChat(updates.chat_id) == null || user == null || needFwdUser && user2 == null; } - } else if (updates instanceof TLRPC.TL_updateShortMessage) { - TLRPC.User user = getUser(updates.from_id); if (user != null && user.status != null && user.status.expires <= 0) { onlinePrivacy.put(user.id, ConnectionsManager.getInstance().getCurrentTime()); updateStatus = true; } - boolean missingData = user == null; + if (missingData) { needGetDiff = true; } else { - if (MessagesStorage.lastSeqValue + 1 == updates.seq) { + if (MessagesStorage.lastPtsValue + updates.pts_count == updates.pts) { TLRPC.TL_message message = new TLRPC.TL_message(); - message.from_id = updates.from_id; message.id = updates.id; - message.to_id = new TLRPC.TL_peerUser(); - message.to_id.user_id = updates.from_id; + if (updates instanceof TLRPC.TL_updateShortMessage) { + if ((updates.flags & TLRPC.MESSAGE_FLAG_OUT) != 0) { + message.from_id = UserConfig.getClientUserId(); + } else { + message.from_id = updates.user_id; + } + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = updates.user_id; + message.dialog_id = updates.user_id; + } else { + message.from_id = updates.user_id; + message.to_id = new TLRPC.TL_peerChat(); + message.to_id.chat_id = updates.chat_id; + message.dialog_id = -updates.chat_id; + } message.message = updates.message; message.date = updates.date; - message.flags = TLRPC.MESSAGE_FLAG_UNREAD; + message.flags = updates.flags; + message.fwd_from_id = updates.fwd_from_id; + message.fwd_date = updates.fwd_date; + message.reply_to_msg_id = updates.reply_to_msg_id; message.media = new TLRPC.TL_messageMediaEmpty(); - MessagesStorage.lastSeqValue = updates.seq; MessagesStorage.lastPtsValue = updates.pts; - MessagesStorage.lastDateValue = updates.date; final MessageObject obj = new MessageObject(message, null, true); final ArrayList objArr = new ArrayList<>(); objArr.add(obj); ArrayList arr = new ArrayList<>(); arr.add(message); - final boolean printUpdate = updatePrintingUsersWithNewMessages(updates.from_id, objArr); - if (printUpdate) { - updatePrintingStrings(); - } - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - if (printUpdate) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_USER_PRINT); - } - updateInterfaceWithMessages(updates.from_id, objArr); - NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + if (updates instanceof TLRPC.TL_updateShortMessage) { + final boolean printUpdate = (updates.flags & TLRPC.MESSAGE_FLAG_OUT) == 0 && updatePrintingUsersWithNewMessages(updates.user_id, objArr); + if (printUpdate) { + updatePrintingStrings(); } - }); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (printUpdate) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_USER_PRINT); + } + updateInterfaceWithMessages(updates.user_id, objArr); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + } + }); + } else { + final boolean printUpdate = updatePrintingUsersWithNewMessages(-updates.chat_id, objArr); + if (printUpdate) { + updatePrintingStrings(); + } + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + if (printUpdate) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_USER_PRINT); + } + + updateInterfaceWithMessages(-updates.chat_id, objArr); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + } + }); + } + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { @Override public void run() { @@ -2805,78 +2948,101 @@ public class MessagesController implements NotificationCenter.NotificationCenter } }); MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); - } else if (MessagesStorage.lastSeqValue != updates.seq) { - FileLog.e("tmessages", "need get diff TL_updateShortMessage, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq); - if (gettingDifference || updatesStartWaitTime == 0 || updatesStartWaitTime != 0 && updatesStartWaitTime + 1500 > System.currentTimeMillis()) { - if (updatesStartWaitTime == 0) { - updatesStartWaitTime = System.currentTimeMillis(); + } else if (MessagesStorage.lastPtsValue != updates.pts) { + FileLog.e("tmessages", "need get diff short message, pts: " + MessagesStorage.lastPtsValue + " " + updates.pts + " count = " + updates.pts_count); + if (gettingDifference || updatesStartWaitTimePts == 0 || updatesStartWaitTimePts != 0 && updatesStartWaitTimePts + 1500 > System.currentTimeMillis()) { + if (updatesStartWaitTimePts == 0) { + updatesStartWaitTimePts = System.currentTimeMillis(); } - FileLog.e("tmessages", "add TL_updateShortMessage to queue"); - updatesQueue.add(updates); - addedToQueue = true; + FileLog.e("tmessages", "add short message to queue"); + updatesQueuePts.add(updates); } else { needGetDiff = true; } } } - } else if (updates instanceof TLRPC.TL_updatesCombined) { - if (MessagesStorage.lastSeqValue + 1 == updates.seq_start || MessagesStorage.lastSeqValue == updates.seq_start) { - MessagesStorage.getInstance().putUsersAndChats(updates.users, updates.chats, true, true); - int lastPtsValue = MessagesStorage.lastPtsValue; - int lastQtsValue = MessagesStorage.lastQtsValue; - if (!processUpdateArray(updates.updates, updates.users, updates.chats)) { - MessagesStorage.lastPtsValue = lastPtsValue; - MessagesStorage.lastQtsValue = lastQtsValue; - FileLog.e("tmessages", "need get diff inner TL_updatesCombined, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq); - needGetDiff = true; - } else { - MessagesStorage.lastDateValue = updates.date; - MessagesStorage.lastSeqValue = updates.seq; - if (MessagesStorage.lastQtsValue != lastQtsValue) { + } else if (updates instanceof TLRPC.TL_updatesCombined || updates instanceof TLRPC.TL_updates) { + MessagesStorage.getInstance().putUsersAndChats(updates.users, updates.chats, true, true); + int lastQtsValue = MessagesStorage.lastQtsValue; + for (int a = 0; a < updates.updates.size(); a++) { + TLRPC.Update update = updates.updates.get(a); + if (update instanceof TLRPC.TL_updateNewMessage || update instanceof TLRPC.TL_updateReadMessages || update instanceof TLRPC.TL_updateReadHistoryInbox || + update instanceof TLRPC.TL_updateReadHistoryOutbox || update instanceof TLRPC.TL_updateDeleteMessages) { + TLRPC.TL_updates updatesNew = new TLRPC.TL_updates(); + updatesNew.updates.add(update); + updatesNew.pts = update.pts; + updatesNew.pts_count = update.pts_count; + if (MessagesStorage.lastPtsValue + update.pts_count == update.pts) { + if (!processUpdateArray(updatesNew.updates, updates.users, updates.chats)) { + FileLog.e("tmessages", "need get diff inner TL_updates, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq); + needGetDiff = true; + } else { + MessagesStorage.lastPtsValue = update.pts; + } + } else if (MessagesStorage.lastPtsValue != update.pts) { + FileLog.e("tmessages", update + " need get diff, pts: " + MessagesStorage.lastPtsValue + " " + update.pts + " count = " + update.pts_count); + if (gettingDifference || updatesStartWaitTimePts == 0 || updatesStartWaitTimePts != 0 && updatesStartWaitTimePts + 1500 > System.currentTimeMillis()) { + if (updatesStartWaitTimePts == 0) { + updatesStartWaitTimePts = System.currentTimeMillis(); + } + FileLog.e("tmessages", "add short message to queue"); + updatesQueuePts.add(updatesNew); + } else { + needGetDiff = true; + } + } + } else if (update instanceof TLRPC.TL_updateNewEncryptedMessage) { + TLRPC.TL_updates updatesNew = new TLRPC.TL_updates(); + updatesNew.updates.add(update); + updatesNew.qts = update.qts; + if (MessagesStorage.lastQtsValue == 0 || MessagesStorage.lastQtsValue + 1 == update.qts) { + processUpdateArray(updatesNew.updates, updates.users, updates.chats); + MessagesStorage.lastQtsValue = update.qts; needReceivedQueue = true; + } else if (MessagesStorage.lastPtsValue != update.qts) { + FileLog.e("tmessages", update + " need get diff, qts: " + MessagesStorage.lastQtsValue + " " + update.qts); + if (gettingDifference || updatesStartWaitTimeQts == 0 || updatesStartWaitTimeQts != 0 && updatesStartWaitTimeQts + 1500 > System.currentTimeMillis()) { + if (updatesStartWaitTimeQts == 0) { + updatesStartWaitTimeQts = System.currentTimeMillis(); + } + FileLog.e("tmessages", "add short message to queue"); + updatesQueueQts.add(updatesNew); + } else { + needGetDiff = true; + } } - } - } else { - FileLog.e("tmessages", "need get diff TL_updatesCombined, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq_start); - if (gettingDifference || updatesStartWaitTime == 0 || updatesStartWaitTime != 0 && updatesStartWaitTime + 1500 > System.currentTimeMillis()) { - if (updatesStartWaitTime == 0) { - updatesStartWaitTime = System.currentTimeMillis(); - } - FileLog.e("tmessages", "add TL_updatesCombined to queue"); - updatesQueue.add(updates); - addedToQueue = true; } else { - needGetDiff = true; + continue; } + updates.updates.remove(a); + a--; } - } else if (updates instanceof TLRPC.TL_updates) { - if (MessagesStorage.lastSeqValue + 1 == updates.seq || updates.seq == 0 || updates.seq == MessagesStorage.lastSeqValue) { - MessagesStorage.getInstance().putUsersAndChats(updates.users, updates.chats, true, true); - int lastPtsValue = MessagesStorage.lastPtsValue; - int lastQtsValue = MessagesStorage.lastQtsValue; - if (!processUpdateArray(updates.updates, updates.users, updates.chats)) { - needGetDiff = true; - MessagesStorage.lastPtsValue = lastPtsValue; - MessagesStorage.lastQtsValue = lastQtsValue; - FileLog.e("tmessages", "need get diff inner TL_updates, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq); - } else { - MessagesStorage.lastDateValue = updates.date; - if (updates.seq != 0) { - MessagesStorage.lastSeqValue = updates.seq; - } - if (MessagesStorage.lastQtsValue != lastQtsValue) { - needReceivedQueue = true; - } + + boolean processUpdate = false; + if (updates instanceof TLRPC.TL_updatesCombined) { + processUpdate = MessagesStorage.lastSeqValue + 1 == updates.seq_start || MessagesStorage.lastSeqValue == updates.seq_start; + } else { + processUpdate = MessagesStorage.lastSeqValue + 1 == updates.seq || updates.seq == 0 || updates.seq == MessagesStorage.lastSeqValue; + } + if (processUpdate) { + processUpdateArray(updates.updates, updates.users, updates.chats); + MessagesStorage.lastDateValue = updates.date; + if (updates.seq != 0) { + MessagesStorage.lastSeqValue = updates.seq; } } else { - FileLog.e("tmessages", "need get diff TL_updates, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq); - if (gettingDifference || updatesStartWaitTime == 0 || updatesStartWaitTime != 0 && updatesStartWaitTime + 1500 > System.currentTimeMillis()) { - if (updatesStartWaitTime == 0) { - updatesStartWaitTime = System.currentTimeMillis(); + if (updates instanceof TLRPC.TL_updatesCombined) { + FileLog.e("tmessages", "need get diff TL_updatesCombined, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq_start); + } else { + FileLog.e("tmessages", "need get diff TL_updates, seq: " + MessagesStorage.lastSeqValue + " " + updates.seq); + } + + if (gettingDifference || updatesStartWaitTimeSeq == 0 || updatesStartWaitTimeSeq != 0 && updatesStartWaitTimeSeq + 1500 > System.currentTimeMillis()) { + if (updatesStartWaitTimeSeq == 0) { + updatesStartWaitTimeSeq = System.currentTimeMillis(); } - FileLog.e("tmessages", "add TL_updates to queue"); - updatesQueue.add(updates); - addedToQueue = true; + FileLog.e("tmessages", "add TL_updates/Combined to queue"); + updatesQueueSeq.add(updates); } else { needGetDiff = true; } @@ -2884,14 +3050,30 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (updates instanceof TLRPC.TL_updatesTooLong) { FileLog.e("tmessages", "need get diff TL_updatesTooLong"); needGetDiff = true; - } else if (updates instanceof UserActionUpdates) { + } else if (updates instanceof UserActionUpdatesSeq) { MessagesStorage.lastSeqValue = updates.seq; + } else if (updates instanceof UserActionUpdatesPts) { + MessagesStorage.lastPtsValue = updates.pts; } SecretChatHelper.getInstance().processPendingEncMessages(); - if (needGetDiff && !fromQueue) { - getDifference(); - } else if (!fromQueue && !updatesQueue.isEmpty()) { - processUpdatesQueue(0); + if (!fromQueue) { + if (needGetDiff) { + getDifference(); + } else { + for (int a = 0; a < 3; a++) { + ArrayList updatesQueue = null; + if (a == 0) { + updatesQueue = updatesQueueSeq; + } else if (a == 1) { + updatesQueue = updatesQueuePts; + } else if (a == 2) { + updatesQueue = updatesQueueQts; + } + if (!updatesQueue.isEmpty()) { + processUpdatesQueue(a, 0); + } + } + } } if (needReceivedQueue) { TLRPC.TL_messages_receivedQueue req = new TLRPC.TL_messages_receivedQueue(); @@ -2914,29 +3096,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter MessagesStorage.getInstance().saveDiffParams(MessagesStorage.lastSeqValue, MessagesStorage.lastPtsValue, MessagesStorage.lastDateValue, MessagesStorage.lastQtsValue); } - private boolean isNotifySettingsMuted(TLRPC.PeerNotifySettings settings) { - return settings instanceof TLRPC.TL_peerNotifySettings && settings.mute_until > ConnectionsManager.getInstance().getCurrentTime(); - } - - public boolean isDialogMuted(long dialog_id) { - /*TLRPC.TL_dialog dialog = dialogs_dict.get(dialog_id); - if (dialog != null) { - return isNotifySettingsMuted(dialog.notify_settings); - } else {*/ - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); - int mute_type = preferences.getInt("notify2_" + dialog_id, 0); - if (mute_type == 2) { - return true; - } else if (mute_type == 3) { - int mute_until = preferences.getInt("notifyuntil_" + dialog_id, 0); - if (mute_until >= ConnectionsManager.getInstance().getCurrentTime()) { - return true; - } - } - //} - return false; - } - public boolean processUpdateArray(ArrayList updates, final ArrayList usersArr, final ArrayList chatsArr) { if (updates.isEmpty()) { return true; @@ -2946,7 +3105,8 @@ public class MessagesController implements NotificationCenter.NotificationCenter final HashMap> messages = new HashMap<>(); final ArrayList pushMessages = new ArrayList<>(); final ArrayList messagesArr = new ArrayList<>(); - final ArrayList markAsReadMessages = new ArrayList<>(); + final HashMap markAsReadMessagesInbox = new HashMap<>(); + final HashMap markAsReadMessagesOutbox = new HashMap<>(); final HashMap markAsReadEncrypted = new HashMap<>(); final ArrayList deletedMessages = new ArrayList<>(); boolean printChanged = false; @@ -3026,18 +3186,27 @@ public class MessagesController implements NotificationCenter.NotificationCenter messages.put(uid, arr); } arr.add(obj); - MessagesStorage.lastPtsValue = update.pts; if (!obj.isFromMe() && obj.isUnread()) { pushMessages.add(obj); } } else if (update instanceof TLRPC.TL_updateReadMessages) { - markAsReadMessages.addAll(update.messages); - MessagesStorage.lastPtsValue = update.pts; + //markAsReadMessages.addAll(update.messages); disabled for now + } else if (update instanceof TLRPC.TL_updateReadHistoryInbox) { + TLRPC.Peer peer = ((TLRPC.TL_updateReadHistoryInbox) update).peer; + if (peer.chat_id != 0) { + markAsReadMessagesInbox.put(-peer.chat_id, update.max_id); + } else { + markAsReadMessagesInbox.put(peer.user_id, update.max_id); + } + } else if (update instanceof TLRPC.TL_updateReadHistoryOutbox) { + TLRPC.Peer peer = ((TLRPC.TL_updateReadHistoryOutbox) update).peer; + if (peer.chat_id != 0) { + markAsReadMessagesOutbox.put(-peer.chat_id, update.max_id); + } else { + markAsReadMessagesOutbox.put(peer.user_id, update.max_id); + } } else if (update instanceof TLRPC.TL_updateDeleteMessages) { deletedMessages.addAll(update.messages); - MessagesStorage.lastPtsValue = update.pts; - } else if (update instanceof TLRPC.TL_updateRestoreMessages) { - MessagesStorage.lastPtsValue = update.pts; } else if (update instanceof TLRPC.TL_updateUserTyping || update instanceof TLRPC.TL_updateChatUserTyping) { if (update.action instanceof TLRPC.TL_sendMessageTypingAction && update.user_id != UserConfig.getClientUserId()) { long uid = -update.chat_id; @@ -3106,7 +3275,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter pushMessages.add(obj); } } else if (update instanceof TLRPC.TL_updateContactLink) { - if (update.my_link instanceof TLRPC.TL_contacts_myLinkContact || update.my_link instanceof TLRPC.TL_contacts_myLinkRequested && update.my_link.contact) { + if (update.my_link instanceof TLRPC.TL_contactLinkContact) { int idx = contactsIds.indexOf(-update.user_id); if (idx != -1) { contactsIds.remove(idx); @@ -3151,8 +3320,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } else if (update instanceof TLRPC.TL_updateNewGeoChatMessage) { //DEPRECATED } else if (update instanceof TLRPC.TL_updateNewEncryptedMessage) { - MessagesStorage.lastQtsValue = update.qts; - ArrayList decryptedMessages = SecretChatHelper.getInstance().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; @@ -3198,7 +3366,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } else if (update instanceof TLRPC.TL_updateEncryptedMessagesRead) { markAsReadEncrypted.put(update.chat_id, Math.max(update.max_date, update.date)); - tasks.add((TLRPC.TL_updateEncryptedMessagesRead)update); + tasks.add((TLRPC.TL_updateEncryptedMessagesRead) update); } else if (update instanceof TLRPC.TL_updateChatParticipantAdd) { MessagesStorage.getInstance().updateChatInfo(update.chat_id, update.user_id, false, update.inviter_id, update.version); } else if (update instanceof TLRPC.TL_updateChatParticipantDelete) { @@ -3338,6 +3506,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter } } else if (update instanceof TLRPC.TL_updateUserName) { if (currentUser != null) { + if (currentUser.username != null && currentUser.username.length() > 0) { + usersByUsernames.remove(currentUser.username); + } + if (update.username != null && update.username.length() > 0) { + usersByUsernames.put(update.username, currentUser); + } currentUser.first_name = update.first_name; currentUser.last_name = update.last_name; currentUser.username = update.username; @@ -3462,15 +3636,27 @@ public class MessagesController implements NotificationCenter.NotificationCenter @Override public void run() { int updateMask = 0; - if (!markAsReadMessages.isEmpty()) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesRead, markAsReadMessages); - NotificationsController.getInstance().processReadMessages(markAsReadMessages, 0, 0, 0, false); - - for (Integer id : markAsReadMessages) { - MessageObject obj = dialogMessage.get(id); - if (obj != null) { - obj.setIsRead(); - updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE; + if (!markAsReadMessagesInbox.isEmpty() || !markAsReadMessagesOutbox.isEmpty()) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesRead, markAsReadMessagesInbox, markAsReadMessagesOutbox); + NotificationsController.getInstance().processReadMessages(markAsReadMessagesInbox, 0, 0, 0, false); + for (HashMap.Entry entry : markAsReadMessagesInbox.entrySet()) { + TLRPC.TL_dialog dialog = dialogs_dict.get((long) entry.getKey()); + if (dialog != null && dialog.top_message <= entry.getValue()) { + MessageObject obj = dialogMessage.get(dialog.top_message); + if (obj != null) { + obj.setIsRead(); + updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE; + } + } + } + for (HashMap.Entry entry : markAsReadMessagesOutbox.entrySet()) { + TLRPC.TL_dialog dialog = dialogs_dict.get((long) entry.getKey()); + if (dialog != null && dialog.top_message <= entry.getValue()) { + MessageObject obj = dialogMessage.get(dialog.top_message); + if (obj != null) { + obj.setIsRead(); + updateMask |= UPDATE_MASK_READ_DIALOG_MESSAGE; + } } } } @@ -3505,11 +3691,11 @@ public class MessagesController implements NotificationCenter.NotificationCenter } }); - if (!markAsReadMessages.isEmpty() || !markAsReadEncrypted.isEmpty()) { - if (!markAsReadMessages.isEmpty()) { - MessagesStorage.getInstance().updateDialogsWithReadedMessages(markAsReadMessages, true); + if (!markAsReadMessagesInbox.isEmpty() || !markAsReadMessagesOutbox.isEmpty() || !markAsReadEncrypted.isEmpty()) { + if (!markAsReadMessagesInbox.isEmpty() || !markAsReadMessagesOutbox.isEmpty()) { + MessagesStorage.getInstance().updateDialogsWithReadedMessages(markAsReadMessagesInbox, true); } - MessagesStorage.getInstance().markMessagesAsRead(markAsReadMessages, markAsReadEncrypted, true); + MessagesStorage.getInstance().markMessagesAsRead(markAsReadMessagesInbox, markAsReadMessagesOutbox, markAsReadEncrypted, true); } if (!deletedMessages.isEmpty()) { MessagesStorage.getInstance().markMessagesAsDeleted(deletedMessages, true); @@ -3526,6 +3712,24 @@ public class MessagesController implements NotificationCenter.NotificationCenter return true; } + private boolean isNotifySettingsMuted(TLRPC.PeerNotifySettings settings) { + return settings instanceof TLRPC.TL_peerNotifySettings && settings.mute_until > ConnectionsManager.getInstance().getCurrentTime(); + } + + public boolean isDialogMuted(long dialog_id) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); + int mute_type = preferences.getInt("notify2_" + dialog_id, 0); + if (mute_type == 2) { + return true; + } else if (mute_type == 3) { + int mute_until = preferences.getInt("notifyuntil_" + dialog_id, 0); + if (mute_until >= ConnectionsManager.getInstance().getCurrentTime()) { + return true; + } + } + return false; + } + private boolean updatePrintingUsersWithNewMessages(long uid, ArrayList messages) { if (uid > 0) { ArrayList arr = printingUsers.get(uid); @@ -3576,7 +3780,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter NotificationCenter.getInstance().postNotificationName(NotificationCenter.didReceivedNewMessages, uid, messages); for (MessageObject message : messages) { - if (lastMessage == null || (!isEncryptedChat && message.messageOwner.id > lastMessage.messageOwner.id || isEncryptedChat && message.messageOwner.id < lastMessage.messageOwner.id) || message.messageOwner.date > lastMessage.messageOwner.date) { + if (lastMessage == null || (!isEncryptedChat && message.getId() > lastMessage.getId() || isEncryptedChat && message.getId() < lastMessage.getId()) || message.messageOwner.date > lastMessage.messageOwner.date) { lastMessage = message; } } @@ -3588,17 +3792,17 @@ public class MessagesController implements NotificationCenter.NotificationCenter dialog = new TLRPC.TL_dialog(); dialog.id = uid; dialog.unread_count = 0; - dialog.top_message = lastMessage.messageOwner.id; + dialog.top_message = lastMessage.getId(); dialog.last_message_date = lastMessage.messageOwner.date; dialogs_dict.put(uid, dialog); dialogs.add(dialog); - dialogMessage.put(lastMessage.messageOwner.id, lastMessage); + dialogMessage.put(lastMessage.getId(), lastMessage); changed = true; } } else { boolean change = false; - if (dialog.top_message > 0 && lastMessage.messageOwner.id > 0 && lastMessage.messageOwner.id > dialog.top_message || - dialog.top_message < 0 && lastMessage.messageOwner.id < 0 && lastMessage.messageOwner.id < dialog.top_message) { + if (dialog.top_message > 0 && lastMessage.getId() > 0 && lastMessage.getId() > dialog.top_message || + dialog.top_message < 0 && lastMessage.getId() < 0 && lastMessage.getId() < dialog.top_message) { change = true; } else { MessageObject currentDialogMessage = dialogMessage.get(dialog.top_message); @@ -3614,12 +3818,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter } if (change) { dialogMessage.remove(dialog.top_message); - dialog.top_message = lastMessage.messageOwner.id; + dialog.top_message = lastMessage.getId(); if (!isBroadcast) { dialog.last_message_date = lastMessage.messageOwner.date; changed = true; } - dialogMessage.put(lastMessage.messageOwner.id, lastMessage); + dialogMessage.put(lastMessage.getId(), lastMessage); } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java index 160447dec..15daba188 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java @@ -103,7 +103,7 @@ public class MessagesStorage { database.executeFast("PRAGMA temp_store = 1").stepThis().dispose(); if (createTable) { 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 messages(mid INTEGER PRIMARY KEY, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER, replydata BLOB)").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, 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(); @@ -162,7 +162,7 @@ public class MessagesStorage { database.executeFast("CREATE TABLE keyvalue(id TEXT PRIMARY KEY, value TEXT)").stepThis().dispose(); //version - database.executeFast("PRAGMA user_version = 13").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 14").stepThis().dispose(); } else { try { SQLiteCursor cursor = database.queryFinalized("SELECT seq, pts, date, qts, lsv, sg, pbytes FROM params WHERE id = 1"); @@ -193,7 +193,7 @@ public class MessagesStorage { } } int version = database.executeInt("PRAGMA user_version"); - if (version < 13) { + if (version < 14) { updateDbToLastVersion(version); } } @@ -368,6 +368,11 @@ public class MessagesStorage { database.executeFast("PRAGMA user_version = 13").stepThis().dispose(); version = 13; } + if (version == 13 && version < 14) { + database.executeFast("ALTER TABLE messages ADD COLUMN replydata BLOB default NULL").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 14").stepThis().dispose(); + version = 14; + } } catch (Exception e) { FileLog.e("tmessages", e); } @@ -753,7 +758,7 @@ public class MessagesStorage { try { ArrayList ids = new ArrayList<>(); ArrayList users = new ArrayList<>(); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM blocked_users WHERE 1")); + SQLiteCursor cursor = database.queryFinalized("SELECT * FROM blocked_users WHERE 1"); StringBuilder usersToLoad = new StringBuilder(); while (cursor.next()) { int user_id = cursor.intValue(0); @@ -840,7 +845,7 @@ public class MessagesStorage { } if ((int) did == 0) { - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM messages WHERE uid = " + did)); + SQLiteCursor cursor = database.queryFinalized("SELECT data FROM messages WHERE uid = " + did); ArrayList filesToDelete = new ArrayList<>(); try { while (cursor.next()) { @@ -1085,20 +1090,16 @@ public class MessagesStorage { }); } - private void updateDialogsWithReadedMessagesInternal(final ArrayList messages) { - if (Thread.currentThread().getId() != storageQueue.getId()) { - throw new RuntimeException("wrong db thread"); - } + private void updateDialogsWithReadedMessagesInternal(final ArrayList messages, final HashMap inbox) { try { HashMap dialogsToUpdate = new HashMap<>(); + StringBuilder dialogsToReload = new StringBuilder(); + if (messages != null && !messages.isEmpty()) { - StringBuilder dialogsToReload = new StringBuilder(); String ids = TextUtils.join(",", messages); - int totalCount = 0; SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, read_state, out FROM messages WHERE mid IN(%s)", ids)); while (cursor.next()) { int out = cursor.intValue(2); - totalCount++; if (out != 0) { continue; } @@ -1119,8 +1120,26 @@ public class MessagesStorage { } } cursor.dispose(); + } else if (inbox != null && !inbox.isEmpty()) { + for (HashMap.Entry entry : inbox.entrySet()) { + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM messages WHERE uid = %d AND mid <= %d AND read_state = 0 AND out = 0", entry.getKey(), entry.getValue())); + if (cursor.next()) { + int count = cursor.intValue(0); + if (count == 0) { + continue; + } + dialogsToUpdate.put((long) entry.getKey(), count); + if (dialogsToReload.length() != 0) { + dialogsToReload.append(","); + } + dialogsToReload.append(entry.getKey()); + } + cursor.dispose(); + } + } - cursor = database.queryFinalized(String.format(Locale.US, "SELECT did, unread_count FROM dialogs WHERE did IN(%s)", dialogsToReload.toString())); + if (dialogsToReload.length() > 0) { + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT did, unread_count FROM dialogs WHERE did IN(%s)", dialogsToReload.toString())); while (cursor.next()) { long did = cursor.longValue(0); int count = cursor.intValue(1); @@ -1153,19 +1172,19 @@ public class MessagesStorage { } } - public void updateDialogsWithReadedMessages(final ArrayList messages, boolean useQueue) { - if (messages.isEmpty()) { + public void updateDialogsWithReadedMessages(final HashMap inbox, boolean useQueue) { + if (inbox.isEmpty()) { return; } if (useQueue) { storageQueue.postRunnable(new Runnable() { @Override public void run() { - updateDialogsWithReadedMessagesInternal(messages); + updateDialogsWithReadedMessagesInternal(null, inbox); } }); } else { - updateDialogsWithReadedMessagesInternal(messages); + updateDialogsWithReadedMessagesInternal(null, inbox); } } @@ -1710,6 +1729,8 @@ public class MessagesStorage { try { ArrayList loadedUsers = new ArrayList<>(); ArrayList fromUser = new ArrayList<>(); + ArrayList replyMessages = new ArrayList<>(); + HashMap> replyMessageOwners = new HashMap<>(); SQLiteCursor cursor = null; int lower_id = (int)dialog_id; @@ -1731,18 +1752,18 @@ public class MessagesStorage { cursor.dispose(); if (containMessage) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " + - "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d)", dialog_id, max_id, count_query / 2, dialog_id, max_id, count_query / 2 - 1)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " + + "SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d)", dialog_id, max_id, count_query / 2, dialog_id, max_id, count_query / 2 - 1)); } else { cursor = null; } } else if (load_type == 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date >= %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", dialog_id, minDate, max_id, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date >= %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d", dialog_id, minDate, max_id, count_query)); } else if (minDate != 0) { if (max_id != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d AND m.mid < %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", dialog_id, minDate, max_id, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d AND m.mid < %d ORDER BY m.date DESC, m.mid DESC LIMIT %d", dialog_id, minDate, max_id, count_query)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query)); } } else { if (load_type == 2) { @@ -1778,16 +1799,16 @@ public class MessagesStorage { offset_query = count_unread - count_query; count_query += 10; } - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, offset_query, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d", dialog_id, offset_query, count_query)); } } else { if (load_type == 1) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid < %d ORDER BY m.mid DESC LIMIT %d", dialog_id, max_id, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid < %d ORDER BY m.mid DESC LIMIT %d", dialog_id, max_id, count_query)); } else if (minDate != 0) { if (max_id != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.mid ASC LIMIT %d", dialog_id, max_id, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.mid ASC LIMIT %d", dialog_id, max_id, count_query)); } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.mid ASC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.mid ASC LIMIT %d,%d", dialog_id, minDate, offset_query, count_query)); } } else { if (load_type == 2) { @@ -1823,7 +1844,7 @@ public class MessagesStorage { offset_query = count_unread - count_query; count_query += 10; } - cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.mid ASC LIMIT %d,%d", dialog_id, offset_query, count_query)); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.mid ASC LIMIT %d,%d", dialog_id, offset_query, count_query)); } } if (cursor != null) { @@ -1849,6 +1870,43 @@ public class MessagesStorage { if (message.fwd_from_id != 0) { fromUser.add(message.fwd_from_id); } + if (message.reply_to_msg_id != 0) { + boolean ok = false; + if (!cursor.isNull(6)) { + ByteBufferDesc data2 = buffersStorage.getFreeBuffer(cursor.byteArrayLength(6)); + if (data2 != null && cursor.byteBufferValue(6, data2.buffer) != 0) { + message.replyMessage = (TLRPC.Message) TLClassStore.Instance().TLdeserialize(data2, data2.readInt32()); + if (message.replyMessage != null) { + fromUser.add(message.replyMessage.from_id); + if (message.replyMessage.action != null && message.replyMessage.action.user_id != 0) { + fromUser.add(message.replyMessage.action.user_id); + } + if (message.replyMessage.media != null && message.replyMessage.media.user_id != 0) { + fromUser.add(message.replyMessage.media.user_id); + } + if (message.replyMessage.media != null && message.replyMessage.media.audio != null && message.replyMessage.media.audio.user_id != 0) { + fromUser.add(message.replyMessage.media.audio.user_id); + } + if (message.replyMessage.fwd_from_id != 0) { + fromUser.add(message.replyMessage.fwd_from_id); + } + ok = true; + } + } + buffersStorage.reuseFreeBuffer(data2); + } + if (!ok) { + if (!replyMessages.contains(message.reply_to_msg_id)) { + replyMessages.add(message.reply_to_msg_id); + } + ArrayList messages = replyMessageOwners.get(message.reply_to_msg_id); + if (messages == null) { + messages = new ArrayList<>(); + replyMessageOwners.put(message.reply_to_msg_id, messages); + } + messages.add(message); + } + } message.send_state = cursor.intValue(2); if (!MessageObject.isUnread(message) && lower_id != 0 || message.id > 0) { message.send_state = 0; @@ -1899,33 +1957,39 @@ public class MessagesStorage { } }); - /*ArrayList> holes = getHoles(dialog_id); - if (holes != null && !res.messages.isEmpty()) { - int start = res.messages.get(res.messages.size() - 1).id; - int end = res.messages.get(0).id; - for (Range range : holes) { - if (range.contains(start) && range.contains(end)) { - res.messages.clear(); - } else if (range.contains(start)) { - while (!res.messages.isEmpty() && range.contains(res.messages.get(res.messages.size() - 1).id)) { - res.messages.remove(res.messages.size() - 1); + if (!replyMessages.isEmpty()) { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid, date FROM messages WHERE mid IN(%s)", TextUtils.join(",", replyMessages))); + while (cursor.next()) { + ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0)); + if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { + TLRPC.Message message = (TLRPC.Message) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); + message.id = cursor.intValue(1); + message.date = cursor.intValue(2); + message.dialog_id = dialog_id; + fromUser.add(message.from_id); + if (message.action != null && message.action.user_id != 0) { + fromUser.add(message.action.user_id); } - if (!res.messages.isEmpty()) { - start = res.messages.get(res.messages.size() - 1).id; + if (message.media != null && message.media.user_id != 0) { + fromUser.add(message.media.user_id); } - } else if (range.contains(end)) { - while (!res.messages.isEmpty() && range.contains(res.messages.get(0).id)) { - res.messages.remove(0); + if (message.media != null && message.media.audio != null && message.media.audio.user_id != 0) { + fromUser.add(message.media.audio.user_id); } - if (!res.messages.isEmpty()) { - end = res.messages.get(0).id; + if (message.fwd_from_id != 0) { + fromUser.add(message.fwd_from_id); + } + ArrayList arrayList = replyMessageOwners.get(message.id); + if (arrayList != null) { + for (TLRPC.Message m : arrayList) { + m.replyMessage = message; + } } - } else if (start >= ) - if (res.messages.isEmpty()) { - break; } + buffersStorage.reuseFreeBuffer(data); } - }*/ + cursor.dispose(); + } StringBuilder usersToLoad = new StringBuilder(); for (int uid : fromUser) { @@ -2590,7 +2654,7 @@ public class MessagesStorage { HashMap messagesMediaIdsMap = new HashMap<>(); StringBuilder messageIds = new StringBuilder(); StringBuilder messageMediaIds = new StringBuilder(); - SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)"); SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)"); SQLitePreparedStatement state3 = database.executeFast("REPLACE INTO randoms VALUES(?, ?)"); SQLitePreparedStatement state4 = database.executeFast("REPLACE INTO download_queue VALUES(?, ?, ?, ?)"); @@ -3164,14 +3228,20 @@ public class MessagesStorage { } } - private void markMessagesAsReadInternal(final ArrayList messages, HashMap encryptedMessages) { + private void markMessagesAsReadInternal(HashMap inbox, HashMap outbox, HashMap encryptedMessages) { if (Thread.currentThread().getId() != storageQueue.getId()) { throw new RuntimeException("wrong db thread"); } try { - if (messages != null && !messages.isEmpty()) { - String ids = TextUtils.join(",", messages); - database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = 1 WHERE mid IN(%s)", ids)).stepThis().dispose(); + if (inbox != null) { + for (HashMap.Entry entry : inbox.entrySet()) { + database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = 1 WHERE uid = %d AND mid <= %d AND read_state = 0 AND out = 0", entry.getKey(), entry.getValue())).stepThis().dispose(); + } + } + if (outbox != null) { + for (HashMap.Entry entry : outbox.entrySet()) { + database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = 1 WHERE uid = %d AND mid <= %d AND read_state = 0 AND out = 1", entry.getKey(), entry.getValue())).stepThis().dispose(); + } } if (encryptedMessages != null && !encryptedMessages.isEmpty()) { for (HashMap.Entry entry : encryptedMessages.entrySet()) { @@ -3190,16 +3260,16 @@ public class MessagesStorage { } } - public void markMessagesAsRead(final ArrayList messages, final HashMap encryptedMessages, boolean useQueue) { + public void markMessagesAsRead(final HashMap inbox, final HashMap outbox, final HashMap encryptedMessages, boolean useQueue) { if (useQueue) { storageQueue.postRunnable(new Runnable() { @Override public void run() { - markMessagesAsReadInternal(messages, encryptedMessages); + markMessagesAsReadInternal(inbox, outbox, encryptedMessages); } }); } else { - markMessagesAsReadInternal(messages, encryptedMessages); + markMessagesAsReadInternal(inbox, outbox, encryptedMessages); } } @@ -3231,7 +3301,7 @@ public class MessagesStorage { NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDeleted, mids); } }); - MessagesStorage.getInstance().updateDialogsWithReadedMessagesInternal(mids); + MessagesStorage.getInstance().updateDialogsWithReadedMessagesInternal(mids, null); MessagesStorage.getInstance().markMessagesAsDeletedInternal(mids); MessagesStorage.getInstance().updateDialogsWithDeletedMessagesInternal(mids); } @@ -3472,7 +3542,7 @@ public class MessagesStorage { try { database.beginTransaction(); if (!messages.messages.isEmpty()) { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)"); SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)"); for (TLRPC.Message message : messages.messages) { fixUnsupportedMedia(message); @@ -3644,7 +3714,7 @@ public class MessagesStorage { } if (!dialogs.dialogs.isEmpty()) { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"); + SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)"); SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO dialogs(did, date, unread_count, last_mid) VALUES(?, ?, ?, ?)"); SQLitePreparedStatement state3 = database.executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)"); SQLitePreparedStatement state4 = database.executeFast("REPLACE INTO dialog_settings VALUES(?, ?)"); diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java index 5ae1cae0b..b21a9fd2e 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java @@ -51,6 +51,7 @@ public class NotificationCenter { public static final int didSetPasscode = totalEvents++; public static final int screenStateChanged = totalEvents++; public static final int appSwitchedToForeground = totalEvents++; + public static final int didLoadedReplyMessages = totalEvents++; public static final int httpFileDidLoaded = totalEvents++; public static final int httpFileDidFailedLoad = totalEvents++; @@ -109,7 +110,7 @@ public class NotificationCenter { } public interface NotificationCenterDelegate { - public abstract void didReceivedNotification(int id, Object... args); + void didReceivedNotification(int id, Object... args); } public void postNotificationName(int id, Object... args) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java index ea5942993..b5501c521 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java @@ -56,6 +56,7 @@ public class NotificationsController { private NotificationManagerCompat notificationManager = null; private HashMap pushDialogs = new HashMap<>(); private HashMap wearNoticationsIds = new HashMap<>(); + private HashMap pushDialogsOverrideMention = new HashMap<>(); private int wearNotificationId = 10000; public ArrayList popupMessages = new ArrayList<>(); private long openned_dialog_id = 0; @@ -313,7 +314,11 @@ public class NotificationsController { MessageObject lastMessageObject = pushMessages.get(0); long dialog_id = lastMessageObject.getDialogId(); - int mid = lastMessageObject.messageOwner.id; + long override_dialog_id = dialog_id; + if ((lastMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) { + override_dialog_id = lastMessageObject.messageOwner.from_id; + } + int mid = lastMessageObject.getId(); int chat_id = lastMessageObject.messageOwner.to_id.chat_id; int user_id = lastMessageObject.messageOwner.to_id.user_id; if (user_id == 0) { @@ -342,9 +347,9 @@ public class NotificationsController { int vibrate_override = 0; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); - int notify_override = preferences.getInt("notify2_" + dialog_id, 0); + int notify_override = preferences.getInt("notify2_" + override_dialog_id, 0); if (notify_override == 3) { - int mute_until = preferences.getInt("notifyuntil_" + dialog_id, 0); + int mute_until = preferences.getInt("notifyuntil_" + override_dialog_id, 0); if (mute_until >= ConnectionsManager.getInstance().getCurrentTime()) { notify_override = 2; } @@ -615,7 +620,7 @@ public class NotificationsController { for (long dialog_id : sortedDialogs) { ArrayList messageObjects = messagesByDialogs.get(dialog_id); - int max_id = messageObjects.get(0).messageOwner.id; + int max_id = messageObjects.get(0).getId(); TLRPC.Chat chat = null; TLRPC.User user = null; String name = null; @@ -737,19 +742,21 @@ public class NotificationsController { } } - public void processReadMessages(ArrayList readMessages, long dialog_id, int max_date, int max_id, boolean isPopup) { + public void processReadMessages(HashMap inbox, long dialog_id, int max_date, int max_id, boolean isPopup) { int oldCount = popupMessages.size(); - int oldCount2 = pushMessages.size(); - if (readMessages != null) { - for (Integer id : readMessages) { - MessageObject messageObject = pushMessagesDict.get(id); - if (messageObject != null) { - if (isPersonalMessage(messageObject)) { - personal_count--; + if (inbox != null) { + for (HashMap.Entry entry : inbox.entrySet()) { + for (int a = 0; a < pushMessages.size(); a++) { + MessageObject messageObject = pushMessages.get(a); + if (messageObject.getDialogId() == entry.getKey() && messageObject.getId() <= entry.getValue()) { + if (isPersonalMessage(messageObject)) { + personal_count--; + } + popupMessages.remove(messageObject); + pushMessagesDict.remove(messageObject.getId()); + pushMessages.remove(a); + a--; } - pushMessages.remove(messageObject); - popupMessages.remove(messageObject); - pushMessagesDict.remove(id); } } } @@ -764,11 +771,11 @@ public class NotificationsController { } } else { if (!isPopup) { - if (messageObject.messageOwner.id <= max_id || max_id < 0) { + if (messageObject.getId() <= max_id || max_id < 0) { remove = true; } } else { - if (messageObject.messageOwner.id == max_id || max_id < 0) { + if (messageObject.getId() == max_id || max_id < 0) { remove = true; } } @@ -779,7 +786,7 @@ public class NotificationsController { } pushMessages.remove(a); popupMessages.remove(messageObject); - pushMessagesDict.remove(messageObject.messageOwner.id); + pushMessagesDict.remove(messageObject.getId()); a--; } } @@ -802,13 +809,17 @@ public class NotificationsController { int popup = 0; for (MessageObject messageObject : messageObjects) { - if (pushMessagesDict.containsKey(messageObject.messageOwner.id)) { + if (pushMessagesDict.containsKey(messageObject.getId())) { continue; } long dialog_id = messageObject.getDialogId(); + long original_dialog_id = dialog_id; if (dialog_id == openned_dialog_id && ApplicationLoader.isScreenOn) { continue; } + if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) { + dialog_id = messageObject.messageOwner.from_id; + } if (isPersonalMessage(messageObject)) { personal_count++; } @@ -833,7 +844,10 @@ public class NotificationsController { popupMessages.add(0, messageObject); } pushMessages.add(0, messageObject); - pushMessagesDict.put(messageObject.messageOwner.id, messageObject); + pushMessagesDict.put(messageObject.getId(), messageObject); + if (original_dialog_id != dialog_id) { + pushDialogsOverrideMention.put(original_dialog_id, 1); + } } } @@ -866,6 +880,13 @@ public class NotificationsController { notify_override = 2; } } + if (notifyCheck) { + Integer override = pushDialogsOverrideMention.get(dialog_id); + if (override != null && override == 1) { + pushDialogsOverrideMention.put(dialog_id, 0); + notify_override = 1; + } + } boolean canAddValue = !(notify_override == 2 || (!preferences.getBoolean("EnableAll", true) || ((int)dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notify_override == 0); Integer currentCount = pushDialogs.get(dialog_id); @@ -883,6 +904,7 @@ public class NotificationsController { } if (newCount == 0) { pushDialogs.remove(dialog_id); + pushDialogsOverrideMention.remove(dialog_id); for (int a = 0; a < pushMessages.size(); a++) { MessageObject messageObject = pushMessages.get(a); if (messageObject.getDialogId() == dialog_id) { @@ -891,7 +913,7 @@ public class NotificationsController { } pushMessages.remove(a); a--; - pushMessagesDict.remove(messageObject.messageOwner.id); + pushMessagesDict.remove(messageObject.getId()); popupMessages.remove(messageObject); } } @@ -930,27 +952,6 @@ public class NotificationsController { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE); HashMap settingsCache = new HashMap<>(); - for (HashMap.Entry entry : dialogs.entrySet()) { - long dialog_id = entry.getKey(); - Boolean value = settingsCache.get(dialog_id); - if (value == null) { - int notify_override = preferences.getInt("notify2_" + dialog_id, 0); - if (notify_override == 3) { - int mute_until = preferences.getInt("notifyuntil_" + dialog_id, 0); - if (mute_until >= ConnectionsManager.getInstance().getCurrentTime()) { - notify_override = 2; - } - } - value = !(notify_override == 2 || (!preferences.getBoolean("EnableAll", true) || ((int) dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notify_override == 0); - settingsCache.put(dialog_id, value); - } - if (!value) { - continue; - } - int count = entry.getValue(); - pushDialogs.put(dialog_id, count); - total_unread_count += count; - } if (messages != null) { for (TLRPC.Message message : messages) { if (pushMessagesDict.containsKey(message.id)) { @@ -961,6 +962,10 @@ public class NotificationsController { personal_count++; } long dialog_id = messageObject.getDialogId(); + long original_dialog_id = dialog_id; + if ((messageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_MENTION) != 0) { + dialog_id = messageObject.messageOwner.from_id; + } Boolean value = settingsCache.get(dialog_id); if (value == null) { int notify_override = preferences.getInt("notify2_" + dialog_id, 0); @@ -976,10 +981,39 @@ public class NotificationsController { if (!value || dialog_id == openned_dialog_id && ApplicationLoader.isScreenOn) { continue; } - pushMessagesDict.put(messageObject.messageOwner.id, messageObject); + pushMessagesDict.put(messageObject.getId(), messageObject); pushMessages.add(0, messageObject); + if (original_dialog_id != dialog_id) { + pushDialogsOverrideMention.put(original_dialog_id, 1); + } } } + for (HashMap.Entry entry : dialogs.entrySet()) { + long dialog_id = entry.getKey(); + Boolean value = settingsCache.get(dialog_id); + if (value == null) { + int notify_override = preferences.getInt("notify2_" + dialog_id, 0); + if (notify_override == 3) { + int mute_until = preferences.getInt("notifyuntil_" + dialog_id, 0); + if (mute_until >= ConnectionsManager.getInstance().getCurrentTime()) { + notify_override = 2; + } + } + Integer override = pushDialogsOverrideMention.get(dialog_id); + if (override != null && override == 1) { + pushDialogsOverrideMention.put(dialog_id, 0); + notify_override = 1; + } + value = !(notify_override == 2 || (!preferences.getBoolean("EnableAll", true) || ((int) dialog_id < 0) && !preferences.getBoolean("EnableGroup", true)) && notify_override == 0); + settingsCache.put(dialog_id, value); + } + if (!value) { + continue; + } + int count = entry.getValue(); + pushDialogs.put(dialog_id, count); + total_unread_count += count; + } if (total_unread_count == 0) { popupMessages.clear(); NotificationCenter.getInstance().postNotificationName(NotificationCenter.pushMessagesUpdated); diff --git a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java index 4cb3e851d..ada7a6ac3 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java @@ -174,12 +174,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter for (int a = 0; a < arr.size(); a++) { DelayedMessage obj = arr.get(a); if (enc && obj.sendEncryptedRequest != null || !enc && obj.sendRequest != null) { - MessagesStorage.getInstance().markMessageAsSendError(obj.obj.messageOwner.id); + MessagesStorage.getInstance().markMessageAsSendError(obj.obj.getId()); obj.obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; arr.remove(a); a--; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, obj.obj.messageOwner.id); - processSentMessage(obj.obj.messageOwner.id); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, obj.obj.getId()); + processSentMessage(obj.obj.getId()); } } if (arr.isEmpty()) { @@ -244,12 +244,12 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter for (int a = 0; a < arr.size(); a++) { DelayedMessage message = arr.get(a); if (message.obj == messageObject) { - MessagesStorage.getInstance().markMessageAsSendError(message.obj.messageOwner.id); + MessagesStorage.getInstance().markMessageAsSendError(message.obj.getId()); message.obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; arr.remove(a); a--; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, message.obj.messageOwner.id); - processSentMessage(message.obj.messageOwner.id); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, message.obj.getId()); + processSentMessage(message.obj.getId()); } } if (arr.isEmpty()) { @@ -284,10 +284,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter NotificationCenter.getInstance().postNotificationName(NotificationCenter.updateMessageMedia, message.obj); } else { FileLog.e("tmessages", "can't load image " + message.httpLocation + " to file " + cacheFile.toString()); - MessagesStorage.getInstance().markMessageAsSendError(message.obj.messageOwner.id); + MessagesStorage.getInstance().markMessageAsSendError(message.obj.getId()); message.obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, message.obj.messageOwner.id); - processSentMessage(message.obj.messageOwner.id); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, message.obj.getId()); + processSentMessage(message.obj.getId()); } } }); @@ -339,10 +339,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ArrayList arr = delayedMessages.get(path); if (arr != null) { for (DelayedMessage message : arr) { - MessagesStorage.getInstance().markMessageAsSendError(message.obj.messageOwner.id); + MessagesStorage.getInstance().markMessageAsSendError(message.obj.getId()); message.obj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, message.obj.messageOwner.id); - processSentMessage(message.obj.messageOwner.id); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, message.obj.getId()); + processSentMessage(message.obj.getId()); } delayedMessages.remove(path); } @@ -356,7 +356,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter ArrayList messages = entry.getValue(); for (int a = 0; a < messages.size(); a++) { DelayedMessage message = messages.get(a); - if (message.obj.messageOwner.id == object.messageOwner.id) { + if (message.obj.getId() == object.getId()) { messages.remove(a); MediaController.getInstance().cancelVideoConvert(message.obj); if (messages.size() == 0) { @@ -378,22 +378,22 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter stopVideoService(keyToRemvoe); } ArrayList messages = new ArrayList<>(); - messages.add(object.messageOwner.id); + messages.add(object.getId()); MessagesController.getInstance().deleteMessages(messages, null, null); } public boolean retrySendMessage(MessageObject messageObject, boolean unsent) { - if (messageObject.messageOwner.id >= 0) { + if (messageObject.getId() >= 0) { return false; } if (messageObject.messageOwner.action instanceof TLRPC.TL_messageEncryptedAction) { int enc_id = (int) (messageObject.getDialogId() >> 32); TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat(enc_id); if (encryptedChat == null) { - MessagesStorage.getInstance().markMessageAsSendError(messageObject.messageOwner.id); + MessagesStorage.getInstance().markMessageAsSendError(messageObject.getId()); messageObject.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, messageObject.messageOwner.id); - processSentMessage(messageObject.messageOwner.id); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, messageObject.getId()); + processSentMessage(messageObject.getId()); return false; } if (messageObject.messageOwner.random_id == 0) { @@ -429,7 +429,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter return true; } if (unsent) { - unsentMessages.put(messageObject.messageOwner.id, messageObject); + unsentMessages.put(messageObject.getId(), messageObject); } sendMessage(messageObject); return true; @@ -449,75 +449,223 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } if (messageObject.messageOwner.media != null && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) { if (messageObject.messageOwner.media.photo instanceof TLRPC.TL_photo) { - sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, null, did); + sendMessage((TLRPC.TL_photo) messageObject.messageOwner.media.photo, null, null, did, messageObject.replyMessageObject); } else if (messageObject.messageOwner.media.audio instanceof TLRPC.TL_audio) { - sendMessage((TLRPC.TL_audio) messageObject.messageOwner.media.audio, messageObject.messageOwner.attachPath, did); + sendMessage((TLRPC.TL_audio) messageObject.messageOwner.media.audio, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject); } else if (messageObject.messageOwner.media.video instanceof TLRPC.TL_video) { TLRPC.TL_video video = (TLRPC.TL_video) messageObject.messageOwner.media.video; video.videoEditedInfo = messageObject.messageOwner.videoEditedInfo; - sendMessage(video, null, messageObject.messageOwner.attachPath, did); + sendMessage(video, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject); } else if (messageObject.messageOwner.media.document instanceof TLRPC.TL_document) { - sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did); + sendMessage((TLRPC.TL_document) messageObject.messageOwner.media.document, null, messageObject.messageOwner.attachPath, did, messageObject.replyMessageObject); } else if (messageObject.messageOwner.media.geo instanceof TLRPC.TL_geoPoint) { - sendMessage(messageObject.messageOwner.media.geo.lat, messageObject.messageOwner.media.geo._long, did); + sendMessage(messageObject.messageOwner.media.geo.lat, messageObject.messageOwner.media.geo._long, did, messageObject.replyMessageObject); } else if (messageObject.messageOwner.media.phone_number != null) { TLRPC.User user = new TLRPC.TL_userContact(); user.phone = messageObject.messageOwner.media.phone_number; user.first_name = messageObject.messageOwner.media.first_name; user.last_name = messageObject.messageOwner.media.last_name; user.id = messageObject.messageOwner.media.user_id; - sendMessage(user, did); + sendMessage(user, did, messageObject.replyMessageObject); } else { sendMessage(messageObject, did); } } else if (messageObject.messageOwner.message != null) { - sendMessage(messageObject.messageOwner.message, did); + sendMessage(messageObject.messageOwner.message, did, messageObject.replyMessageObject); } else { sendMessage(messageObject, did); } } - public void sendMessage(TLRPC.User user, long peer) { - sendMessage(null, null, null, null, null, null, user, null, null, null, peer, false, null); + public void sendMessage(TLRPC.User user, long peer, MessageObject reply_to_msg) { + sendMessage(null, null, null, null, null, null, user, null, null, null, peer, false, null, reply_to_msg); } - public void sendMessage(ArrayList messages) { + public void sendMessage(ArrayList messages, long peer) { + if ((int) peer == 0 || messages == null || messages.isEmpty()) { + return; + } + int lower_id = (int) peer; + TLRPC.Peer to_id; + TLRPC.InputPeer sendToPeer; + if (lower_id < 0) { + to_id = new TLRPC.TL_peerChat(); + to_id.chat_id = -lower_id; + sendToPeer = new TLRPC.TL_inputPeerChat(); + sendToPeer.chat_id = -lower_id; + } else { + to_id = new TLRPC.TL_peerUser(); + to_id.user_id = lower_id; + TLRPC.User sendToUser = MessagesController.getInstance().getUser(lower_id); + if (sendToUser == null) { + return; + } + if (sendToUser instanceof TLRPC.TL_userForeign || sendToUser instanceof TLRPC.TL_userRequest) { + sendToPeer = new TLRPC.TL_inputPeerForeign(); + sendToPeer.user_id = sendToUser.id; + sendToPeer.access_hash = sendToUser.access_hash; + } else { + sendToPeer = new TLRPC.TL_inputPeerContact(); + sendToPeer.user_id = sendToUser.id; + } + } + ArrayList objArr = new ArrayList<>(); + ArrayList arr = new ArrayList<>(); + ArrayList randomIds = new ArrayList<>(); + ArrayList ids = new ArrayList<>(); + + for (int a = 0; a < messages.size(); a++) { + MessageObject msgObj = messages.get(a); + + TLRPC.Message newMsg = new TLRPC.TL_message(); + newMsg.flags |= TLRPC.MESSAGE_FLAG_FWD; + if (msgObj.isForwarded()) { + newMsg.fwd_from_id = msgObj.messageOwner.fwd_from_id; + newMsg.fwd_date = msgObj.messageOwner.fwd_date; + } else { + newMsg.fwd_from_id = msgObj.messageOwner.from_id; + newMsg.fwd_date = msgObj.messageOwner.date; + } + newMsg.media = msgObj.messageOwner.media; + newMsg.message = msgObj.messageOwner.message; + newMsg.fwd_msg_id = msgObj.getId(); + newMsg.attachPath = msgObj.messageOwner.attachPath; + if (newMsg.attachPath == null) { + newMsg.attachPath = ""; + } + newMsg.local_id = newMsg.id = UserConfig.getNewMessageId(); + newMsg.from_id = UserConfig.getClientUserId(); + newMsg.flags |= TLRPC.MESSAGE_FLAG_OUT; + if (newMsg.random_id == 0) { + newMsg.random_id = getNextRandomId(); + } + randomIds.add(newMsg.random_id); + ids.add(newMsg.fwd_msg_id); + newMsg.date = ConnectionsManager.getInstance().getCurrentTime(); + newMsg.flags |= TLRPC.MESSAGE_FLAG_UNREAD; + newMsg.dialog_id = peer; + newMsg.to_id = to_id; + MessageObject newMsgObj = new MessageObject(newMsg, null, true); + newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; + objArr.add(newMsgObj); + arr.add(newMsg); + + putToSendingMessages(newMsg); + + if (a % 100 == 0 || a == messages.size() - 1) { + MessagesStorage.getInstance().putMessages(arr, false, true, false, 0); + MessagesController.getInstance().updateInterfaceWithMessages(peer, objArr); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.dialogsNeedReload); + UserConfig.saveConfig(false); + + TLRPC.TL_messages_forwardMessages req = new TLRPC.TL_messages_forwardMessages(); + req.peer = sendToPeer; + req.random_id = randomIds; + req.id = ids; + + /*ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + if (error == null) { + final int oldId = newMsgObj.id; + final ArrayList sentMessages = new ArrayList<>(); + final String attachPath = newMsgObj.attachPath; + + if (response instanceof TLRPC.messages_StatedMessages) { + TLRPC.messages_StatedMessages res = (TLRPC.messages_StatedMessages) response; + if (!res.messages.isEmpty()) { + sentMessages.addAll(res.messages); + TLRPC.Message message = res.messages.get(0); + newMsgObj.id = message.id; + processSentMessage(newMsgObj, message, originalPath); + } + if (res instanceof TLRPC.TL_messages_statedMessages) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, -1, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_statedMessagesLinks) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, -1, res.pts_count); + } + } + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + MessagesStorage.getInstance().updateMessageStateAndId(newMsgObj.random_id, oldId, newMsgObj.id, 0, false); + MessagesStorage.getInstance().putMessages(sentMessages, true, false, false, 0); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj); + processSentMessage(oldId); + removeFromSendingMessages(oldId); + } + }); + 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); + } + removeFromSendingMessages(newMsgObj.id); + } + }); + } + } + }, null, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassCanCompress, ConnectionsManager.DEFAULT_DATACENTER_ID); + */ + if (a != messages.size() - 1) { + objArr = new ArrayList<>(); + arr = new ArrayList<>(); + randomIds = new ArrayList<>(); + ids = new ArrayList<>(); + } + } + } } public void sendMessage(MessageObject message) { - sendMessage(null, null, null, null, null, message, null, null, null, null, message.getDialogId(), true, message.messageOwner.attachPath); + sendMessage(null, null, null, null, null, message, null, null, null, null, message.getDialogId(), true, message.messageOwner.attachPath, null); } public void sendMessage(MessageObject message, long peer) { - sendMessage(null, null, null, null, null, message, null, null, null, null, peer, false, message.messageOwner.attachPath); + sendMessage(null, null, null, null, null, message, null, null, null, null, peer, false, message.messageOwner.attachPath, null); } - public void sendMessage(TLRPC.TL_document document, String originalPath, String path, long peer) { - sendMessage(null, null, null, null, null, null, null, document, null, originalPath, peer, false, path); + public void sendMessage(TLRPC.TL_document document, String originalPath, String path, long peer, MessageObject reply_to_msg) { + sendMessage(null, null, null, null, null, null, null, document, null, originalPath, peer, false, path, reply_to_msg); } - public void sendMessage(String message, long peer) { - sendMessage(message, null, null, null, null, null, null, null, null, null, peer, false, null); + public void sendMessage(String message, long peer, MessageObject reply_to_msg) { + sendMessage(message, null, null, null, null, null, null, null, null, null, peer, false, null, reply_to_msg); } - public void sendMessage(double lat, double lon, long peer) { - sendMessage(null, lat, lon, null, null, null, null, null, null, null, peer, false, null); + public void sendMessage(double lat, double lon, long peer, MessageObject reply_to_msg) { + sendMessage(null, lat, lon, null, null, null, null, null, null, null, peer, false, null, reply_to_msg); } - public void sendMessage(TLRPC.TL_photo photo, String originalPath, String path, long peer) { - sendMessage(null, null, null, photo, null, null, null, null, null, originalPath, peer, false, path); + public void sendMessage(TLRPC.TL_photo photo, String originalPath, String path, long peer, MessageObject reply_to_msg) { + sendMessage(null, null, null, photo, null, null, null, null, null, originalPath, peer, false, path, reply_to_msg); } - public void sendMessage(TLRPC.TL_video video, String originalPath, String path, long peer) { - sendMessage(null, null, null, null, video, null, null, null, null, originalPath, peer, false, path); + public void sendMessage(TLRPC.TL_video video, String originalPath, String path, long peer, MessageObject reply_to_msg) { + sendMessage(null, null, null, null, video, null, null, null, null, originalPath, peer, false, path, reply_to_msg); } - public void sendMessage(TLRPC.TL_audio audio, String path, long peer) { - sendMessage(null, null, null, null, null, null, null, null, audio, null, peer, false, path); + public void sendMessage(TLRPC.TL_audio audio, String path, long peer, MessageObject reply_to_msg) { + sendMessage(null, null, null, null, null, null, null, null, audio, null, peer, false, path, reply_to_msg); } - private void sendMessage(String message, Double lat, Double lon, TLRPC.TL_photo photo, TLRPC.TL_video video, MessageObject msgObj, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, boolean retry, String path) { + private void sendMessage(String message, Double lat, Double lon, TLRPC.TL_photo photo, TLRPC.TL_video video, MessageObject msgObj, TLRPC.User user, TLRPC.TL_document document, TLRPC.TL_audio audio, String originalPath, long peer, boolean retry, String path, MessageObject reply_to_msg) { if (peer == 0) { return; } @@ -537,7 +685,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter newMsg = msgObj.messageOwner; if (msgObj.type == 0) { - if (msgObj.messageOwner instanceof TLRPC.TL_messageForwarded) { + if (msgObj.isForwarded()) { type = 4; } else { message = newMsg.message; @@ -548,14 +696,14 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter lon = newMsg.media.geo._long; type = 1; } else if (msgObj.type == 1) { - if (msgObj.messageOwner instanceof TLRPC.TL_messageForwarded) { + if (msgObj.isForwarded()) { type = 4; } else { photo = (TLRPC.TL_photo) newMsg.media.photo; type = 2; } } else if (msgObj.type == 3) { - if (msgObj.messageOwner instanceof TLRPC.TL_messageForwarded) { + if (msgObj.isForwarded()) { type = 4; } else { type = 3; @@ -631,24 +779,20 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } newMsg.attachPath = path; } else if (msgObj != null) { - newMsg = new TLRPC.TL_messageForwarded(); - if (msgObj.messageOwner instanceof TLRPC.TL_messageForwarded) { + newMsg = new TLRPC.TL_message(); + newMsg.flags |= TLRPC.MESSAGE_FLAG_FWD; + if (msgObj.isForwarded()) { newMsg.fwd_from_id = msgObj.messageOwner.fwd_from_id; newMsg.fwd_date = msgObj.messageOwner.fwd_date; - newMsg.media = msgObj.messageOwner.media; - newMsg.message = msgObj.messageOwner.message; - newMsg.fwd_msg_id = msgObj.messageOwner.id; - newMsg.attachPath = msgObj.messageOwner.attachPath; - type = 4; } else { newMsg.fwd_from_id = msgObj.messageOwner.from_id; newMsg.fwd_date = msgObj.messageOwner.date; - newMsg.media = msgObj.messageOwner.media; - newMsg.message = msgObj.messageOwner.message; - newMsg.fwd_msg_id = msgObj.messageOwner.id; - newMsg.attachPath = msgObj.messageOwner.attachPath; - type = 4; } + newMsg.media = msgObj.messageOwner.media; + newMsg.message = msgObj.messageOwner.message; + newMsg.fwd_msg_id = msgObj.getId(); + newMsg.attachPath = msgObj.messageOwner.attachPath; + type = 4; } else if (user != null) { if (encryptedChat != null && AndroidUtilities.getPeerLayerVersion(encryptedChat.layer) >= 17) { newMsg = new TLRPC.TL_message_secret(); @@ -699,6 +843,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter newMsg.date = ConnectionsManager.getInstance().getCurrentTime(); newMsg.flags |= TLRPC.MESSAGE_FLAG_UNREAD; newMsg.dialog_id = peer; + if (reply_to_msg != null) { + newMsg.flags |= TLRPC.MESSAGE_FLAG_REPLY; + newMsg.reply_to_msg_id = reply_to_msg.getId(); + } if (lower_id != 0) { if (high_id == 1) { if (currentChatInfo == null) { @@ -758,6 +906,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } MessageObject newMsgObj = new MessageObject(newMsg, null, true); + newMsgObj.replyMessageObject = reply_to_msg; newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; ArrayList objArr = new ArrayList<>(); @@ -782,6 +931,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter reqSend.message = message; reqSend.peer = sendToPeer; reqSend.random_id = newMsg.random_id; + if (reply_to_msg != null) { + reqSend.reply_to_msg_id = reply_to_msg.getId(); + } performSendMessageRequest(reqSend, newMsgObj.messageOwner, null); } } else { @@ -915,6 +1067,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter request.peer = sendToPeer; request.random_id = newMsg.random_id; request.media = inputMedia; + if (reply_to_msg != null) { + request.reply_to_msg_id = reply_to_msg.getId(); + } if (delayedMessage != null) { delayedMessage.sendRequest = request; } @@ -1111,8 +1266,8 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.TL_messages_forwardMessage reqSend = new TLRPC.TL_messages_forwardMessage(); reqSend.peer = sendToPeer; reqSend.random_id = newMsg.random_id; - if (msgObj.messageOwner.id >= 0) { - reqSend.id = msgObj.messageOwner.id; + if (msgObj.getId() >= 0) { + reqSend.id = msgObj.getId(); } else { reqSend.id = msgObj.messageOwner.fwd_msg_id; } @@ -1120,10 +1275,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } catch (Exception e) { FileLog.e("tmessages", e); - MessagesStorage.getInstance().markMessageAsSendError(newMsgObj.messageOwner.id); + MessagesStorage.getInstance().markMessageAsSendError(newMsgObj.getId()); newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; - NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.messageOwner.id); - processSentMessage(newMsgObj.messageOwner.id); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.messageSendError, newMsgObj.getId()); + processSentMessage(newMsgObj.getId()); } } @@ -1269,13 +1424,21 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter TLRPC.messages_SentMessage res = (TLRPC.messages_SentMessage) response; newMsgObj.id = res.id; newMsgObj.date = res.date; - MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.date); + if (res instanceof TLRPC.TL_messages_sentMessage) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, res.date, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_sentMessageLink) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.date, res.pts_count); + } } else if (response instanceof TLRPC.messages_StatedMessage) { TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage) response; sentMessages.add(res.message); newMsgObj.id = res.message.id; processSentMessage(newMsgObj, res.message, originalPath); - MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.message.date); + if (res instanceof TLRPC.TL_messages_statedMessage) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, res.message.date, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_statedMessageLink) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, res.message.date, res.pts_count); + } } else if (response instanceof TLRPC.messages_StatedMessages) { TLRPC.messages_StatedMessages res = (TLRPC.messages_StatedMessages) response; if (!res.messages.isEmpty()) { @@ -1286,7 +1449,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } processSentMessage(newMsgObj, message, originalPath); } - MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, -1); + if (res instanceof TLRPC.TL_messages_statedMessages) { + MessagesController.getInstance().processNewDifferenceParams(-1, res.pts, -1, res.pts_count); + } else if (res instanceof TLRPC.TL_messages_statedMessagesLinks) { + MessagesController.getInstance().processNewDifferenceParams(res.seq, res.pts, -1, res.pts_count); + } } MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { @Override @@ -1545,7 +1712,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } } - private static boolean prepareSendingDocumentInternal(String path, String originalPath, Uri uri, String mime, final long dialog_id) { + private static boolean prepareSendingDocumentInternal(String path, String originalPath, Uri uri, String mime, final long dialog_id, final MessageObject reply_to_msg) { if ((path == null || path.length() == 0) && uri == null) { return false; } @@ -1653,13 +1820,13 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - SendMessagesHelper.getInstance().sendMessage(documentFinal, originalPathFinal, pathFinal, dialog_id); + SendMessagesHelper.getInstance().sendMessage(documentFinal, originalPathFinal, pathFinal, dialog_id, reply_to_msg); } }); return true; } - public static void prepareSendingDocument(String path, String originalPath, Uri uri, String mine, long dialog_id) { + public static void prepareSendingDocument(String path, String originalPath, Uri uri, String mine, long dialog_id, MessageObject reply_to_msg) { if ((path == null || originalPath == null) && uri == null) { return; } @@ -1671,10 +1838,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } paths.add(path); originalPaths.add(originalPath); - prepareSendingDocuments(paths, originalPaths, uris, mine, dialog_id); + prepareSendingDocuments(paths, originalPaths, uris, mine, dialog_id, reply_to_msg); } - public static void prepareSendingDocuments(final ArrayList paths, final ArrayList originalPaths, final ArrayList uris, final String mime, final long dialog_id) { + public static void prepareSendingDocuments(final ArrayList paths, final ArrayList originalPaths, final ArrayList uris, final String mime, final long dialog_id, final MessageObject reply_to_msg) { if (paths == null && originalPaths == null && uris == null || paths != null && originalPaths != null && paths.size() != originalPaths.size()) { return; } @@ -1684,14 +1851,14 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter boolean error = false; if (paths != null) { for (int a = 0; a < paths.size(); a++) { - if (!prepareSendingDocumentInternal(paths.get(a), originalPaths.get(a), null, mime, dialog_id)) { + if (!prepareSendingDocumentInternal(paths.get(a), originalPaths.get(a), null, mime, dialog_id, reply_to_msg)) { error = true; } } } if (uris != null) { for (int a = 0; a < uris.size(); a++) { - if (!prepareSendingDocumentInternal(null, null, uris.get(a), mime, dialog_id)) { + if (!prepareSendingDocumentInternal(null, null, uris.get(a), mime, dialog_id, reply_to_msg)) { error = true; } } @@ -1713,7 +1880,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter }).start(); } - public static void prepareSendingPhoto(String imageFilePath, Uri imageUri, long dialog_id) { + public static void prepareSendingPhoto(String imageFilePath, Uri imageUri, long dialog_id, MessageObject reply_to_msg) { ArrayList paths = null; ArrayList uris = null; if (imageFilePath != null && imageFilePath.length() != 0) { @@ -1724,10 +1891,10 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter uris = new ArrayList<>(); uris.add(imageUri); } - prepareSendingPhotos(paths, uris, dialog_id); + prepareSendingPhotos(paths, uris, dialog_id, reply_to_msg); } - public static void prepareSendingPhotosSearch(final ArrayList photos, final long dialog_id) { + public static void prepareSendingPhotosSearch(final ArrayList photos, final long dialog_id, final MessageObject reply_to_msg) { if (photos == null || photos.isEmpty()) { return; } @@ -1789,7 +1956,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - SendMessagesHelper.getInstance().sendMessage(documentFinal, originalPathFinal, pathFinal, dialog_id); + SendMessagesHelper.getInstance().sendMessage(documentFinal, originalPathFinal, pathFinal, dialog_id, reply_to_msg); } }); } else { @@ -1832,7 +1999,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - SendMessagesHelper.getInstance().sendMessage(photoFinal, originalPathFinal, needDownloadHttpFinal ? searchImage.imageUrl : null, dialog_id); + SendMessagesHelper.getInstance().sendMessage(photoFinal, originalPathFinal, needDownloadHttpFinal ? searchImage.imageUrl : null, dialog_id, reply_to_msg); } }); } @@ -1842,7 +2009,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter }).start(); } - public static void prepareSendingPhotos(ArrayList paths, ArrayList uris, final long dialog_id) { + public static void prepareSendingPhotos(ArrayList paths, ArrayList uris, final long dialog_id, final MessageObject reply_to_msg) { if (paths == null && uris == null || paths != null && paths.isEmpty() || uris != null && uris.isEmpty()) { return; } @@ -1923,7 +2090,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - SendMessagesHelper.getInstance().sendMessage(photoFinal, originalPathFinal, null, dialog_id); + SendMessagesHelper.getInstance().sendMessage(photoFinal, originalPathFinal, null, dialog_id, reply_to_msg); } }); } @@ -1931,14 +2098,14 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter } if (sendAsDocuments != null && !sendAsDocuments.isEmpty()) { for (int a = 0; a < sendAsDocuments.size(); a++) { - prepareSendingDocumentInternal(sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), null, "gif", dialog_id); + prepareSendingDocumentInternal(sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), null, "gif", dialog_id, reply_to_msg); } } } }).start(); } - public static void prepareSendingVideo(final String videoPath, final long estimatedSize, final long duration, final int width, final int height, final TLRPC.VideoEditedInfo videoEditedInfo, final long dialog_id) { + public static void prepareSendingVideo(final String videoPath, final long estimatedSize, final long duration, final int width, final int height, final TLRPC.VideoEditedInfo videoEditedInfo, final long dialog_id, final MessageObject reply_to_msg) { if (videoPath == null || videoPath.length() == 0) { return; } @@ -1955,6 +2122,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter originalPath += temp.length() + "_" + temp.lastModified(); if (videoEditedInfo != null) { originalPath += duration + "_" + videoEditedInfo.startTime + "_" + videoEditedInfo.endTime; + if (videoEditedInfo.resultWidth == videoEditedInfo.originalWidth) { + originalPath += "_" + videoEditedInfo.resultWidth; + } } TLRPC.TL_video video = null; if (!isEncrypted) { @@ -2049,11 +2219,11 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - SendMessagesHelper.getInstance().sendMessage(videoFinal, originalPathFinal, finalPath, dialog_id); + SendMessagesHelper.getInstance().sendMessage(videoFinal, originalPathFinal, finalPath, dialog_id, reply_to_msg); } }); } else { - prepareSendingDocumentInternal(videoPath, videoPath, null, null, dialog_id); + prepareSendingDocumentInternal(videoPath, videoPath, null, null, dialog_id, reply_to_msg); } } }).start(); diff --git a/TMessagesProj/src/main/java/org/telegram/android/WearReplyReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/WearReplyReceiver.java index 9e32dc6a6..e94dc43c2 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/WearReplyReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/android/WearReplyReceiver.java @@ -31,7 +31,7 @@ public class WearReplyReceiver extends BroadcastReceiver { if (dialog_id == 0 || max_id == 0) { return; } - SendMessagesHelper.getInstance().sendMessage(text.toString(), dialog_id); + SendMessagesHelper.getInstance().sendMessage(text.toString(), dialog_id, null); MessagesController.getInstance().markDialogAsRead(dialog_id, max_id, max_id, 0, 0, true, false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/query/ReplyMessageQuery.java b/TMessagesProj/src/main/java/org/telegram/android/query/ReplyMessageQuery.java new file mode 100644 index 000000000..da9717dd1 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/query/ReplyMessageQuery.java @@ -0,0 +1,185 @@ +/* + * This is the source code of Telegram for Android v. 2.x + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.android.query; + +import android.text.TextUtils; + +import org.telegram.SQLite.SQLiteCursor; +import org.telegram.SQLite.SQLitePreparedStatement; +import org.telegram.android.AndroidUtilities; +import org.telegram.android.ImageLoader; +import org.telegram.android.MessageObject; +import org.telegram.android.MessagesStorage; +import org.telegram.android.NotificationCenter; +import org.telegram.messenger.ByteBufferDesc; +import org.telegram.messenger.ConnectionsManager; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.RPCRequest; +import org.telegram.messenger.TLClassStore; +import org.telegram.messenger.TLObject; +import org.telegram.messenger.TLRPC; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Locale; + +public class ReplyMessageQuery { + + public static void loadReplyMessagesForMessages(final ArrayList messages, final long dialog_id) { + final ArrayList replyMessages = new ArrayList<>(); + final HashMap> replyMessageOwners = new HashMap<>(); + for (MessageObject messageObject : messages) { + if (messageObject.getId() > 0 && messageObject.isReply() && messageObject.replyMessageObject == null) { + Integer id = messageObject.messageOwner.reply_to_msg_id; + ArrayList messageObjects = replyMessageOwners.get(id); + if (messageObjects == null) { + messageObjects = new ArrayList<>(); + replyMessageOwners.put(id, messageObjects); + } + messageObjects.add(messageObject); + if (!replyMessages.contains(id)) { + replyMessages.add(id); + } + } + } + if (replyMessages.isEmpty()) { + return; + } + + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + final ArrayList result = new ArrayList<>(); + final ArrayList users = new ArrayList<>(); + ArrayList loadedUsers = new ArrayList<>(); + ArrayList fromUser = new ArrayList<>(); + + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid, date FROM messages WHERE mid IN(%s)", TextUtils.join(",", replyMessages))); + while (cursor.next()) { + ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0)); + if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) { + TLRPC.Message message = (TLRPC.Message) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); + message.id = cursor.intValue(1); + message.date = cursor.intValue(2); + message.dialog_id = dialog_id; + fromUser.add(message.from_id); + if (message.action != null && message.action.user_id != 0) { + fromUser.add(message.action.user_id); + } + if (message.media != null && message.media.user_id != 0) { + fromUser.add(message.media.user_id); + } + if (message.media != null && message.media.audio != null && message.media.audio.user_id != 0) { + fromUser.add(message.media.audio.user_id); + } + if (message.fwd_from_id != 0) { + fromUser.add(message.fwd_from_id); + } + result.add(message); + replyMessages.remove((Integer) message.id); + } + MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); + } + cursor.dispose(); + + StringBuilder usersToLoad = new StringBuilder(); + for (int uid : fromUser) { + if (!loadedUsers.contains(uid)) { + if (usersToLoad.length() != 0) { + usersToLoad.append(","); + } + usersToLoad.append(uid); + loadedUsers.add(uid); + } + } + if (usersToLoad.length() != 0) { + MessagesStorage.getInstance().getUsersInternal(usersToLoad.toString(), users); + } + broadcastReplyMessages(result, replyMessageOwners, users, dialog_id); + + if (!replyMessages.isEmpty()) { + TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages(); + req.id = replyMessages; + ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { + @Override + public void run(TLObject response, TLRPC.TL_error error) { + if (error == null) { + TLRPC.messages_Messages messagesRes = (TLRPC.messages_Messages) response; + ImageLoader.saveMessagesThumbs(messagesRes.messages); + broadcastReplyMessages(messagesRes.messages, replyMessageOwners, messagesRes.users, dialog_id); + MessagesStorage.getInstance().putUsersAndChats(messagesRes.users, null, true, true); + saveReplyMessages(replyMessageOwners, messagesRes.messages); + } + } + }); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + private static void saveReplyMessages(final HashMap> replyMessageOwners, final ArrayList result) { + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + try { + MessagesStorage.getInstance().getDatabase().beginTransaction(); + SQLitePreparedStatement state = MessagesStorage.getInstance().getDatabase().executeFast("UPDATE messages SET replydata = ? WHERE mid = ?"); + for (TLRPC.Message message : result) { + ArrayList messageObjects = replyMessageOwners.get(message.id); + if (messageObjects != null) { + ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(message.getObjectSize()); + message.serializeToStream(data); + for (MessageObject messageObject : messageObjects) { + state.requery(); + state.bindByteBuffer(1, data.buffer); + state.bindInteger(2, messageObject.getId()); + state.step(); + } + MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); + } + } + state.dispose(); + MessagesStorage.getInstance().getDatabase().commitTransaction(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + }); + } + + private static void broadcastReplyMessages(final ArrayList result, final HashMap> replyMessageOwners, ArrayList users, final long dialog_id) { + final HashMap usersHashMap = new HashMap<>(); + for (TLRPC.User user : users) { + usersHashMap.put(user.id, user); + } + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + boolean changed = false; + for (TLRPC.Message message : result) { + ArrayList arrayList = replyMessageOwners.get(message.id); + if (arrayList != null) { + MessageObject messageObject = new MessageObject(message, usersHashMap, false); + for (MessageObject m : arrayList) { + m.replyMessageObject = messageObject; + } + changed = true; + } + } + if (changed) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.didLoadedReplyMessages, dialog_id); + } + } + }); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/Cache.java b/TMessagesProj/src/main/java/org/telegram/android/volley/Cache.java index e64e69b2a..90433e7ef 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/Cache.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/Cache.java @@ -28,43 +28,43 @@ public interface Cache { * @param key Cache key * @return An {@link Entry} or null in the event of a cache miss */ - public Entry get(String key); + Entry get(String key); /** * Adds or replaces an entry to the cache. * @param key Cache key * @param entry Data to store and metadata for cache coherency, TTL, etc. */ - public void put(String key, Entry entry); + void put(String key, Entry entry); /** * Performs any potentially long-running actions needed to initialize the cache; * will be called from a worker thread. */ - public void initialize(); + void initialize(); /** * Invalidates an entry in the cache. * @param key Cache key * @param fullExpire True to fully expire the entry, false to soft expire */ - public void invalidate(String key, boolean fullExpire); + void invalidate(String key, boolean fullExpire); /** * Removes an entry from the cache. * @param key Cache key */ - public void remove(String key); + void remove(String key); /** * Empties the cache. */ - public void clear(); + void clear(); /** * Data and metadata for an entry returned by the cache. */ - public static class Entry { + class Entry { /** The data returned from cache. */ public byte[] data; diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/Network.java b/TMessagesProj/src/main/java/org/telegram/android/volley/Network.java index ac3c24b12..f43165409 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/Network.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/Network.java @@ -26,5 +26,5 @@ public interface Network { * @return A {@link NetworkResponse} with data and caching metadata; will never be null * @throws VolleyError on errors */ - public NetworkResponse performRequest(Request request) throws VolleyError; + NetworkResponse performRequest(Request request) throws VolleyError; } diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/RequestQueue.java b/TMessagesProj/src/main/java/org/telegram/android/volley/RequestQueue.java index bec780aec..869c29965 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/RequestQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/RequestQueue.java @@ -175,7 +175,7 @@ public class RequestQueue { * {@link RequestQueue#cancelAll(RequestFilter)}. */ public interface RequestFilter { - public boolean apply(Request request); + boolean apply(Request request); } /** diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/Response.java b/TMessagesProj/src/main/java/org/telegram/android/volley/Response.java index c2dd5419e..af7d96f69 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/Response.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/Response.java @@ -26,7 +26,7 @@ public class Response { /** Callback interface for delivering parsed responses. */ public interface Listener { /** Called when a response is received. */ - public void onResponse(T response); + void onResponse(T response); } /** Callback interface for delivering error responses. */ @@ -35,7 +35,7 @@ public class Response { * Callback method that an error has been occurred with the * provided error code and optional user-readable message. */ - public void onErrorResponse(VolleyError error); + void onErrorResponse(VolleyError error); } /** Returns a successful response containing the parsed result. */ diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/ResponseDelivery.java b/TMessagesProj/src/main/java/org/telegram/android/volley/ResponseDelivery.java index 6eb35eb12..9ad24f355 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/ResponseDelivery.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/ResponseDelivery.java @@ -20,16 +20,16 @@ public interface ResponseDelivery { /** * Parses a response from the network or cache and delivers it. */ - public void postResponse(Request request, Response response); + void postResponse(Request request, Response response); /** * Parses a response from the network or cache and delivers it. The provided * Runnable will be executed after delivery. */ - public void postResponse(Request request, Response response, Runnable runnable); + void postResponse(Request request, Response response, Runnable runnable); /** * Posts an error for the given request. */ - public void postError(Request request, VolleyError error); + void postError(Request request, VolleyError error); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/RetryPolicy.java b/TMessagesProj/src/main/java/org/telegram/android/volley/RetryPolicy.java index 7218777a1..c2c1d24d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/RetryPolicy.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/RetryPolicy.java @@ -24,12 +24,12 @@ public interface RetryPolicy { /** * Returns the current timeout (used for logging). */ - public int getCurrentTimeout(); + int getCurrentTimeout(); /** * Returns the current retry count (used for logging). */ - public int getCurrentRetryCount(); + int getCurrentRetryCount(); /** * Prepares for the next retry by applying a backoff to the timeout. @@ -37,5 +37,5 @@ public interface RetryPolicy { * @throws VolleyError In the event that the retry could not be performed (for example if we * ran out of attempts), the passed in error is thrown. */ - public void retry(VolleyError error) throws VolleyError; + void retry(VolleyError error) throws VolleyError; } diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/Authenticator.java b/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/Authenticator.java index e87dfc100..f0d4845b1 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/Authenticator.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/Authenticator.java @@ -27,10 +27,10 @@ public interface Authenticator { * * @throws AuthFailureError If authentication did not succeed */ - public String getAuthToken() throws AuthFailureError; + String getAuthToken() throws AuthFailureError; /** * Invalidates the provided auth token. */ - public void invalidateAuthToken(String authToken); + void invalidateAuthToken(String authToken); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HttpStack.java b/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HttpStack.java index 74a326d9e..97816eda7 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HttpStack.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HttpStack.java @@ -38,7 +38,7 @@ public interface HttpStack { * {@link Request#getHeaders()} * @return the HTTP response */ - public HttpResponse performRequest(Request request, Map additionalHeaders) + HttpResponse performRequest(Request request, Map additionalHeaders) throws IOException, AuthFailureError; } diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HurlStack.java b/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HurlStack.java index 435fd675c..e374fbaf4 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HurlStack.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/HurlStack.java @@ -56,7 +56,7 @@ public class HurlStack implements HttpStack { * Returns a URL to use instead of the provided one, or null to indicate * this URL should not be used at all. */ - public String rewriteUrl(String originalUrl); + String rewriteUrl(String originalUrl); } private final UrlRewriter mUrlRewriter; diff --git a/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/ImageLoader.java index 64105a84f..f22b65d80 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/android/volley/toolbox/ImageLoader.java @@ -71,8 +71,8 @@ public class ImageLoader { * must not block. Implementation with an LruCache is recommended. */ public interface ImageCache { - public Bitmap getBitmap(String url); - public void putBitmap(String url, Bitmap bitmap); + Bitmap getBitmap(String url); + void putBitmap(String url, Bitmap bitmap); } /** @@ -138,7 +138,7 @@ public class ImageLoader { * image loading in order to, for example, run an animation to fade in network loaded * images. */ - public void onResponse(ImageContainer response, boolean isImmediate); + void onResponse(ImageContainer response, boolean isImmediate); } /** diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java index 487f019cc..cf91ee20a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java @@ -480,7 +480,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. datacenter = new Datacenter(); datacenter.datacenterId = 3; - datacenter.addAddressAndPort("174.140.142.5", 443); + datacenter.addAddressAndPort("149.154.175.117", 443); datacenters.put(datacenter.datacenterId, datacenter); } } else if (datacenters.size() == 1) { @@ -646,8 +646,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. int lastClassGuid = 1; public int generateClassGuid() { int guid = lastClassGuid++; - ArrayList requests = new ArrayList<>(); - requestsByGuids.put(guid, requests); + requestsByGuids.put(guid, new ArrayList()); return guid; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 462098cc7..62f217442 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -54,10 +54,10 @@ public class FileLoadOperation { private File tempPath = null; private boolean isForceRequest = false; - public static interface FileLoadOperationDelegate { - public abstract void didFinishLoadingFile(FileLoadOperation operation, File finalFile); - public abstract void didFailedLoadingFile(FileLoadOperation operation, int state); - public abstract void didChangedLoadProgress(FileLoadOperation operation, float progress); + public interface FileLoadOperationDelegate { + void didFinishLoadingFile(FileLoadOperation operation, File finalFile); + void didFailedLoadingFile(FileLoadOperation operation, int state); + void didChangedLoadProgress(FileLoadOperation operation, float progress); } public FileLoadOperation(TLRPC.FileLocation photoLocation, int size) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 74afae274..2719aabf5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -19,13 +19,13 @@ import java.util.concurrent.Semaphore; public class FileLoader { - public static interface FileLoaderDelegate { - public abstract void fileUploadProgressChanged(String location, float progress, boolean isEncrypted); - public abstract void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile); - public abstract void fileDidFailedUpload(String location, boolean isEncrypted); - public abstract void fileDidLoaded(String location, File finalFile, int type); - public abstract void fileDidFailedLoad(String location, int state); - public abstract void fileLoadProgressChanged(String location, float progress); + public interface FileLoaderDelegate { + void fileUploadProgressChanged(String location, float progress, boolean isEncrypted); + void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile); + void fileDidFailedUpload(String location, boolean isEncrypted); + void fileDidLoaded(String location, File finalFile, int type); + void fileDidFailedLoad(String location, int state); + void fileLoadProgressChanged(String location, float progress); } public static final int MEDIA_DIR_IMAGE = 0; @@ -628,7 +628,7 @@ public class FileLoader { } public static TLRPC.PhotoSize getClosestPhotoSizeWithSize(ArrayList sizes, int side) { - if (sizes == null) { + if (sizes == null || sizes.isEmpty()) { return null; } int lastSide = 0; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index 6bf1f236f..6048711dc 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -45,10 +45,10 @@ public class FileUploadOperation { private MessageDigest mdEnc = null; private boolean started = false; - public static interface FileUploadOperationDelegate { - public abstract void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile); - public abstract void didFailedUploadingFile(FileUploadOperation operation); - public abstract void didChangedUploadProgress(FileUploadOperation operation, float progress); + public interface FileUploadOperationDelegate { + void didFinishUploadingFile(FileUploadOperation operation, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile); + void didFailedUploadingFile(FileUploadOperation operation); + void didChangedUploadProgress(FileUploadOperation operation, float progress); } public FileUploadOperation(String location, boolean encrypted, int estimated) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java index a2d747a2a..c25869052 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLClassStore.java @@ -61,7 +61,6 @@ public class TLClassStore { classStore.put(TLRPC.TL_account_privacyRules.constructor, TLRPC.TL_account_privacyRules.class); classStore.put(TLRPC.TL_help_appUpdate.constructor, TLRPC.TL_help_appUpdate.class); classStore.put(TLRPC.TL_help_noAppUpdate.constructor, TLRPC.TL_help_noAppUpdate.class); - classStore.put(TLRPC.TL_messageForwarded.constructor, TLRPC.TL_messageForwarded.class); classStore.put(TLRPC.TL_messageEmpty.constructor, TLRPC.TL_messageEmpty.class); classStore.put(TLRPC.TL_message.constructor, TLRPC.TL_message.class); classStore.put(TLRPC.TL_messageService.constructor, TLRPC.TL_messageService.class); @@ -157,9 +156,6 @@ public class TLClassStore { classStore.put(TLRPC.TL_messageActionChatEditTitle.constructor, TLRPC.TL_messageActionChatEditTitle.class); classStore.put(TLRPC.TL_messageActionGeoChatCreate.constructor, TLRPC.TL_messageActionGeoChatCreate.class); classStore.put(TLRPC.TL_messageActionGeoChatCheckin.constructor, TLRPC.TL_messageActionGeoChatCheckin.class); - classStore.put(TLRPC.TL_contacts_foreignLinkMutual.constructor, TLRPC.TL_contacts_foreignLinkMutual.class); - classStore.put(TLRPC.TL_contacts_foreignLinkUnknown.constructor, TLRPC.TL_contacts_foreignLinkUnknown.class); - classStore.put(TLRPC.TL_contacts_foreignLinkRequested.constructor, TLRPC.TL_contacts_foreignLinkRequested.class); classStore.put(TLRPC.TL_dh_gen_retry.constructor, TLRPC.TL_dh_gen_retry.class); classStore.put(TLRPC.TL_dh_gen_fail.constructor, TLRPC.TL_dh_gen_fail.class); classStore.put(TLRPC.TL_dh_gen_ok.constructor, TLRPC.TL_dh_gen_ok.class); @@ -222,7 +218,6 @@ public class TLClassStore { classStore.put(TLRPC.TL_updateContactLink.constructor, TLRPC.TL_updateContactLink.class); classStore.put(TLRPC.TL_updateReadMessages.constructor, TLRPC.TL_updateReadMessages.class); classStore.put(TLRPC.TL_updateChatParticipantDelete.constructor, TLRPC.TL_updateChatParticipantDelete.class); - classStore.put(TLRPC.TL_updateRestoreMessages.constructor, TLRPC.TL_updateRestoreMessages.class); classStore.put(TLRPC.TL_updateServiceNotification.constructor, TLRPC.TL_updateServiceNotification.class); classStore.put(TLRPC.TL_updateNotifySettings.constructor, TLRPC.TL_updateNotifySettings.class); classStore.put(TLRPC.TL_updateUserTyping.constructor, TLRPC.TL_updateUserTyping.class); @@ -260,9 +255,6 @@ public class TLClassStore { classStore.put(TLRPC.TL_decryptedMessageActionTyping.constructor, TLRPC.TL_decryptedMessageActionTyping.class); classStore.put(TLRPC.TL_decryptedMessageActionReadMessages.constructor, TLRPC.TL_decryptedMessageActionReadMessages.class); classStore.put(TLRPC.TL_decryptedMessageActionScreenshotMessages.constructor, TLRPC.TL_decryptedMessageActionScreenshotMessages.class); - classStore.put(TLRPC.TL_contacts_myLinkRequested.constructor, TLRPC.TL_contacts_myLinkRequested.class); - classStore.put(TLRPC.TL_contacts_myLinkContact.constructor, TLRPC.TL_contacts_myLinkContact.class); - classStore.put(TLRPC.TL_contacts_myLinkEmpty.constructor, TLRPC.TL_contacts_myLinkEmpty.class); classStore.put(TLRPC.TL_server_DH_inner_data.constructor, TLRPC.TL_server_DH_inner_data.class); classStore.put(TLRPC.TL_new_session_created.constructor, TLRPC.TL_new_session_created.class); classStore.put(TLRPC.TL_account_password.constructor, TLRPC.TL_account_password.class); @@ -341,7 +333,6 @@ public class TLClassStore { classStore.put(TLRPC.TL_updateShort.constructor, TLRPC.TL_updateShort.class); classStore.put(TLRPC.TL_updatesCombined.constructor, TLRPC.TL_updatesCombined.class); classStore.put(TLRPC.TL_updatesTooLong.constructor, TLRPC.TL_updatesTooLong.class); - classStore.put(TLRPC.TL_messages_chat.constructor, TLRPC.TL_messages_chat.class); classStore.put(TLRPC.TL_wallPaper.constructor, TLRPC.TL_wallPaper.class); classStore.put(TLRPC.TL_wallPaperSolid.constructor, TLRPC.TL_wallPaperSolid.class); classStore.put(TLRPC.TL_msg_new_detailed_info.constructor, TLRPC.TL_msg_new_detailed_info.class); @@ -379,7 +370,16 @@ public class TLClassStore { classStore.put(TLRPC.TL_decryptedMessageActionAbortKey.constructor, TLRPC.TL_decryptedMessageActionAbortKey.class); classStore.put(TLRPC.TL_decryptedMessageActionNoop.constructor, TLRPC.TL_decryptedMessageActionNoop.class); classStore.put(TLRPC.TL_decryptedMessageMediaExternalDocument.constructor, TLRPC.TL_decryptedMessageMediaExternalDocument.class); + classStore.put(TLRPC.TL_updateReadHistoryInbox.constructor, TLRPC.TL_updateReadHistoryInbox.class); + classStore.put(TLRPC.TL_updateReadHistoryOutbox.constructor, TLRPC.TL_updateReadHistoryOutbox.class); + classStore.put(TLRPC.TL_contactLinkUnknown.constructor, TLRPC.TL_contactLinkUnknown.class); + classStore.put(TLRPC.TL_contactLinkNone.constructor, TLRPC.TL_contactLinkNone.class); + classStore.put(TLRPC.TL_contactLinkHasPhone.constructor, TLRPC.TL_contactLinkHasPhone.class); + classStore.put(TLRPC.TL_contactLinkContact.constructor, TLRPC.TL_contactLinkContact.class); + classStore.put(TLRPC.TL_messages_affectedMessages.constructor, TLRPC.TL_messages_affectedMessages.class); + classStore.put(TLRPC.TL_messageMediaUnsupported_old.constructor, TLRPC.TL_messageMediaUnsupported_old.class); + classStore.put(TLRPC.TL_userSelf_old2.constructor, TLRPC.TL_userSelf_old2.class); classStore.put(TLRPC.TL_msg_container.constructor, TLRPC.TL_msg_container.class); classStore.put(TLRPC.TL_fileEncryptedLocation.constructor, TLRPC.TL_fileEncryptedLocation.class); classStore.put(TLRPC.TL_messageActionTTLChange.constructor, TLRPC.TL_messageActionTTLChange.class); @@ -415,6 +415,9 @@ public class TLClassStore { classStore.put(TLRPC.TL_documentEncrypted_old.constructor, TLRPC.TL_documentEncrypted_old.class); classStore.put(TLRPC.TL_document_old.constructor, TLRPC.TL_document_old.class); classStore.put(TLRPC.TL_config_old.constructor, TLRPC.TL_config_old.class); + classStore.put(TLRPC.TL_messageForwarded_old2.constructor, TLRPC.TL_messageForwarded_old2.class); + classStore.put(TLRPC.TL_message_old2.constructor, TLRPC.TL_message_old2.class); + classStore.put(TLRPC.TL_documentAttributeSticker_old.constructor, TLRPC.TL_documentAttributeSticker_old.class); } static TLClassStore store = null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java index 6ce1e5194..cd766543f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java @@ -16,7 +16,10 @@ public class TLRPC { public static final int MESSAGE_FLAG_UNREAD = 1; public static final int MESSAGE_FLAG_OUT = 2; - public static final int LAYER = 23; + public static final int MESSAGE_FLAG_FWD = 4; + public static final int MESSAGE_FLAG_REPLY = 8; + public static final int MESSAGE_FLAG_MENTION = 16; + public static final int LAYER = 25; public static class ChatPhoto extends TLObject { public FileLocation photo_small; @@ -192,20 +195,17 @@ public class TLRPC { } public static class TL_auth_checkedPhone extends TLObject { - public static int constructor = 0xe300cc3b; + public static int constructor = 0x811ea28e; public boolean phone_registered; - public boolean phone_invited; public void readParams(AbsSerializedData stream) { phone_registered = stream.readBool(); - phone_invited = stream.readBool(); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); stream.writeBool(phone_registered); - stream.writeBool(phone_invited); } } @@ -275,6 +275,7 @@ public class TLRPC { public static class DocumentAttribute extends TLObject { public int duration; public String file_name; + public String alt; public int w; public int h; } @@ -335,11 +336,16 @@ public class TLRPC { } public static class TL_documentAttributeSticker extends DocumentAttribute { - public static int constructor = 0xfb0a5727; + public static int constructor = 0x994c9882; + public void readParams(AbsSerializedData stream) { + alt = stream.readString(); + } + public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); + stream.writeString(alt); } } @@ -537,15 +543,15 @@ public class TLRPC { } public static class TL_contacts_link extends TLObject { - public static int constructor = 0xeccea3f5; + public static int constructor = 0x3ace484c; - public contacts_MyLink my_link; - public contacts_ForeignLink foreign_link; + public ContactLink my_link; + public ContactLink foreign_link; public User user; public void readParams(AbsSerializedData stream) { - my_link = (contacts_MyLink)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); - foreign_link = (contacts_ForeignLink)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + my_link = (ContactLink)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + foreign_link = (ContactLink)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); user = (User)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); } @@ -629,6 +635,24 @@ public class TLRPC { } } + public static class TL_messages_affectedMessages extends TLObject { + public static int constructor = 0x84d19185; + + public int pts; + public int pts_count; + + public void readParams(AbsSerializedData stream) { + pts = stream.readInt32(); + pts_count = stream.readInt32(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(pts); + stream.writeInt32(pts_count); + } + } + public static class DestroySessionRes extends TLObject { public long session_id; } @@ -1200,16 +1224,11 @@ public class TLRPC { } public static class TL_messageMediaUnsupported extends MessageMedia { - public static int constructor = 0x29632a36; + public static int constructor = 0x9f84f49e; - public void readParams(AbsSerializedData stream) { - bytes = stream.readByteArray(); - } - public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); - stream.writeByteArray(bytes); } } @@ -2020,13 +2039,14 @@ public class TLRPC { public ArrayList messages = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); public ArrayList users = new ArrayList<>(); - public ArrayList links = new ArrayList<>(); public int pts; + public int pts_count; + public ArrayList links = new ArrayList<>(); public int seq; } public static class TL_messages_statedMessagesLinks extends messages_StatedMessages { - public static int constructor = 0x3e74f5c6; + public static int constructor = 0x51be5d19; public void readParams(AbsSerializedData stream) { @@ -2045,12 +2065,13 @@ public class TLRPC { for (int a = 0; a < count; a++) { users.add((User)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } + pts = stream.readInt32(); + pts_count = stream.readInt32(); stream.readInt32(); count = stream.readInt32(); for (int a = 0; a < count; a++) { links.add((TL_contacts_link)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } - pts = stream.readInt32(); seq = stream.readInt32(); } @@ -2074,19 +2095,20 @@ public class TLRPC { for (int a = 0; a < count; a++) { users.get(a).serializeToStream(stream); } + stream.writeInt32(pts); + stream.writeInt32(pts_count); stream.writeInt32(0x1cb5c415); count = links.size(); stream.writeInt32(count); for (int a = 0; a < count; a++) { links.get(a).serializeToStream(stream); } - stream.writeInt32(pts); stream.writeInt32(seq); } } public static class TL_messages_statedMessages extends messages_StatedMessages { - public static int constructor = 0x969478bb; + public static int constructor = 0x7d84b48; public void readParams(AbsSerializedData stream) { @@ -2106,7 +2128,7 @@ public class TLRPC { users.add((User)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } pts = stream.readInt32(); - seq = stream.readInt32(); + pts_count = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { @@ -2130,7 +2152,7 @@ public class TLRPC { users.get(a).serializeToStream(stream); } stream.writeInt32(pts); - stream.writeInt32(seq); + stream.writeInt32(pts_count); } } @@ -2414,7 +2436,7 @@ public class TLRPC { } public static class TL_userSelf extends User { - public static int constructor = 0x7007b451; + public static int constructor = 0x1c60e608; public void readParams(AbsSerializedData stream) { @@ -2425,7 +2447,6 @@ public class TLRPC { phone = stream.readString(); photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); - inactive = stream.readBool(); } public void serializeToStream(AbsSerializedData stream) { @@ -2437,7 +2458,6 @@ public class TLRPC { stream.writeString(phone); photo.serializeToStream(stream); status.serializeToStream(stream); - stream.writeBool(inactive); } } @@ -2655,42 +2675,6 @@ public class TLRPC { } } - public static class contacts_ForeignLink extends TLObject { - public boolean has_phone; - } - - public static class TL_contacts_foreignLinkMutual extends contacts_ForeignLink { - public static int constructor = 0x1bea8ce1; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_contacts_foreignLinkUnknown extends contacts_ForeignLink { - public static int constructor = 0x133421f8; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_contacts_foreignLinkRequested extends contacts_ForeignLink { - public static int constructor = 0xa7801f47; - - - public void readParams(AbsSerializedData stream) { - has_phone = stream.readBool(); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeBool(has_phone); - } - } - public static class Set_client_DH_params_answer extends TLObject { public byte[] nonce; public byte[] server_nonce; @@ -3005,22 +2989,22 @@ public class TLRPC { } public static class TL_messages_affectedHistory extends TLObject { - public static int constructor = 0xb7de36f2; + public static int constructor = 0xb45c69d1; public int pts; - public int seq; + public int pts_count; public int offset; public void readParams(AbsSerializedData stream) { pts = stream.readInt32(); - seq = stream.readInt32(); + pts_count = stream.readInt32(); offset = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); stream.writeInt32(pts); - stream.writeInt32(seq); + stream.writeInt32(pts_count); stream.writeInt32(offset); } } @@ -3076,6 +3060,45 @@ public class TLRPC { } } + public static class ContactLink extends TLObject { + } + + public static class TL_contactLinkNone extends ContactLink { + public static int constructor = 0xfeedd3ad; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_contactLinkContact extends ContactLink { + public static int constructor = 0xd502c2d0; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_contactLinkHasPhone extends ContactLink { + public static int constructor = 0x268f3f59; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_contactLinkUnknown extends ContactLink { + public static int constructor = 0x5f4f9247; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class InputPrivacyRule extends TLObject { public ArrayList users = new ArrayList<>(); } @@ -3514,19 +3537,20 @@ public class TLRPC { public int id; public int date; public int pts; - public int seq; + public int pts_count; public ArrayList links = new ArrayList<>(); + public int seq; } public static class TL_messages_sentMessage extends messages_SentMessage { - public static int constructor = 0xd1f4d35c; + public static int constructor = 0x900eac40; public void readParams(AbsSerializedData stream) { id = stream.readInt32(); date = stream.readInt32(); pts = stream.readInt32(); - seq = stream.readInt32(); + pts_count = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { @@ -3534,24 +3558,25 @@ public class TLRPC { stream.writeInt32(id); stream.writeInt32(date); stream.writeInt32(pts); - stream.writeInt32(seq); + stream.writeInt32(pts_count); } } public static class TL_messages_sentMessageLink extends messages_SentMessage { - public static int constructor = 0xe9db4a3f; + public static int constructor = 0xe923400d; public void readParams(AbsSerializedData stream) { id = stream.readInt32(); date = stream.readInt32(); pts = stream.readInt32(); - seq = stream.readInt32(); + pts_count = stream.readInt32(); stream.readInt32(); int count = stream.readInt32(); for (int a = 0; a < count; a++) { links.add((TL_contacts_link)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } + seq = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { @@ -3559,13 +3584,14 @@ public class TLRPC { stream.writeInt32(id); stream.writeInt32(date); stream.writeInt32(pts); - stream.writeInt32(seq); + stream.writeInt32(pts_count); stream.writeInt32(0x1cb5c415); int count = links.size(); stream.writeInt32(count); - for (TL_contacts_link link : links) { - link.serializeToStream(stream); + for (int a = 0; a < count; a++) { + links.get(a).serializeToStream(stream); } + stream.writeInt32(seq); } } @@ -3787,10 +3813,12 @@ public class TLRPC { public int max_date; public int date; public int user_id; - public contacts_MyLink my_link; - public contacts_ForeignLink foreign_link; + public ContactLink my_link; + public ContactLink foreign_link; public ArrayList messages = new ArrayList<>(); public int pts; + public int pts_count; + public int max_id; public int version; public String type; public MessageMedia media; @@ -3801,12 +3829,12 @@ public class TLRPC { public String first_name; public String last_name; public String username; + public String phone; public int qts; public int id; 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; @@ -3839,13 +3867,13 @@ public class TLRPC { } public static class TL_updateContactLink extends Update { - public static int constructor = 0x51a48a9a; + public static int constructor = 0x9d2e67c5; public void readParams(AbsSerializedData stream) { user_id = stream.readInt32(); - my_link = (contacts_MyLink)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); - foreign_link = (contacts_ForeignLink)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + my_link = (ContactLink)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + foreign_link = (ContactLink)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); } public void serializeToStream(AbsSerializedData stream) { @@ -3857,7 +3885,7 @@ public class TLRPC { } public static class TL_updateReadMessages extends Update { - public static int constructor = 0xc6649e31; + public static int constructor = 0x2e5ab668; public void readParams(AbsSerializedData stream) { @@ -3867,6 +3895,7 @@ public class TLRPC { messages.add(stream.readInt32()); } pts = stream.readInt32(); + pts_count = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { @@ -3874,10 +3903,32 @@ public class TLRPC { stream.writeInt32(0x1cb5c415); int count = messages.size(); stream.writeInt32(count); - for (Integer message : messages) { - stream.writeInt32(message); + for (int a = 0; a < count; a++) { + stream.writeInt32(messages.get(a)); } stream.writeInt32(pts); + stream.writeInt32(pts_count); + } + } + + public static class TL_updateReadHistoryInbox extends Update { + public static int constructor = 0x9961fd5c; + + public Peer peer; + + public void readParams(AbsSerializedData stream) { + peer = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + max_id = stream.readInt32(); + pts = stream.readInt32(); + pts_count = stream.readInt32(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(max_id); + stream.writeInt32(pts); + stream.writeInt32(pts_count); } } @@ -3899,28 +3950,24 @@ public class TLRPC { } } - public static class TL_updateRestoreMessages extends Update { - public static int constructor = 0xd15de04d; + public static class TL_updateReadHistoryOutbox extends Update { + public static int constructor = 0x2f2f21bf; + public Peer peer; public void readParams(AbsSerializedData stream) { - stream.readInt32(); - int count = stream.readInt32(); - for (int a = 0; a < count; a++) { - messages.add(stream.readInt32()); - } + peer = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + max_id = stream.readInt32(); pts = stream.readInt32(); + pts_count = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = messages.size(); - stream.writeInt32(count); - for (Integer message : messages) { - stream.writeInt32(message); - } + peer.serializeToStream(stream); + stream.writeInt32(max_id); stream.writeInt32(pts); + stream.writeInt32(pts_count); } } @@ -3984,7 +4031,7 @@ public class TLRPC { public void readParams(AbsSerializedData stream) { chat_id = stream.readInt32(); user_id = stream.readInt32(); - action = (SendMessageAction)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + action = (SendMessageAction) TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); } public void serializeToStream(AbsSerializedData stream) { @@ -4033,19 +4080,21 @@ public class TLRPC { } public static class TL_updateNewMessage extends Update { - public static int constructor = 0x13abdb3; + public static int constructor = 0x1f2b0afd; public Message message; public void readParams(AbsSerializedData stream) { message = (Message)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); pts = stream.readInt32(); + pts_count = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); message.serializeToStream(stream); stream.writeInt32(pts); + stream.writeInt32(pts_count); } } @@ -4066,8 +4115,7 @@ public class TLRPC { } public static class TL_updateDeleteMessages extends Update { - public static int constructor = 0xa92bfe26; - + public static int constructor = 0xa20db0e5; public void readParams(AbsSerializedData stream) { stream.readInt32(); @@ -4076,6 +4124,7 @@ public class TLRPC { messages.add(stream.readInt32()); } pts = stream.readInt32(); + pts_count = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { @@ -4083,10 +4132,11 @@ public class TLRPC { stream.writeInt32(0x1cb5c415); int count = messages.size(); stream.writeInt32(count); - for (Integer message : messages) { - stream.writeInt32(message); + for (int a = 0; a < count; a++) { + stream.writeInt32(messages.get(a)); } stream.writeInt32(pts); + stream.writeInt32(pts_count); } } @@ -4609,42 +4659,6 @@ public class TLRPC { } } - public static class contacts_MyLink extends TLObject { - public boolean contact; - } - - public static class TL_contacts_myLinkRequested extends contacts_MyLink { - public static int constructor = 0x6c69efee; - - - public void readParams(AbsSerializedData stream) { - contact = stream.readBool(); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeBool(contact); - } - } - - public static class TL_contacts_myLinkContact extends contacts_MyLink { - public static int constructor = 0xc240ebd9; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_contacts_myLinkEmpty extends contacts_MyLink { - public static int constructor = 0xd22a1c60; - - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - } - } - public static class TL_server_DH_inner_data extends TLObject { public static int constructor = 0xb5890dba; @@ -5041,16 +5055,22 @@ public class TLRPC { } public static class TL_config extends TLObject { - public static int constructor = 0x7dae33e0; + public static int constructor = 0x3e6f732a; public int date; public int expires; public boolean test_mode; public int this_dc; public ArrayList dc_options = new ArrayList<>(); - public int chat_big_size; public int chat_size_max; public int broadcast_size_max; + public int online_update_period_ms; + public int offline_blur_timeout_ms; + public int offline_idle_timeout_ms; + public int online_cloud_timeout_ms; + public int notify_cloud_delay_ms; + public int notify_default_delay_ms; + public int chat_big_size; public ArrayList disabled_features = new ArrayList<>(); public void readParams(AbsSerializedData stream) { @@ -5063,9 +5083,15 @@ public class TLRPC { for (int a = 0; a < count; a++) { dc_options.add((TL_dcOption)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } - chat_big_size = stream.readInt32(); chat_size_max = stream.readInt32(); broadcast_size_max = stream.readInt32(); + online_update_period_ms = stream.readInt32(); + offline_blur_timeout_ms = stream.readInt32(); + offline_idle_timeout_ms = stream.readInt32(); + online_cloud_timeout_ms = stream.readInt32(); + notify_cloud_delay_ms = stream.readInt32(); + notify_default_delay_ms = stream.readInt32(); + chat_big_size = stream.readInt32(); stream.readInt32(); count = stream.readInt32(); for (int a = 0; a < count; a++) { @@ -5085,9 +5111,15 @@ public class TLRPC { for (int a = 0; a < count; a++) { dc_options.get(a).serializeToStream(stream); } - stream.writeInt32(chat_big_size); stream.writeInt32(chat_size_max); stream.writeInt32(broadcast_size_max); + stream.writeInt32(online_update_period_ms); + stream.writeInt32(offline_blur_timeout_ms); + stream.writeInt32(offline_idle_timeout_ms); + stream.writeInt32(online_cloud_timeout_ms); + stream.writeInt32(notify_cloud_delay_ms); + stream.writeInt32(notify_default_delay_ms); + stream.writeInt32(chat_big_size); stream.writeInt32(0x1cb5c415); count = disabled_features.size(); stream.writeInt32(count); @@ -5150,10 +5182,14 @@ public class TLRPC { } public static class TL_messages_readMessageContents extends TLObject { - public static int constructor = 0x354b5bc2; + public static int constructor = 0x36a73f77; public ArrayList id = new ArrayList<>(); + public Class responseClass () { + return TL_messages_affectedMessages.class; + } + public void readParams(AbsSerializedData stream) { stream.readInt32(); int count = stream.readInt32(); @@ -5167,8 +5203,8 @@ public class TLRPC { stream.writeInt32(0x1cb5c415); int count = id.size(); stream.writeInt32(count); - for (Integer anId : id) { - stream.writeInt32(anId); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); } } } @@ -5378,6 +5414,25 @@ public class TLRPC { } } + public static class TL_account_updateDeviceLocked extends TLObject { + public static int constructor = 0x38df3532; + + public int period; + + public Class responseClass () { + return Bool.class; + } + + public void readParams(AbsSerializedData stream) { + period = stream.readInt32(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(period); + } + } + public static class TL_messages_getAllStickers extends TLObject { public static int constructor = 0xaa3bc868; @@ -5485,10 +5540,9 @@ public class TLRPC { } public static class TL_messages_chats extends TLObject { - public static int constructor = 0x8150cbd8; + public static int constructor = 0x64ff9fd5; public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); public void readParams(AbsSerializedData stream) { stream.readInt32(); @@ -5496,11 +5550,6 @@ public class TLRPC { for (int a = 0; a < count; a++) { chats.add((Chat)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } - stream.readInt32(); - count = stream.readInt32(); - for (int a = 0; a < count; a++) { - users.add((User)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); - } } public void serializeToStream(AbsSerializedData stream) { @@ -5511,12 +5560,6 @@ public class TLRPC { for (int a = 0; a < count; a++) { chats.get(a).serializeToStream(stream); } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } } } @@ -6444,13 +6487,14 @@ public class TLRPC { public Message message; public ArrayList chats = new ArrayList<>(); public ArrayList users = new ArrayList<>(); - public ArrayList links = new ArrayList<>(); public int pts; + public int pts_count; + public ArrayList links = new ArrayList<>(); public int seq; } public static class TL_messages_statedMessageLink extends messages_StatedMessage { - public static int constructor = 0xa9af2881; + public static int constructor = 0x948a288; public void readParams(AbsSerializedData stream) { @@ -6465,12 +6509,13 @@ public class TLRPC { for (int a = 0; a < count; a++) { users.add((User)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } + pts = stream.readInt32(); + pts_count = stream.readInt32(); stream.readInt32(); count = stream.readInt32(); for (int a = 0; a < count; a++) { links.add((TL_contacts_link)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } - pts = stream.readInt32(); seq = stream.readInt32(); } @@ -6489,19 +6534,20 @@ public class TLRPC { for (int a = 0; a < count; a++) { users.get(a).serializeToStream(stream); } + stream.writeInt32(pts); + stream.writeInt32(pts_count); stream.writeInt32(0x1cb5c415); count = links.size(); stream.writeInt32(count); for (int a = 0; a < count; a++) { links.get(a).serializeToStream(stream); } - stream.writeInt32(pts); stream.writeInt32(seq); } } public static class TL_messages_statedMessage extends messages_StatedMessage { - public static int constructor = 0xd07ae726; + public static int constructor = 0x96240c6a; public void readParams(AbsSerializedData stream) { @@ -6517,7 +6563,7 @@ public class TLRPC { users.add((User)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); } pts = stream.readInt32(); - seq = stream.readInt32(); + pts_count = stream.readInt32(); } public void serializeToStream(AbsSerializedData stream) { @@ -6536,7 +6582,7 @@ public class TLRPC { users.get(a).serializeToStream(stream); } stream.writeInt32(pts); - stream.writeInt32(seq); + stream.writeInt32(pts_count); } } @@ -6634,43 +6680,65 @@ public class TLRPC { } public static class Updates extends TLObject { + public int flags; public int id; - public int from_id; public int chat_id; public String message; public int pts; + public int pts_count; public int date; - public int seq; + public int fwd_from_id; + public int fwd_date; + public int reply_to_msg_id; public ArrayList updates = new ArrayList<>(); public ArrayList users = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); + public int seq; + public int user_id; public Update update; public int seq_start; + public int qts; } public static class TL_updateShortChatMessage extends Updates { - public static int constructor = 0x2b2fbd4e; + public static int constructor = 0x52238b3c; public void readParams(AbsSerializedData stream) { + flags = stream.readInt32(); id = stream.readInt32(); - from_id = stream.readInt32(); + user_id = stream.readInt32(); chat_id = stream.readInt32(); message = stream.readString(); pts = stream.readInt32(); + pts_count = stream.readInt32(); date = stream.readInt32(); - seq = stream.readInt32(); + if ((flags & MESSAGE_FLAG_FWD) != 0) { + fwd_from_id = stream.readInt32(); + fwd_date = stream.readInt32(); + } + if ((flags & MESSAGE_FLAG_REPLY) != 0) { + reply_to_msg_id = stream.readInt32(); + } } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); stream.writeInt32(id); - stream.writeInt32(from_id); + stream.writeInt32(user_id); stream.writeInt32(chat_id); stream.writeString(message); stream.writeInt32(pts); + stream.writeInt32(pts_count); stream.writeInt32(date); - stream.writeInt32(seq); + if ((flags & MESSAGE_FLAG_FWD) != 0) { + stream.writeInt32(fwd_from_id); + stream.writeInt32(fwd_date); + } + if ((flags & MESSAGE_FLAG_REPLY) != 0) { + stream.writeInt32(reply_to_msg_id); + } } } @@ -6724,26 +6792,42 @@ public class TLRPC { } public static class TL_updateShortMessage extends Updates { - public static int constructor = 0xd3f45784; + public static int constructor = 0xed5c2127; public void readParams(AbsSerializedData stream) { + flags = stream.readInt32(); id = stream.readInt32(); - from_id = stream.readInt32(); + user_id = stream.readInt32(); message = stream.readString(); pts = stream.readInt32(); + pts_count = stream.readInt32(); date = stream.readInt32(); - seq = stream.readInt32(); + if ((flags & MESSAGE_FLAG_FWD) != 0) { + fwd_from_id = stream.readInt32(); + fwd_date = stream.readInt32(); + } + if ((flags & MESSAGE_FLAG_REPLY) != 0) { + reply_to_msg_id = stream.readInt32(); + } } public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); stream.writeInt32(id); - stream.writeInt32(from_id); + stream.writeInt32(user_id); stream.writeString(message); stream.writeInt32(pts); + stream.writeInt32(pts_count); stream.writeInt32(date); - stream.writeInt32(seq); + if ((flags & MESSAGE_FLAG_FWD) != 0) { + stream.writeInt32(fwd_from_id); + stream.writeInt32(fwd_date); + } + if ((flags & MESSAGE_FLAG_REPLY) != 0) { + stream.writeInt32(reply_to_msg_id); + } } } @@ -6823,33 +6907,6 @@ public class TLRPC { } } - public static class TL_messages_chat extends TLObject { - public static int constructor = 0x40e9002a; - - public Chat chat; - public ArrayList users = new ArrayList<>(); - - public void readParams(AbsSerializedData stream) { - chat = (Chat)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); - stream.readInt32(); - int count = stream.readInt32(); - for (int a = 0; a < count; a++) { - users.add((User)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32())); - } - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - chat.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = users.size(); - stream.writeInt32(count); - for (User user : users) { - user.serializeToStream(stream); - } - } - } - public static class WallPaper extends TLObject { public int id; public String title; @@ -8249,12 +8306,11 @@ public class TLRPC { } public static class TL_messages_readHistory extends TLObject { - public static int constructor = 0xeed884c6; + public static int constructor = 0xb04f2510; public InputPeer peer; public int max_id; public int offset; - public boolean read_contents; public Class responseClass () { return TL_messages_affectedHistory.class; @@ -8264,7 +8320,6 @@ public class TLRPC { peer = (InputPeer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); max_id = stream.readInt32(); offset = stream.readInt32(); - read_contents = stream.readBool(); } public void serializeToStream(AbsSerializedData stream) { @@ -8272,7 +8327,6 @@ public class TLRPC { peer.serializeToStream(stream); stream.writeInt32(max_id); stream.writeInt32(offset); - stream.writeBool(read_contents); } } @@ -8321,9 +8375,10 @@ public class TLRPC { } public static class TL_messages_sendMessage extends TLObject { - public static int constructor = 0x4cde0aab; + public static int constructor = 0x1ca852a1; public InputPeer peer; + public int reply_to_msg_id; public String message; public long random_id; @@ -8333,6 +8388,7 @@ public class TLRPC { public void readParams(AbsSerializedData stream) { peer = (InputPeer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + reply_to_msg_id = stream.readInt32(); message = stream.readString(); random_id = stream.readInt64(); } @@ -8340,15 +8396,17 @@ public class TLRPC { public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); peer.serializeToStream(stream); + stream.writeInt32(reply_to_msg_id); stream.writeString(message); stream.writeInt64(random_id); } } public static class TL_messages_sendMedia extends TLObject { - public static int constructor = 0xa3c85d76; + public static int constructor = 0xfcee7fc0; public InputPeer peer; + public int reply_to_msg_id; public InputMedia media; public long random_id; @@ -8358,6 +8416,7 @@ public class TLRPC { public void readParams(AbsSerializedData stream) { peer = (InputPeer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + reply_to_msg_id = stream.readInt32(); media = (InputMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); random_id = stream.readInt64(); } @@ -8365,16 +8424,18 @@ public class TLRPC { public void serializeToStream(AbsSerializedData stream) { stream.writeInt32(constructor); peer.serializeToStream(stream); + stream.writeInt32(reply_to_msg_id); media.serializeToStream(stream); stream.writeInt64(random_id); } } public static class TL_messages_forwardMessages extends TLObject { - public static int constructor = 0x514cd10f; + public static int constructor = 0xded42045; public InputPeer peer; public ArrayList id = new ArrayList<>(); + public ArrayList random_id = new ArrayList<>(); public Class responseClass () { return messages_StatedMessages.class; @@ -8387,6 +8448,11 @@ public class TLRPC { for (int a = 0; a < count; a++) { id.add(stream.readInt32()); } + stream.readInt32(); + count = stream.readInt32(); + for (int a = 0; a < count; a++) { + random_id.add(stream.readInt64()); + } } public void serializeToStream(AbsSerializedData stream) { @@ -8395,8 +8461,14 @@ public class TLRPC { stream.writeInt32(0x1cb5c415); int count = id.size(); stream.writeInt32(count); - for (Integer anId : id) { - stream.writeInt32(anId); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + stream.writeInt32(0x1cb5c415); + count = random_id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(random_id.get(a)); } } } @@ -8691,7 +8763,7 @@ public class TLRPC { public int offset; public int limit; - public Class responseClass () { + public Class responseClass() { return TL_upload_file.class; } @@ -8845,7 +8917,7 @@ public class TLRPC { public int id; public long random_id; - public Class responseClass () { + public Class responseClass() { return messages_StatedMessage.class; } @@ -8968,7 +9040,7 @@ public class TLRPC { public TL_inputGeoChat peer; - public Class responseClass () { + public Class responseClass() { return TL_messages_chatFull.class; } @@ -9294,7 +9366,7 @@ public class TLRPC { public TL_inputEncryptedChat peer; public boolean typing; - public Class responseClass () { + public Class responseClass() { return Bool.class; } @@ -9332,8 +9404,62 @@ public class TLRPC { } } + public static class TL_messages_deleteMessages extends TLObject { + public static int constructor = 0xa5f18925; + + public ArrayList id = new ArrayList<>(); + + public Class responseClass () { + return TL_messages_affectedMessages.class; + } + + public void readParams(AbsSerializedData stream) { + stream.readInt32(); + int count = stream.readInt32(); + for (int a = 0; a < count; a++) { + id.add(stream.readInt32()); + } + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + } + } + //manually created + public static class TL_documentAttributeSticker_old extends TL_documentAttributeSticker { + public static int constructor = 0xfb0a5727; + + public void readParams(AbsSerializedData stream) { + + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_messageMediaUnsupported_old extends TL_messageMediaUnsupported { + public static int constructor = 0x29632a36; + + + public void readParams(AbsSerializedData stream) { + bytes = stream.readByteArray(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeByteArray(bytes); + } + } + public static class TL_config_old extends TL_config { public static int constructor = 0x2e54dd74; @@ -9543,6 +9669,34 @@ public class TLRPC { } } + public static class TL_userSelf_old2 extends TL_userSelf { + public static int constructor = 0x7007b451; + + + public void readParams(AbsSerializedData stream) { + id = stream.readInt32(); + first_name = stream.readString(); + last_name = stream.readString(); + username = stream.readString(); + phone = stream.readString(); + photo = (UserProfilePhoto)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + status = (UserStatus)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + inactive = stream.readBool(); + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + stream.writeString(first_name); + stream.writeString(last_name); + stream.writeString(username); + stream.writeString(phone); + photo.serializeToStream(stream); + status.serializeToStream(stream); + stream.writeBool(inactive); + } + } + public static class TL_userSelf_old extends TL_userSelf { public static int constructor = 0x720535ec; @@ -9869,7 +10023,7 @@ public class TLRPC { return 0; } - public Class responseClass () { + public Class responseClass() { return RpcDropAnswer.class; } @@ -10000,6 +10154,7 @@ public class TLRPC { public int date; public String message; public MessageMedia media; + public int reply_to_msg_id; public MessageAction action; public int send_state = 0; public int fwd_msg_id = 0; @@ -10012,10 +10167,11 @@ public class TLRPC { public int layer; public int seq_in; public int seq_out; + public TLRPC.Message replyMessage; public VideoEditedInfo videoEditedInfo = null; } - public static class TL_messageForwarded extends Message { + public static class TL_messageForwarded_old2 extends Message { public static int constructor = 0xa367e716; @@ -10028,6 +10184,7 @@ public class TLRPC { to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); date = stream.readInt32(); message = stream.readString(); + flags |= MESSAGE_FLAG_FWD; media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); if (id < 0) { fwd_msg_id = stream.readInt32(); @@ -10060,6 +10217,60 @@ public class TLRPC { } public static class TL_message extends Message { + public static int constructor = 0xa7ab1991; + + + public void readParams(AbsSerializedData stream) { + flags = stream.readInt32(); + id = stream.readInt32(); + from_id = stream.readInt32(); + to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + if ((flags & MESSAGE_FLAG_FWD) != 0) { + fwd_from_id = stream.readInt32(); + fwd_date = stream.readInt32(); + } + if ((flags & MESSAGE_FLAG_REPLY) != 0) { + reply_to_msg_id = stream.readInt32(); + } + date = stream.readInt32(); + message = stream.readString(); + media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); + if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) { + attachPath = stream.readString(); + } + if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) { + videoEditedInfo = new VideoEditedInfo(); + videoEditedInfo.parseString(message); + } + if ((flags & MESSAGE_FLAG_FWD) != 0 && id < 0) { + fwd_msg_id = stream.readInt32(); + } + } + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(id); + stream.writeInt32(from_id); + to_id.serializeToStream(stream); + if ((flags & MESSAGE_FLAG_FWD) != 0) { + stream.writeInt32(fwd_from_id); + stream.writeInt32(fwd_date); + } + if ((flags & MESSAGE_FLAG_REPLY) != 0) { + stream.writeInt32(reply_to_msg_id); + } + stream.writeInt32(date); + stream.writeString(message); + media.serializeToStream(stream); + stream.writeString(attachPath); + if ((flags & MESSAGE_FLAG_FWD) != 0 && id < 0) { + stream.writeInt32(fwd_msg_id); + } + } + } + + public static class TL_message_old2 extends TL_message { public static int constructor = 0x567699b3; @@ -10143,7 +10354,7 @@ public class TLRPC { } } - public static class TL_messageForwarded_old extends TL_messageForwarded { + public static class TL_messageForwarded_old extends TL_messageForwarded_old2 { public static int constructor = 0x5f46804; @@ -10155,6 +10366,7 @@ public class TLRPC { to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); flags |= stream.readBool() ? MESSAGE_FLAG_OUT : 0; flags |= stream.readBool() ? MESSAGE_FLAG_UNREAD : 0; + flags |= MESSAGE_FLAG_FWD; date = stream.readInt32(); message = stream.readString(); media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); @@ -10259,102 +10471,6 @@ public class TLRPC { } } - public static class TL_messages_deleteMessages extends TLObject { - public static int constructor = 0x14f2dd0a; - - public ArrayList id = new ArrayList<>(); - - public Class responseClass () { - return Vector.class; - } - - public void readParams(AbsSerializedData stream) { - stream.readInt32(); - int count = stream.readInt32(); - for (int a = 0; a < count; a++) { - id.add(stream.readInt32()); - } - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = id.size(); - stream.writeInt32(count); - for (Integer anId : id) { - stream.writeInt32(anId); - } - } - - public void parseVector(Vector vector, AbsSerializedData data) { - int size = data.readInt32(); - for (int a = 0; a < size; a++) { - vector.objects.add(data.readInt32()); - } - } - } - - public static class TL_messages_restoreMessages extends TLObject { - public static int constructor = 0x395f9d7e; - - public ArrayList id = new ArrayList<>(); - - public Class responseClass () { - return Vector.class; - } - - public void readParams(AbsSerializedData stream) { - stream.readInt32(); - int count = stream.readInt32(); - for (int a = 0; a < count; a++) { - id.add(stream.readInt32()); - } - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = id.size(); - stream.writeInt32(count); - for (Integer anId : id) { - stream.writeInt32(anId); - } - } - - public void parseVector(Vector vector, AbsSerializedData data) { - int size = data.readInt32(); - for (int a = 0; a < size; a++) { - vector.objects.add(data.readInt32()); - } - } - } - - public static class TL_messages_receivedMessages extends TLObject { - public static int constructor = 0x28abcb68; - - public int max_id; - - public Class responseClass () { - return Vector.class; - } - - public void readParams(AbsSerializedData stream) { - max_id = stream.readInt32(); - } - - public void serializeToStream(AbsSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(max_id); - } - - public void parseVector(Vector vector, AbsSerializedData data) { - int size = data.readInt32(); - for (int a = 0; a < size; a++) { - vector.objects.add(data.readInt32()); - } - } - } - public static class Vector extends TLObject { public static int constructor = 0x1cb5c415; public ArrayList objects = new ArrayList<>(); @@ -10526,11 +10642,12 @@ public class TLRPC { } public static class TL_dialog extends TLObject { - public static int constructor = 0xab3a99ac; + public static int constructor = 0xc1dd804a; public Peer peer; public int top_message; public int unread_count; + public int read_inbox_max_id; public PeerNotifySettings notify_settings; public int last_message_date; public long id; @@ -10539,6 +10656,7 @@ public class TLRPC { public void readParams(AbsSerializedData stream) { peer = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); top_message = stream.readInt32(); + read_inbox_max_id = stream.readInt32(); unread_count = stream.readInt32(); notify_settings = (PeerNotifySettings)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32()); } @@ -10547,6 +10665,7 @@ public class TLRPC { stream.writeInt32(constructor); peer.serializeToStream(stream); stream.writeInt32(top_message); + stream.writeInt32(read_inbox_max_id); stream.writeInt32(unread_count); notify_settings.serializeToStream(stream); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java b/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java index 406c05139..3772ed52c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java @@ -28,11 +28,11 @@ public class TcpConnection extends ConnectionContext { TcpConnectionStageSuspended } - public abstract static interface TcpConnectionDelegate { - public abstract void tcpConnectionClosed(TcpConnection connection); - public abstract void tcpConnectionConnected(TcpConnection connection); - public abstract void tcpConnectionQuiackAckReceived(TcpConnection connection, int ack); - public abstract void tcpConnectionReceivedData(TcpConnection connection, ByteBufferDesc data, int length); + public interface TcpConnectionDelegate { + void tcpConnectionClosed(TcpConnection connection); + void tcpConnectionConnected(TcpConnection connection); + void tcpConnectionQuiackAckReceived(TcpConnection connection, int ack); + void tcpConnectionReceivedData(TcpConnection connection, ByteBufferDesc data, int length); } private static PyroSelector selector; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index 732ba6f74..5c7c76456 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -48,7 +48,6 @@ public class ActionBar extends FrameLayout { private boolean allowOverlayTitle; private CharSequence lastTitle; - private boolean showingOverlayTitle; private boolean castShadows = true; protected boolean isSearchFieldVisible; @@ -419,6 +418,13 @@ public class ActionBar extends FrameLayout { menu.closeSearchField(); } + public void openSearchField(String text) { + if (isSearchFieldVisible || menu == null) { + return; + } + menu.openSearchField(text); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int actionBarHeight = AndroidUtilities.getCurrentActionBarHeight(); @@ -446,10 +452,9 @@ public class ActionBar extends FrameLayout { } public void setTitleOverlayText(String text) { - if (showingOverlayTitle == (text != null) || !allowOverlayTitle || parentFragment.parentLayout == null) { + if (!allowOverlayTitle || parentFragment.parentLayout == null) { return; } - showingOverlayTitle = text != null; CharSequence textToSet = text != null ? text : lastTitle; if (textToSet != null && titleTextView == null) { createTitleTextView(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index 398ecde2c..16fb026d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -39,12 +39,12 @@ import java.util.ArrayList; public class ActionBarLayout extends FrameLayout { - public static interface ActionBarLayoutDelegate { - public abstract boolean onPreIme(); - public abstract boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout); - public abstract boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout); - public abstract boolean needCloseLastFragment(ActionBarLayout layout); - public abstract void onRebuildAllFragments(ActionBarLayout layout); + public interface ActionBarLayoutDelegate { + boolean onPreIme(); + boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout); + boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout); + boolean needCloseLastFragment(ActionBarLayout layout); + void onRebuildAllFragments(ActionBarLayout layout); } public class LinearLayoutContainer extends LinearLayout { @@ -809,7 +809,7 @@ public class ActionBarLayout extends FrameLayout { backgroundView.setVisibility(GONE); } if (drawerLayoutContainer != null) { - drawerLayoutContainer.setAllowOpenDrawer(true); + drawerLayoutContainer.setAllowOpenDrawer(true, false); } } }; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java index 188804be6..c035b1d47 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -52,7 +52,7 @@ public class ActionBarMenu extends LinearLayout { view.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - onItemClick((Integer)view.getTag()); + onItemClick((Integer) view.getTag()); } }); return view; @@ -147,6 +147,22 @@ public class ActionBarMenu extends LinearLayout { ActionBarMenuItem item = (ActionBarMenuItem)view; if (item.isSearchField()) { parentActionBar.onSearchFieldVisibilityChanged(item.toggleSearch()); + break; + } + } + } + } + + public void openSearchField(String text) { + for (int a = 0; a < getChildCount(); a++) { + View view = getChildAt(a); + if (view instanceof ActionBarMenuItem) { + ActionBarMenuItem item = (ActionBarMenuItem)view; + if (item.isSearchField()) { + parentActionBar.onSearchFieldVisibilityChanged(item.toggleSearch()); + item.getSearchField().setText(text); + item.getSearchField().setSelection(text.length()); + break; } } } 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 fa19aa490..e8991c227 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -42,7 +42,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed { public static class ActionBarMenuItemSearchListener { public void onSearchExpand() { } - public void onSearchCollapse() { } + public boolean onSearchCollapse() { return true; } public void onTextChanged(EditText editText) { } public void onSearchPressed(EditText editText) { } } @@ -322,11 +322,10 @@ public class ActionBarMenuItem extends FrameLayoutFixed { return false; } if (searchContainer.getVisibility() == VISIBLE) { - searchContainer.setVisibility(GONE); - setVisibility(VISIBLE); - AndroidUtilities.hideKeyboard(searchField); - if (listener != null) { - listener.onSearchCollapse(); + if (listener == null || listener != null && listener.onSearchCollapse()) { + searchContainer.setVisibility(GONE); + setVisibility(VISIBLE); + AndroidUtilities.hideKeyboard(searchField); } return false; } else { 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 4d3831a56..479ab5512 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -48,8 +48,8 @@ public class ActionBarPopupWindow extends PopupWindow { private ViewTreeObserver.OnScrollChangedListener mSuperScrollListener; private ViewTreeObserver mViewTreeObserver; - public static interface OnDispatchKeyEventListener { - public void onDispatchKeyEvent(KeyEvent keyEvent); + public interface OnDispatchKeyEventListener { + void onDispatchKeyEvent(KeyEvent keyEvent); } public static class ActionBarPopupWindowLayout extends LinearLayout { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java index 91fa7dc3d..1fdf62d77 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -23,7 +23,7 @@ import org.telegram.messenger.R; public class BaseFragment { private boolean isFinished = false; - private AlertDialog visibleDialog = null; + protected AlertDialog visibleDialog = null; protected View fragmentView; protected ActionBarLayout parentLayout; 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 600807d1f..bbed0a058 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java @@ -251,11 +251,15 @@ public class DrawerLayoutContainer extends FrameLayout { parentActionBarLayout = layout; } - public void setAllowOpenDrawer(boolean value) { + public void setAllowOpenDrawer(boolean value, boolean animated) { allowOpenDrawer = value; if (!allowOpenDrawer && drawerPosition != 0) { - setDrawerPosition(0); - onDrawerAnimationEnd(false); + if (!animated) { + setDrawerPosition(0); + onDrawerAnimationEnd(false); + } else { + closeDrawer(true); + } } } 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 551bf48ed..4ae9e1f19 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -55,7 +55,7 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { private long reqId = 0; private int lastReqId; private MessagesActivitySearchAdapterDelegate delegate; - private boolean needMessagesSearch; + private int needMessagesSearch; private boolean messagesSearchEndReached; private String lastMessagesSearchString; private int lastSearchId = 0; @@ -66,11 +66,11 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { public CharSequence name; } - public static interface MessagesActivitySearchAdapterDelegate { - public abstract void searchStateChanged(boolean searching); + public interface MessagesActivitySearchAdapterDelegate { + void searchStateChanged(boolean searching); } - public DialogsSearchAdapter(Context context, boolean messagesSearch) { + public DialogsSearchAdapter(Context context, int messagesSearch) { mContext = context; needMessagesSearch = messagesSearch; } @@ -88,7 +88,7 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { } private void searchMessagesInternal(final String query) { - if (!needMessagesSearch) { + if (needMessagesSearch == 0) { return; } if (reqId != 0) { @@ -110,7 +110,7 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { req.peer = new TLRPC.TL_inputPeerEmpty(); req.q = query; if (lastMessagesSearchString != null && query.equals(lastMessagesSearchString) && !searchResultMessages.isEmpty()) { - req.max_id = searchResultMessages.get(searchResultMessages.size() - 1).messageOwner.id; + req.max_id = searchResultMessages.get(searchResultMessages.size() - 1).getId(); } lastMessagesSearchString = query; req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); @@ -151,6 +151,9 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { } private void searchDialogsInternal(final String query, final boolean serverOnly, final int searchId) { + if (needMessagesSearch == 2) { + return; + } MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { @Override public void run() { @@ -178,7 +181,7 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { 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")); + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized("SELECT did, date FROM dialogs ORDER BY date DESC LIMIT 200"); while (cursor.next()) { long id = cursor.longValue(0); DialogSearchResult dialogSearchResult = new DialogSearchResult(); @@ -488,8 +491,10 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { if (query == null || query.length() == 0) { searchResult.clear(); searchResultNames.clear(); + if (needMessagesSearch != 2) { + queryServerSearch(null); + } searchMessagesInternal(null); - queryServerSearch(null); notifyDataSetChanged(); } else { final int searchId = ++lastSearchId; @@ -507,7 +512,9 @@ public class DialogsSearchAdapter extends BaseContactsSearchAdapter { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { - queryServerSearch(query); + if (needMessagesSearch != 2) { + queryServerSearch(query); + } searchMessagesInternal(query); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java new file mode 100644 index 000000000..ba3af3b0f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -0,0 +1,186 @@ +/* + * This is the source code of Telegram for Android v. 2.x + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Adapters; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import org.telegram.android.MessageObject; +import org.telegram.android.MessagesController; +import org.telegram.messenger.TLRPC; +import org.telegram.ui.Cells.MentionCell; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +public class MentionsAdapter extends BaseFragmentAdapter { + + public interface MentionsAdapterDelegate { + void needChangePanelVisibility(boolean show); + } + + private Context mContext; + private TLRPC.ChatParticipants info; + private ArrayList searchResult = new ArrayList<>(); + private MentionsAdapterDelegate delegate; + private int usernameStartPosition; + private int usernameLength; + private String lastText; + private int lastPosition; + private ArrayList messages; + + public MentionsAdapter(Context context, MentionsAdapterDelegate delegate) { + mContext = context; + this.delegate = delegate; + } + + public void setChatInfo(TLRPC.ChatParticipants chatParticipants) { + info = chatParticipants; + if (lastText != null) { + searchUsername(lastText, lastPosition, messages); + } + } + + public void searchUsername(String text, int position, ArrayList messageObjects) { + if (text == null || text.length() == 0 || position < text.length()) { + delegate.needChangePanelVisibility(false); + lastText = null; + return; + } + if (info == null) { + lastText = text; + lastPosition = position; + messages = messageObjects; + delegate.needChangePanelVisibility(false); + return; + } + lastText = null; + StringBuilder username = new StringBuilder(); + boolean found = false; + for (int a = position; a >= 0; a--) { + if (a >= text.length()) { + continue; + } + char ch = text.charAt(a); + if (ch == '@' && (a == 0 || text.charAt(a - 1) == ' ')) { + found = true; + usernameStartPosition = a; + usernameLength = username.length() + 1; + break; + } + if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_')) { + delegate.needChangePanelVisibility(false); + return; + } + username.insert(0, ch); + } + if (!found) { + delegate.needChangePanelVisibility(false); + return; + } + final ArrayList users = new ArrayList<>(); + for (int a = 0; a < Math.min(100, messageObjects.size()); a++) { + int from_id = messageObjects.get(a).messageOwner.from_id; + if (!users.contains(from_id)) { + users.add(from_id); + } + } + String usernameString = username.toString().toLowerCase(); + ArrayList newResult = new ArrayList<>(); + for (TLRPC.TL_chatParticipant chatParticipant : info.participants) { + TLRPC.User user = MessagesController.getInstance().getUser(chatParticipant.user_id); + if (user == null || user instanceof TLRPC.TL_userSelf) { + continue; + } + if (user.username != null && user.username.length() > 0 && (usernameString.length() > 0 && user.username.toLowerCase().startsWith(usernameString) || usernameString.length() == 0)) { + newResult.add(user); + } + } + searchResult = newResult; + Collections.sort(searchResult, new Comparator() { + @Override + public int compare(TLRPC.User lhs, TLRPC.User rhs) { + int lhsNum = users.indexOf(lhs.id); + int rhsNum = users.indexOf(rhs.id); + if (lhsNum != -1 && rhsNum != -1) { + return Integer.compare(lhsNum, rhsNum); + } else if (lhsNum != -1 && rhsNum == -1) { + return -1; + } else if (lhsNum == -1 && rhsNum != -1) { + return 1; + } + return 0; + } + }); + notifyDataSetChanged(); + delegate.needChangePanelVisibility(!newResult.isEmpty()); + } + + public int getUsernameStartPosition() { + return usernameStartPosition; + } + + public int getUsernameLength() { + return usernameLength; + } + + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public int getCount() { + return searchResult.size(); + } + + @Override + public boolean isEmpty() { + return searchResult.isEmpty(); + } + + @Override + public int getItemViewType(int position) { + return 0; + } + + @Override + public boolean hasStableIds() { + return true; + } + + @Override + public boolean areAllItemsEnabled() { + return true; + } + + @Override + public boolean isEnabled(int position) { + return true; + } + + @Override + public TLRPC.User getItem(int i) { + if (i < 0 || i >= searchResult.size()) { + return null; + } + return searchResult.get(i); + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + if (view == null) { + view = new MentionCell(mContext); + } + ((MentionCell) view).setUser(searchResult.get(i)); + return view; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java index 538756f76..ef6f61c0f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -47,8 +47,8 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio private String lastSticker; private boolean visible; - public static interface StickersAdapterDelegate { - public abstract void needChangePanelVisibility(boolean show); + public interface StickersAdapterDelegate { + void needChangePanelVisibility(boolean show); } private class Holder extends RecyclerView.ViewHolder { @@ -80,7 +80,7 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio @Override public void run() { if (stickers != null && !stickers.isEmpty() && !stickersToLoad.isEmpty() && visible) { - String fileName = (String)args[0]; + String fileName = (String) args[0]; stickersToLoad.remove(fileName); if (stickersToLoad.isEmpty()) { delegate.needChangePanelVisibility(stickers != null && !stickers.isEmpty() && stickersToLoad.isEmpty()); @@ -214,6 +214,7 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio final HashMap> result = new HashMap<>(); for (TLRPC.TL_stickerPack stickerPack : res.packs) { if (stickerPack != null && stickerPack.emoticon != null) { + stickerPack.emoticon = stickerPack.emoticon.replace("\uFE0F", ""); ArrayList arrayList = result.get(stickerPack.emoticon); for (Long id : stickerPack.documents) { TLRPC.Document document = documents.get(id); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Animation/Animator10.java b/TMessagesProj/src/main/java/org/telegram/ui/Animation/Animator10.java index 32e6ccfe1..31a6d756b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Animation/Animator10.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Animation/Animator10.java @@ -177,14 +177,14 @@ public abstract class Animator10 implements Cloneable { } - public static interface AnimatorListener { + public interface AnimatorListener { void onAnimationStart(Animator10 animation); void onAnimationEnd(Animator10 animation); void onAnimationCancel(Animator10 animation); void onAnimationRepeat(Animator10 animation); } - public static interface AnimatorPauseListener { + public interface AnimatorPauseListener { void onAnimationPause(Animator10 animation); void onAnimationResume(Animator10 animation); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Animation/TypeEvaluator.java b/TMessagesProj/src/main/java/org/telegram/ui/Animation/TypeEvaluator.java index 33de5d619..db5769e0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Animation/TypeEvaluator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Animation/TypeEvaluator.java @@ -17,5 +17,5 @@ package org.telegram.ui.Animation; public interface TypeEvaluator { - public T evaluate(float fraction, T startValue, T endValue); + T evaluate(float fraction, T startValue, T endValue); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Animation/ValueAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Animation/ValueAnimator.java index b4baca6de..168ff1dac 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Animation/ValueAnimator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Animation/ValueAnimator.java @@ -646,7 +646,7 @@ public class ValueAnimator extends Animator10 { return anim; } - public static interface AnimatorUpdateListener { + public interface AnimatorUpdateListener { void onAnimationUpdate(ValueAnimator animation); } 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 f07555cf2..2fcaed609 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -25,6 +25,7 @@ import org.telegram.android.AndroidUtilities; import org.telegram.android.ImageReceiver; import org.telegram.android.MessageObject; import org.telegram.android.MessagesController; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; @@ -35,10 +36,10 @@ import org.telegram.ui.Components.AvatarDrawable; public class ChatActionCell extends BaseCell { - public static interface ChatActionCellDelegate { - public abstract void didClickedImage(ChatActionCell cell); - public abstract void didLongPressed(ChatActionCell cell); - public abstract void needOpenUserProfile(int uid); + public interface ChatActionCellDelegate { + void didClickedImage(ChatActionCell cell); + void didLongPressed(ChatActionCell cell); + void needOpenUserProfile(int uid); } private static Drawable backgroundBlack; @@ -55,7 +56,6 @@ public class ChatActionCell extends BaseCell { private int textX = 0; private int textY = 0; private int textXLeft = 0; - private boolean useBlackBackground = false; private int previousWidth = 0; private boolean imagePressed = false; @@ -119,10 +119,6 @@ public class ChatActionCell extends BaseCell { requestLayout(); } - public void setUseBlackBackground(boolean value) { - useBlackBackground = value; - } - public MessageObject getMessageObject() { return currentMessageObject; } @@ -267,7 +263,7 @@ public class ChatActionCell extends BaseCell { } Drawable backgroundDrawable = null; - if (useBlackBackground) { + if (ApplicationLoader.isCustomTheme()) { backgroundDrawable = backgroundBlack; } else { backgroundDrawable = backgroundBlue; 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 92b5c0dec..7a3f1a6b4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java @@ -183,9 +183,15 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega buttonState = 3; invalidate(); } else if (buttonState == 3) { - FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.audio); - buttonState = 2; - invalidate(); + if (currentMessageObject.isOut() && currentMessageObject.isSending()) { + if (delegate != null) { + delegate.didPressedCancelSendButton(this); + } + } else { + FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.audio); + buttonState = 2; + invalidate(); + } } } @@ -291,12 +297,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); - setMeasuredDimension(width, AndroidUtilities.dp(68)); - if (isChat) { - backgroundWidth = Math.min(width - AndroidUtilities.dp(102), AndroidUtilities.dp(300)); - } else { - backgroundWidth = Math.min(width - AndroidUtilities.dp(50), AndroidUtilities.dp(300)); - } + setMeasuredDimension(width, AndroidUtilities.dp(68) + namesOffset); } @Override @@ -325,7 +326,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega } int diff = 0; if (needAvatarImage) { - avatarImage.setImageCoords(x, AndroidUtilities.dp(9), AndroidUtilities.dp(50), AndroidUtilities.dp(50)); + avatarImage.setImageCoords(x, AndroidUtilities.dp(9) + namesOffset, AndroidUtilities.dp(50), AndroidUtilities.dp(50)); } else { diff = AndroidUtilities.dp(56); seekBarX -= diff; @@ -337,8 +338,8 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega seekBar.height = AndroidUtilities.dp(30); progressView.width = backgroundWidth - AndroidUtilities.dp(136) + diff; progressView.height = AndroidUtilities.dp(30); - seekBarY = AndroidUtilities.dp(13); - buttonY = AndroidUtilities.dp(10); + seekBarY = AndroidUtilities.dp(13) + namesOffset; + buttonY = AndroidUtilities.dp(10) + namesOffset; updateProgress(); } @@ -358,6 +359,12 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega @Override public void setMessageObject(MessageObject messageObject) { if (currentMessageObject != messageObject || isUserDataChanged()) { + if (AndroidUtilities.isTablet()) { + backgroundWidth = Math.min(AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(isChat ? 102 : 50), AndroidUtilities.dp(300)); + } else { + backgroundWidth = Math.min(AndroidUtilities.displaySize.x - AndroidUtilities.dp(isChat ? 102 : 50), AndroidUtilities.dp(300)); + } + int uid = messageObject.messageOwner.media.audio.user_id; if (uid == 0) { uid = messageObject.messageOwner.from_id; @@ -430,7 +437,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega buttonDrawable.draw(canvas); canvas.save(); - canvas.translate(timeX, AndroidUtilities.dp(45)); + canvas.translate(timeX, AndroidUtilities.dp(45) + namesOffset); timeLayout.draw(canvas); canvas.restore(); } 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 8258de3f7..0fdec7f4b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java @@ -11,6 +11,7 @@ package org.telegram.ui.Cells; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.text.Html; import android.text.Layout; @@ -22,7 +23,10 @@ import android.view.SoundEffectConstants; import org.telegram.android.AndroidUtilities; import org.telegram.android.ContactsController; +import org.telegram.android.Emoji; import org.telegram.android.LocaleController; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLoader; import org.telegram.messenger.TLRPC; import org.telegram.android.MessagesController; import org.telegram.messenger.R; @@ -32,16 +36,19 @@ import org.telegram.ui.Components.AvatarDrawable; public class ChatBaseCell extends BaseCell { - public static interface ChatBaseCellDelegate { - public abstract void didPressedUserAvatar(ChatBaseCell cell, TLRPC.User user); - public abstract void didPressedCancelSendButton(ChatBaseCell cell); - public abstract void didLongPressed(ChatBaseCell cell); - public abstract boolean canPerformActions(); + public interface ChatBaseCellDelegate { + void didPressedUserAvatar(ChatBaseCell cell, TLRPC.User user); + void didPressedCancelSendButton(ChatBaseCell cell); + void didLongPressed(ChatBaseCell cell); + void didPressReplyMessage(ChatBaseCell cell, int id); + void didPressUrl(String url); + boolean canPerformActions(); } public boolean isChat = false; protected boolean isPressed = false; protected boolean forwardName = false; + protected boolean isHighlighted = false; protected boolean media = false; protected boolean isCheckPressed = true; private boolean wasLayout = false; @@ -66,12 +73,17 @@ public class ChatBaseCell extends BaseCell { private static Drawable clockMediaDrawable; private static Drawable broadcastMediaDrawable; private static Drawable errorDrawable; + private static Drawable backgroundBlack; + private static Drawable backgroundBlue; protected static Drawable mediaBackgroundDrawable; private static TextPaint timePaintIn; private static TextPaint timePaintOut; private static TextPaint timeMediaPaint; private static TextPaint namePaint; private static TextPaint forwardNamePaint; + private static TextPaint replyNamePaint; + private static TextPaint replyTextPaint; + private static Paint replyLinePaint; protected int backgroundWidth = 100; @@ -83,6 +95,19 @@ public class ChatBaseCell extends BaseCell { private boolean avatarPressed = false; private boolean forwardNamePressed = false; + private StaticLayout replyNameLayout; + private StaticLayout replyTextLayout; + private ImageReceiver replyImageReceiver; + private int replyStartX; + private int replyStartY; + protected int replyNameWidth; + private float replyNameOffset; + protected int replyTextWidth; + private float replyTextOffset; + private boolean needReplyImage = false; + private boolean replyPressed = false; + private TLRPC.FileLocation currentReplyPhoto; + private StaticLayout nameLayout; protected int nameWidth; private float nameOffsetX = 0; @@ -137,6 +162,8 @@ public class ChatBaseCell extends BaseCell { mediaBackgroundDrawable = getResources().getDrawable(R.drawable.phototime); broadcastDrawable = getResources().getDrawable(R.drawable.broadcast3); broadcastMediaDrawable = getResources().getDrawable(R.drawable.broadcast4); + backgroundBlack = getResources().getDrawable(R.drawable.system_black); + backgroundBlue = getResources().getDrawable(R.drawable.system_blue); timePaintIn = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); timePaintIn.setTextSize(AndroidUtilities.dp(12)); @@ -155,17 +182,29 @@ public class ChatBaseCell extends BaseCell { forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); forwardNamePaint.setTextSize(AndroidUtilities.dp(14)); + + replyNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + replyNamePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + replyNamePaint.setTextSize(AndroidUtilities.dp(14)); + + replyTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + replyTextPaint.setTextSize(AndroidUtilities.dp(14)); + + replyLinePaint = new Paint(); } avatarImage = new ImageReceiver(this); avatarImage.setRoundRadius(AndroidUtilities.dp(21)); avatarDrawable = new AvatarDrawable(); + replyImageReceiver = new ImageReceiver(this); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); avatarImage.clearImage(); + replyImageReceiver.clearImage(); currentPhoto = null; + currentReplyPhoto = null; } @Override @@ -178,6 +217,14 @@ public class ChatBaseCell extends BaseCell { this.delegate = delegate; } + public void setHighlighted(boolean value) { + if (isHighlighted == value) { + return; + } + isHighlighted = value; + invalidate(); + } + public void setCheckPressed(boolean value, boolean pressed) { isCheckPressed = value; isPressed = pressed; @@ -202,10 +249,27 @@ public class ChatBaseCell extends BaseCell { newPhoto = newUser.photo.photo_small; } + if (replyTextLayout == null && currentMessageObject.replyMessageObject != null) { + return true; + } + if (currentPhoto == null && newPhoto != null || currentPhoto != null && newPhoto == null || currentPhoto != null && newPhoto != null && (currentPhoto.local_id != newPhoto.local_id || currentPhoto.volume_id != newPhoto.volume_id)) { return true; } + TLRPC.FileLocation newReplyPhoto = null; + + if (currentMessageObject.replyMessageObject != null) { + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(currentMessageObject.replyMessageObject.photoThumbs, 80); + if (photoSize != null && currentMessageObject.replyMessageObject.type != 13) { + newReplyPhoto = photoSize.location; + } + } + + if (currentReplyPhoto == null && newReplyPhoto != null) { + return true; + } + String newNameString = null; if (drawName && isChat && newUser != null && !currentMessageObject.isOut()) { newNameString = ContactsController.formatName(newUser.first_name, newUser.last_name); @@ -217,7 +281,7 @@ public class ChatBaseCell extends BaseCell { newUser = MessagesController.getInstance().getUser(currentMessageObject.messageOwner.fwd_from_id); newNameString = null; - if (newUser != null && drawForwardedName && currentMessageObject.messageOwner instanceof TLRPC.TL_messageForwarded) { + if (newUser != null && drawForwardedName && currentMessageObject.messageOwner.fwd_from_id != 0) { newNameString = ContactsController.formatName(newUser.first_name, newUser.last_name); } return currentForwardNameString == null && newNameString != null || currentForwardNameString != null && newNameString == null || currentForwardNameString != null && newNameString != null && !currentForwardNameString.equals(newNameString); @@ -231,6 +295,11 @@ public class ChatBaseCell extends BaseCell { isCheckPressed = true; isAvatarVisible = false; wasLayout = false; + replyNameLayout = null; + replyTextLayout = null; + replyNameWidth = 0; + replyTextWidth = 0; + currentReplyPhoto = null; currentUser = MessagesController.getInstance().getUser(messageObject.messageOwner.from_id); if (isChat && !messageObject.isOut()) { @@ -272,7 +341,7 @@ public class ChatBaseCell extends BaseCell { nameLayout = new StaticLayout(nameStringFinal, namePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (nameLayout.getLineCount() > 0) { nameWidth = (int)Math.ceil(nameLayout.getLineWidth(0)); - namesOffset += AndroidUtilities.dp(18); + namesOffset += AndroidUtilities.dp(19); nameOffsetX = nameLayout.getLineLeft(0); } else { nameWidth = 0; @@ -283,7 +352,7 @@ public class ChatBaseCell extends BaseCell { nameWidth = 0; } - if (drawForwardedName && messageObject.messageOwner instanceof TLRPC.TL_messageForwarded) { + if (drawForwardedName && messageObject.isForwarded()) { currentForwardUser = MessagesController.getInstance().getUser(messageObject.messageOwner.fwd_from_id); if (currentForwardUser != null) { currentForwardNameString = ContactsController.formatName(currentForwardUser.first_name, currentForwardUser.last_name); @@ -311,6 +380,87 @@ public class ChatBaseCell extends BaseCell { forwardedNameWidth = 0; } + if (messageObject.isReply()) { + namesOffset += AndroidUtilities.dp(42); + if (messageObject.contentType == 2 || messageObject.contentType == 3) { + namesOffset += AndroidUtilities.dp(4); + } else if (messageObject.contentType == 1) { + if (messageObject.type == 13) { + namesOffset -= AndroidUtilities.dp(42); + } else { + namesOffset += AndroidUtilities.dp(5); + } + } + + int maxWidth; + if (messageObject.type == 13) { + int width; + if (AndroidUtilities.isTablet()) { + int leftWidth = AndroidUtilities.displaySize.x / 100 * 35; + if (leftWidth < AndroidUtilities.dp(320)) { + leftWidth = AndroidUtilities.dp(320); + } + width = AndroidUtilities.displaySize.x - leftWidth; + } else { + width = AndroidUtilities.displaySize.x; + } + if (messageObject.isOut()) { + maxWidth = width - backgroundWidth - AndroidUtilities.dp(60); + } else { + maxWidth = width - backgroundWidth - AndroidUtilities.dp(56 + (isChat ? 61 : 0)); + } + } else { + maxWidth = getMaxNameWidth() - AndroidUtilities.dp(22); + } + if (!media && messageObject.contentType != 0) { + maxWidth -= AndroidUtilities.dp(8); + } + + CharSequence stringFinalName = null; + CharSequence stringFinalText = null; + if (messageObject.replyMessageObject != null) { + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, 80); + if (photoSize == null || messageObject.replyMessageObject.type == 13 || messageObject.type == 13 && !AndroidUtilities.isTablet()) { + replyImageReceiver.setImageBitmap((Drawable) null); + needReplyImage = false; + } else { + currentReplyPhoto = photoSize.location; + replyImageReceiver.setImage(photoSize.location, "50_50", null, true); + needReplyImage = true; + maxWidth -= AndroidUtilities.dp(44); + } + + TLRPC.User user = MessagesController.getInstance().getUser(messageObject.replyMessageObject.messageOwner.from_id); + if (user != null) { + stringFinalName = TextUtils.ellipsize(ContactsController.formatName(user.first_name, user.last_name).replace("\n", " "), replyNamePaint, maxWidth - AndroidUtilities.dp(8), TextUtils.TruncateAt.END); + } + if (messageObject.replyMessageObject.messageText != null && messageObject.replyMessageObject.messageText.length() > 0) { + String mess = messageObject.replyMessageObject.messageText.toString(); + if (mess.length() > 150) { + mess = mess.substring(0, 150); + } + mess = mess.replace("\n", " "); + stringFinalText = Emoji.replaceEmoji(mess, replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14)); + stringFinalText = TextUtils.ellipsize(stringFinalText, replyTextPaint, maxWidth - AndroidUtilities.dp(8), TextUtils.TruncateAt.END); + } + } + if (stringFinalName == null) { + stringFinalName = LocaleController.getString("Loading", R.string.Loading); + } + replyNameLayout = new StaticLayout(stringFinalName, replyNamePaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (replyNameLayout.getLineCount() > 0) { + replyNameWidth = (int)Math.ceil(replyNameLayout.getLineWidth(0)) + AndroidUtilities.dp(12 + (needReplyImage ? 44 : 0)); + replyNameOffset = replyNameLayout.getLineLeft(0); + } + if (stringFinalText != null) { + replyTextLayout = new StaticLayout(stringFinalText, replyTextPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (replyTextLayout.getLineCount() > 0) { + replyTextWidth = (int) Math.ceil(replyTextLayout.getLineWidth(0)) + AndroidUtilities.dp(12 + (needReplyImage ? 44 : 0)); + replyTextOffset = replyTextLayout.getLineLeft(0); + } + } + } + requestLayout(); } @@ -337,6 +487,11 @@ public class ChatBaseCell extends BaseCell { forwardNamePressed = true; result = true; } + } else if (currentMessageObject.isReply()) { + if (x >= replyStartX && x <= replyStartX + Math.max(replyNameWidth, replyTextWidth) && y >= replyStartY && y <= replyStartY + AndroidUtilities.dp(35)) { + replyPressed = true; + result = true; + } } if (result) { startCheckLongPress(); @@ -374,6 +529,20 @@ public class ChatBaseCell extends BaseCell { forwardNamePressed = false; } } + } else if (replyPressed) { + if (event.getAction() == MotionEvent.ACTION_UP) { + replyPressed = false; + playSoundEffect(SoundEffectConstants.CLICK); + if (delegate != null) { + delegate.didPressReplyMessage(this, currentMessageObject.messageOwner.reply_to_msg_id); + } + } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { + replyPressed = false; + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (!(x >= replyStartX && x <= replyStartX + Math.max(replyNameWidth, replyTextWidth) && y >= replyStartY && y <= replyStartY + AndroidUtilities.dp(35))) { + replyPressed = false; + } + } } } return result; @@ -442,7 +611,7 @@ public class ChatBaseCell extends BaseCell { Drawable currentBackgroundDrawable = null; if (currentMessageObject.isOut()) { - if (isPressed() && isCheckPressed || !isCheckPressed && isPressed) { + if (isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted) { if (!media) { currentBackgroundDrawable = backgroundDrawableOutSelected; } else { @@ -457,7 +626,7 @@ public class ChatBaseCell extends BaseCell { } setDrawableBounds(currentBackgroundDrawable, layoutWidth - backgroundWidth - (!media ? 0 : AndroidUtilities.dp(9)), AndroidUtilities.dp(1), backgroundWidth, layoutHeight - AndroidUtilities.dp(2)); } else { - if (isPressed() && isCheckPressed || !isCheckPressed && isPressed) { + if (isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted) { if (!media) { currentBackgroundDrawable = backgroundDrawableInSelected; } else { @@ -491,21 +660,79 @@ public class ChatBaseCell extends BaseCell { } if (drawForwardedName && forwardedNameLayout != null) { - canvas.save(); + forwardNameY = AndroidUtilities.dp(10 + (drawName ? 19 : 0)); if (currentMessageObject.isOut()) { forwardNamePaint.setColor(0xff4a923c); forwardNameX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(10); - forwardNameY = AndroidUtilities.dp(10 + (drawName ? 18 : 0)); } else { forwardNamePaint.setColor(0xff006fc8); forwardNameX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(19); - forwardNameY = AndroidUtilities.dp(10 + (drawName ? 18 : 0)); } + canvas.save(); canvas.translate(forwardNameX - forwardNameOffsetX, forwardNameY); forwardedNameLayout.draw(canvas); canvas.restore(); } + if (currentMessageObject.isReply()) { + if (currentMessageObject.type == 13) { + replyLinePaint.setColor(0xffffffff); + replyNamePaint.setColor(0xffffffff); + replyTextPaint.setColor(0xffffffff); + int backWidth; + if (currentMessageObject.isOut()) { + backWidth = currentBackgroundDrawable.getBounds().left - AndroidUtilities.dp(32); + replyStartX = currentBackgroundDrawable.getBounds().left - AndroidUtilities.dp(9) - backWidth; + } else { + backWidth = getWidth() - currentBackgroundDrawable.getBounds().right - AndroidUtilities.dp(32); + replyStartX = currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(23); + } + Drawable back; + if (ApplicationLoader.isCustomTheme()) { + back = backgroundBlack; + } else { + back = backgroundBlue; + } + replyStartY = layoutHeight - AndroidUtilities.dp(58); + back.setBounds(replyStartX - AndroidUtilities.dp(7), replyStartY - AndroidUtilities.dp(6), replyStartX - AndroidUtilities.dp(7) + backWidth, replyStartY + AndroidUtilities.dp(41)); + back.draw(canvas); + } else { + if (currentMessageObject.isOut()) { + replyLinePaint.setColor(0xff8dc97a); + replyNamePaint.setColor(0xff61a349); + replyTextPaint.setColor(0xff70b15c); + replyStartX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(11); + } else { + replyLinePaint.setColor(0xff6c9fd2); + replyNamePaint.setColor(0xff377aae); + replyTextPaint.setColor(0xff999999); + if (currentMessageObject.contentType == 1 && media) { + replyStartX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(11); + } else { + replyStartX = currentBackgroundDrawable.getBounds().left + AndroidUtilities.dp(20); + } + } + replyStartY = AndroidUtilities.dp(12 + (drawForwardedName && forwardedNameLayout != null ? 36 : 0) + (drawName && nameLayout != null ? 20 : 0)); + } + canvas.drawRect(replyStartX, replyStartY, replyStartX + AndroidUtilities.dp(2), replyStartY + AndroidUtilities.dp(35), replyLinePaint); + if (needReplyImage) { + replyImageReceiver.setImageCoords(replyStartX + AndroidUtilities.dp(10), replyStartY, AndroidUtilities.dp(35), AndroidUtilities.dp(35)); + replyImageReceiver.draw(canvas); + } + if (replyNameLayout != null) { + canvas.save(); + canvas.translate(replyStartX - replyNameOffset + AndroidUtilities.dp(10 + (needReplyImage ? 44 : 0)), replyStartY); + replyNameLayout.draw(canvas); + canvas.restore(); + } + if (replyTextLayout != null) { + canvas.save(); + canvas.translate(replyStartX - replyTextOffset + AndroidUtilities.dp(10 + (needReplyImage ? 44 : 0)), replyStartY + AndroidUtilities.dp(19)); + replyTextLayout.draw(canvas); + canvas.restore(); + } + } + if (drawTime) { if (media) { setDrawableBounds(mediaBackgroundDrawable, timeX - AndroidUtilities.dp(3), layoutHeight - AndroidUtilities.dp(27.5f), timeWidth + AndroidUtilities.dp(6 + (currentMessageObject.isOut() ? 20 : 0)), AndroidUtilities.dp(16.5f)); 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 13edf97c4..45907c708 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java @@ -32,9 +32,9 @@ import org.telegram.ui.Components.AvatarDrawable; public class ChatContactCell extends ChatBaseCell { - public static interface ChatContactCellDelegate { - public abstract void didClickAddButton(ChatContactCell cell, TLRPC.User user); - public abstract void didClickPhone(ChatContactCell cell); + public interface ChatContactCellDelegate { + void didClickAddButton(ChatContactCell cell, TLRPC.User user); + void didClickPhone(ChatContactCell cell); } private static TextPaint namePaint; @@ -113,7 +113,7 @@ public class ChatContactCell extends ChatBaseCell { if (x >= avatarImage.getImageX() && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(42) && y >= avatarImage.getImageY() && y <= avatarImage.getImageY() + avatarImage.getImageHeight()) { avatarPressed = true; result = true; - } else if (x >= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(52) && y >= AndroidUtilities.dp(13) && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(92) && y <= AndroidUtilities.dp(52)) { + } else if (x >= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(52) && y >= AndroidUtilities.dp(13) + namesOffset && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(92) && y <= AndroidUtilities.dp(52) + namesOffset) { buttonPressed = true; result = true; } @@ -154,7 +154,7 @@ public class ChatContactCell extends ChatBaseCell { } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { buttonPressed = false; } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - if (!(x >= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(52) && y >= AndroidUtilities.dp(13) && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(92) && y <= AndroidUtilities.dp(52))) { + if (!(x >= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(52) && y >= AndroidUtilities.dp(13) + namesOffset && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(92) && y <= AndroidUtilities.dp(52) + namesOffset)) { buttonPressed = false; } } @@ -235,7 +235,7 @@ public class ChatContactCell extends ChatBaseCell { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(71)); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), AndroidUtilities.dp(71) + namesOffset); } @Override @@ -257,7 +257,7 @@ public class ChatContactCell extends ChatBaseCell { x = AndroidUtilities.dp(16); } } - avatarImage.setImageCoords(x, AndroidUtilities.dp(9), AndroidUtilities.dp(42), AndroidUtilities.dp(42)); + avatarImage.setImageCoords(x, AndroidUtilities.dp(9) + namesOffset, AndroidUtilities.dp(42), AndroidUtilities.dp(42)); } @Override @@ -272,14 +272,14 @@ public class ChatContactCell extends ChatBaseCell { if (nameLayout != null) { canvas.save(); - canvas.translate(avatarImage.getImageX() + avatarImage.getImageWidth() + AndroidUtilities.dp(9), AndroidUtilities.dp(10)); + canvas.translate(avatarImage.getImageX() + avatarImage.getImageWidth() + AndroidUtilities.dp(9), AndroidUtilities.dp(10) + namesOffset); namePaint.setColor(AvatarDrawable.getColorForId(currentMessageObject.messageOwner.media.user_id)); nameLayout.draw(canvas); canvas.restore(); } if (phoneLayout != null) { canvas.save(); - canvas.translate(avatarImage.getImageX() + avatarImage.getImageWidth() + AndroidUtilities.dp(9), AndroidUtilities.dp(31)); + canvas.translate(avatarImage.getImageX() + avatarImage.getImageWidth() + AndroidUtilities.dp(9), AndroidUtilities.dp(31) + namesOffset); phoneLayout.draw(canvas); canvas.restore(); } @@ -291,7 +291,7 @@ public class ChatContactCell extends ChatBaseCell { } else { addContactDrawable = addContactDrawableIn; } - setDrawableBounds(addContactDrawable, avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(78), AndroidUtilities.dp(13)); + setDrawableBounds(addContactDrawable, avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(78), AndroidUtilities.dp(13) + namesOffset); addContactDrawable.draw(canvas); } } 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 db40b041c..48b337a0d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java @@ -43,9 +43,9 @@ import java.util.Locale; public class ChatMediaCell extends ChatBaseCell implements MediaController.FileDownloadProgressListener { - public static interface ChatMediaCellDelegate { - public abstract void didClickedImage(ChatMediaCell cell); - public abstract void didPressedOther(ChatMediaCell cell); + public interface ChatMediaCellDelegate { + void didClickedImage(ChatMediaCell cell); + void didPressedOther(ChatMediaCell cell); } private static Drawable placeholderDocInDrawable; @@ -191,7 +191,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD otherPressed = true; result = true; } - } else { + } else if (currentMessageObject.type != 13) { if (x >= photoImage.getImageX() && x <= photoImage.getImageX() + backgroundWidth && y >= photoImage.getImageY() && y <= photoImage.getImageY() + photoImage.getImageHeight()) { imagePressed = true; result = true; @@ -359,7 +359,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD photoImage.cancelLoadImage(); } else if (currentMessageObject.type == 8 || currentMessageObject.type == 9) { FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.document); - if (lastDownloadedGifMessage != null && lastDownloadedGifMessage.messageOwner.id == currentMessageObject.messageOwner.id) { + if (lastDownloadedGifMessage != null && lastDownloadedGifMessage.getId() == currentMessageObject.getId()) { lastDownloadedGifMessage = null; } } else if (currentMessageObject.type == 3) { @@ -413,7 +413,6 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD media = messageObject.type != 9; boolean dataChanged = currentMessageObject == messageObject && (isUserDataChanged() || photoNotSet); if (currentMessageObject != messageObject || isPhotoDataChanged(messageObject) || dataChanged) { - super.setMessageObject(messageObject); cancelLoading = false; buttonState = -1; @@ -510,13 +509,13 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD photoImage.setImageBitmap((BitmapDrawable) null); } } else if (messageObject.type == 4) { //geo - photoWidth = AndroidUtilities.dp(100); + photoWidth = AndroidUtilities.dp(200); photoHeight = AndroidUtilities.dp(100); backgroundWidth = photoWidth + AndroidUtilities.dp(12); double lat = messageObject.messageOwner.media.geo.lat; double lon = messageObject.messageOwner.media.geo._long; - 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); + currentUrl = String.format(Locale.US, "https://maps.googleapis.com/maps/api/staticmap?center=%f,%f&zoom=13&size=200x100&maptype=roadmap&scale=%d&markers=color:red|size:big|%f,%f&sensor=false", lat, lon, Math.min(2, (int)Math.ceil(AndroidUtilities.density)), lat, lon); photoImage.setNeedsQualityThumb(false); photoImage.setShouldGenerateQualityThumb(false); photoImage.setParentMessageObject(null); @@ -531,6 +530,12 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD } } float maxHeight = AndroidUtilities.displaySize.y * 0.4f; + float maxWidth; + if (AndroidUtilities.isTablet()) { + maxWidth = AndroidUtilities.getMinTabletSide() * 0.5f; + } else { + maxWidth = AndroidUtilities.displaySize.x * 0.5f; + } if (photoWidth == 0) { photoHeight = (int) maxHeight; photoWidth = photoHeight + AndroidUtilities.dp(100); @@ -539,28 +544,32 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD photoWidth *= maxHeight / photoHeight; photoHeight = (int)maxHeight; } + if (photoWidth > maxWidth) { + photoHeight *= maxWidth / photoWidth; + photoWidth = (int)maxWidth; + } backgroundWidth = photoWidth + AndroidUtilities.dp(12); currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 80); photoImage.setNeedsQualityThumb(false); photoImage.setShouldGenerateQualityThumb(false); photoImage.setParentMessageObject(null); - if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() > 0) { - File f = new File(currentMessageObject.messageOwner.attachPath); + if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() > 0) { + File f = new File(messageObject.messageOwner.attachPath); if (f.exists()) { - photoImage.setImage(null, currentMessageObject.messageOwner.attachPath, + photoImage.setImage(null, messageObject.messageOwner.attachPath, String.format(Locale.US, "%d_%d", photoWidth, photoHeight), null, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, "b1", - currentMessageObject.messageOwner.media.document.size, true); + messageObject.messageOwner.media.document.size, true); } - } else if (currentMessageObject.messageOwner.media.document.id != 0) { - photoImage.setImage(currentMessageObject.messageOwner.media.document, null, + } else if (messageObject.messageOwner.media.document.id != 0) { + photoImage.setImage(messageObject.messageOwner.media.document, null, String.format(Locale.US, "%d_%d", photoWidth, photoHeight), null, currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null, "b1", - currentMessageObject.messageOwner.media.document.size, true); + messageObject.messageOwner.media.document.size, true); } } else { if (AndroidUtilities.isTablet()) { @@ -598,7 +607,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD if (currentPhotoObject != null) { boolean noSize = false; - if (currentMessageObject.type == 3 || currentMessageObject.type == 8) { + if (messageObject.type == 3 || messageObject.type == 8) { noSize = true; } float scale = (float) currentPhotoObject.w / (float) photoWidth; @@ -631,12 +640,12 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD w = (int) (currentPhotoObject.w / hScale); } } - int timeWidthTotal = timeWidth + AndroidUtilities.dp(14 + (currentMessageObject.isOut() ? 20 : 0)); + int timeWidthTotal = timeWidth + AndroidUtilities.dp(14 + (messageObject.isOut() ? 20 : 0)); if (w < timeWidthTotal) { w = timeWidthTotal; } - if (currentMessageObject.isSecretPhoto()) { + if (messageObject.isSecretPhoto()) { if (AndroidUtilities.isTablet()) { w = h = (int) (AndroidUtilities.getMinTabletSide() * 0.5f); } else { @@ -660,7 +669,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD String fileName = FileLoader.getAttachFileName(currentPhotoObject); if (messageObject.type == 1) { boolean photoExist = true; - File cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + File cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); if (!cacheFile.exists()) { photoExist = false; } else { @@ -691,6 +700,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD photoImage.setImageBitmap((Bitmap)null); } } + super.setMessageObject(messageObject); invalidate(); } @@ -733,7 +743,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD buttonState = 1; radialProgress.setBackground(getDrawableForCurrentState(), true, animated); Float progress = ImageLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath); - if (progress == null && SendMessagesHelper.getInstance().isSendingMessage(currentMessageObject.messageOwner.id)) { + if (progress == null && SendMessagesHelper.getInstance().isSendingMessage(currentMessageObject.getId())) { progress = 1.0f; } radialProgress.setProgress(progress != null ? progress : 0, false); @@ -783,7 +793,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), photoHeight + AndroidUtilities.dp(14)); + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), photoHeight + AndroidUtilities.dp(14) + namesOffset); } @Override @@ -804,10 +814,10 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD x = AndroidUtilities.dp(15); } } - photoImage.setImageCoords(x, AndroidUtilities.dp(7), photoWidth, photoHeight); + photoImage.setImageCoords(x, AndroidUtilities.dp(7) + namesOffset, photoWidth, photoHeight); int size = AndroidUtilities.dp(48); buttonX = (int)(x + (photoWidth - size) / 2.0f); - buttonY = (int)(AndroidUtilities.dp(7) + (photoHeight - size) / 2.0f); + buttonY = (int)(AndroidUtilities.dp(7) + (photoHeight - size) / 2.0f) + namesOffset; 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)); @@ -854,7 +864,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD gifDrawable.draw(canvas); canvas.restore(); } else { - photoImage.setPressed(isPressed() && isCheckPressed || !isCheckPressed && isPressed); + photoImage.setPressed(isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted); photoImage.setVisible(!PhotoViewer.getInstance().isShowingImage(currentMessageObject), false); imageDrawn = photoImage.draw(canvas); drawTime = photoImage.getVisible(); @@ -874,7 +884,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD menuDrawable = docMenuInDrawable; } - setDrawableBounds(menuDrawable, photoImage.getImageX() + backgroundWidth - AndroidUtilities.dp(44), AndroidUtilities.dp(10)); + setDrawableBounds(menuDrawable, photoImage.getImageX() + backgroundWidth - AndroidUtilities.dp(44), AndroidUtilities.dp(10) + namesOffset); menuDrawable.draw(canvas); if (buttonState >= 0 && buttonState < 4) { @@ -973,7 +983,7 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD @Override public void onSuccessDownload(String fileName) { radialProgress.setProgress(1, true); - if (currentMessageObject.type == 8 && lastDownloadedGifMessage != null && lastDownloadedGifMessage.messageOwner.id == currentMessageObject.messageOwner.id) { + if (currentMessageObject.type == 8 && lastDownloadedGifMessage != null && lastDownloadedGifMessage.getId() == currentMessageObject.getId()) { buttonState = 2; didPressedButton(true); } else if (!photoNotSet) { 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 ef2814c84..f1f324e61 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -17,6 +17,7 @@ import android.view.MotionEvent; import org.telegram.android.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.android.MessageObject; +import org.telegram.ui.Components.URLSpanNoUnderline; public class ChatMessageCell extends ChatBaseCell { @@ -62,7 +63,16 @@ public class ChatMessageCell extends ChatBaseCell { } else { if (link[0] == pressedLink) { try { - pressedLink.onClick(this); + if (pressedLink instanceof URLSpanNoUnderline) { + String url = ((URLSpanNoUnderline) pressedLink).getURL(); + if (url.startsWith("@") || url.startsWith("#")) { + if (delegate != null) { + delegate.didPressUrl(url); + } + } + } else { + pressedLink.onClick(this); + } } catch (Exception e) { FileLog.e("tmessages", e); } @@ -164,6 +174,8 @@ public class ChatMessageCell extends ChatBaseCell { int maxChildWidth = Math.max(backgroundWidth, nameWidth); maxChildWidth = Math.max(maxChildWidth, forwardedNameWidth); + maxChildWidth = Math.max(maxChildWidth, replyNameWidth); + maxChildWidth = Math.max(maxChildWidth, replyTextWidth); int timeMore = timeWidth + AndroidUtilities.dp(6); if (messageObject.isOut()) { 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 9858f39cf..b18bacc25 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -612,7 +612,7 @@ public class DialogCell extends BaseCell { } } if (dialog != null) { - if (currentDialogId != dialog.id || message != null && message.messageOwner.id != dialog.top_message || unreadCount != dialog.unread_count) { + if (currentDialogId != dialog.id || message != null && message.getId() != dialog.top_message || unreadCount != dialog.unread_count) { currentDialogId = dialog.id; update(0); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java new file mode 100644 index 000000000..64d5d7bbe --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java @@ -0,0 +1,99 @@ +/* + * This is the source code of Telegram for Android v. 2.x + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Cells; + +import android.content.Context; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.ContactsController; +import org.telegram.messenger.TLRPC; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.BackupImageView; + +public class MentionCell extends LinearLayout { + + private BackupImageView imageView; + private TextView nameTextView; + private TextView usernameTextView; + private AvatarDrawable avatarDrawable; + + public MentionCell(Context context) { + super(context); + + setOrientation(HORIZONTAL); + + avatarDrawable = new AvatarDrawable(); + avatarDrawable.setSmallStyle(true); + + imageView = new BackupImageView(context); + imageView.imageReceiver.setRoundRadius(AndroidUtilities.dp(14)); + addView(imageView); + LayoutParams layoutParams = (LayoutParams) imageView.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(12); + layoutParams.topMargin = AndroidUtilities.dp(4); + layoutParams.width = AndroidUtilities.dp(28); + layoutParams.height = AndroidUtilities.dp(28); + imageView.setLayoutParams(layoutParams); + + nameTextView = new TextView(context); + nameTextView.setTextColor(0xff000000); + nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + nameTextView.setSingleLine(true); + nameTextView.setGravity(Gravity.LEFT); + nameTextView.setEllipsize(TextUtils.TruncateAt.END); + addView(nameTextView); + layoutParams = (LayoutParams) nameTextView.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(12); + layoutParams.width = LayoutParams.WRAP_CONTENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.gravity = Gravity.CENTER_VERTICAL; + nameTextView.setLayoutParams(layoutParams); + + usernameTextView = new TextView(context); + usernameTextView.setTextColor(0xff999999); + usernameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + usernameTextView.setSingleLine(true); + usernameTextView.setGravity(Gravity.LEFT); + usernameTextView.setEllipsize(TextUtils.TruncateAt.END); + addView(usernameTextView); + layoutParams = (LayoutParams) usernameTextView.getLayoutParams(); + layoutParams.leftMargin = AndroidUtilities.dp(12); + layoutParams.width = LayoutParams.WRAP_CONTENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.gravity = Gravity.CENTER_VERTICAL; + usernameTextView.setLayoutParams(layoutParams); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(36), MeasureSpec.EXACTLY)); + } + + public void setUser(TLRPC.User user) { + if (user == null) { + nameTextView.setText(""); + usernameTextView.setText(""); + imageView.setImageDrawable(null); + return; + } + avatarDrawable.setInfo(user); + if (user.photo != null && user.photo.photo_small != null) { + imageView.setImage(user.photo.photo_small, "50_50", avatarDrawable); + } else { + imageView.setImageDrawable(avatarDrawable); + } + nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); + usernameTextView.setText("@" + user.username); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java index faf3b1630..25d67fe46 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoEditToolCell.java @@ -83,4 +83,10 @@ public class PhotoEditToolCell extends FrameLayoutFixed { valueTextView.setText("" + (int) value); } } + + public void setIconAndTextAndValue(int resId, String text, String value) { + iconImage.setImageResource(resId); + nameTextView.setText(text.toUpperCase()); + valueTextView.setText(value); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java index 2fe47d9e0..b20ed7c78 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerAlbumsCell.java @@ -15,7 +15,6 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; @@ -27,8 +26,8 @@ import org.telegram.ui.Components.FrameLayoutFixed; public class PhotoPickerAlbumsCell extends FrameLayoutFixed { - public static interface PhotoPickerAlbumsCellDelegate { - public abstract void didSelectAlbum(MediaController.AlbumEntry albumEntry); + public interface PhotoPickerAlbumsCellDelegate { + void didSelectAlbum(MediaController.AlbumEntry albumEntry); } private AlbumView[] albumViews; @@ -180,11 +179,6 @@ public class PhotoPickerAlbumsCell extends FrameLayoutFixed { albumViews[a].setLayoutParams(layoutParams); } - ViewGroup.LayoutParams layoutParams = getLayoutParams(); - if (layoutParams != null) { - layoutParams.height = AndroidUtilities.dp(4) + itemWidth; - setLayoutParams(layoutParams); - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(4) + itemWidth, MeasureSpec.EXACTLY)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java index 30c1fe4c6..e24419ed1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoPickerSearchCell.java @@ -26,8 +26,8 @@ import org.telegram.messenger.R; public class PhotoPickerSearchCell extends LinearLayout { - public static interface PhotoPickerSearchCellDelegate { - public abstract void didPressedSearchButton(int index); + public interface PhotoPickerSearchCellDelegate { + void didPressedSearchButton(int index); } private class SearchButton extends FrameLayout { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java index 90f3d4f54..32719d2a3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell.java @@ -14,7 +14,6 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -39,9 +38,9 @@ public class SharedPhotoVideoCell extends FrameLayoutFixed { private int itemsCount; private boolean isFirst; - public static interface SharedPhotoVideoCellDelegate { - public abstract void didClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a); - public abstract boolean didLongClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a); + public interface SharedPhotoVideoCellDelegate { + void didClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a); + boolean didLongClickItem(SharedPhotoVideoCell cell, int index, MessageObject messageObject, int a); } private class PhotoVideoView extends FrameLayoutFixed { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index de91e2207..a57f8dd39 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -10,6 +10,7 @@ package org.telegram.ui; import android.app.Activity; import android.app.AlertDialog; +import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; @@ -19,6 +20,7 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.media.ExifInterface; import android.net.Uri; import android.os.Build; @@ -27,6 +29,7 @@ import android.provider.MediaStore; import android.support.v7.widget.LinearLayoutManager; import android.text.Html; import android.text.TextUtils; +import android.util.Base64; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; @@ -42,6 +45,7 @@ import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; @@ -49,14 +53,20 @@ import android.widget.Toast; import org.telegram.android.AndroidUtilities; import org.telegram.PhoneFormat.PhoneFormat; +import org.telegram.android.Emoji; 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.android.query.ReplyMessageQuery; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.RPCRequest; +import org.telegram.messenger.SerializedData; +import org.telegram.messenger.TLClassStore; +import org.telegram.messenger.TLObject; import org.telegram.messenger.TLRPC; import org.telegram.android.ContactsController; import org.telegram.messenger.FileLog; @@ -68,6 +78,7 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.ui.Adapters.BaseFragmentAdapter; +import org.telegram.ui.Adapters.MentionsAdapter; import org.telegram.ui.Adapters.StickersAdapter; import org.telegram.ui.AnimationCompat.AnimatorListenerAdapterProxy; import org.telegram.ui.AnimationCompat.AnimatorSetProxy; @@ -138,12 +149,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private FrameLayout stickersPanel; private TextView muteItem; private ImageView pagedownButton; + private BackupImageView replyImageView; + private TextView replyNameTextView; + private TextView replyObjectTextView; + private ImageView replyIconImageView; + private MentionsAdapter mentionsAdapter; + private ListView mentionListView; + private AnimatorSetProxy mentionListAnimation; private boolean allowStickersPanel; private AnimatorSetProxy runningAnimation; private MessageObject selectedObject; + private ArrayList forwardingMessages; private MessageObject forwaringMessage; + private MessageObject replyingMessageObject; private boolean paused = true; private boolean readWhenResume = false; @@ -153,7 +173,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int readWithMid = 0; private boolean scrollToTopOnResume = false; private boolean scrollToTopUnReadOnResume = false; - private boolean isCustomTheme = false; private long dialog_id; private boolean isBroadcast = false; private HashMap selectedMessagesIds = new HashMap<>(); @@ -217,6 +236,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int delete_chat = 12; private final static int share_contact = 13; private final static int mute = 14; + private final static int reply = 15; private final static int id_chat_compose_panel = 1000; @@ -392,6 +412,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.getInstance().addObserver(this, NotificationCenter.updateMessageMedia); NotificationCenter.getInstance().addObserver(this, NotificationCenter.replaceMessagesObjects); NotificationCenter.getInstance().addObserver(this, NotificationCenter.notificationsSettingsUpdated); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.didLoadedReplyMessages); super.onFragmentCreate(); @@ -427,6 +448,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { chatActivityEnterView.onDestroy(); } + if (avatarImageView != null) { + avatarImageView.setImageDrawable(null); + } + if (replyImageView != null) { + replyImageView.setImageDrawable(null); + } NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messagesDidLoaded); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.emojiDidLoaded); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces); @@ -452,6 +479,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateMessageMedia); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.replaceMessagesObjects); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.notificationsSettingsUpdated); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didLoadedReplyMessages); if (AndroidUtilities.isTablet()) { NotificationCenter.getInstance().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, true); } @@ -531,13 +559,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(false); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override - public void didSelectPhotos(ArrayList photos) { - SendMessagesHelper.prepareSendingPhotos(photos, null, dialog_id); - } - - @Override - public void didSelectWebPhotos(ArrayList photos) { - SendMessagesHelper.prepareSendingPhotosSearch(photos, dialog_id); + public void didSelectPhotos(ArrayList photos, ArrayList webPhotos) { + SendMessagesHelper.prepareSendingPhotos(photos, null, dialog_id, replyingMessageObject); + SendMessagesHelper.prepareSendingPhotosSearch(webPhotos, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } @Override @@ -582,10 +607,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fragment.setDelegate(new LocationActivity.LocationActivityDelegate() { @Override public void didSelectLocation(double latitude, double longitude) { - SendMessagesHelper.getInstance().sendMessage(latitude, longitude, dialog_id); - if (chatListView != null) { - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); - } + SendMessagesHelper.getInstance().sendMessage(latitude, longitude, dialog_id, replyingMessageObject); + moveScrollToLastMessage(); + showReplyForMessageObjectOrForward(false, null, null, true); if (paused) { scrollToTopOnResume = true; } @@ -598,7 +622,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void didSelectFiles(DocumentSelectActivity activity, ArrayList files) { activity.finishFragment(); - SendMessagesHelper.prepareSendingDocuments(files, files, null, null, dialog_id); + SendMessagesHelper.prepareSendingDocuments(files, files, null, null, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } @Override @@ -677,8 +702,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putBoolean("serverOnly", true); - args.putString("selectAlertString", LocaleController.getString("ForwardMessagesTo", R.string.ForwardMessagesTo)); - args.putString("selectAlertStringGroup", LocaleController.getString("ForwardMessagesToGroup", R.string.ForwardMessagesToGroup)); MessagesActivity fragment = new MessagesActivity(args); fragment.setDelegate(ChatActivity.this); presentFragment(fragment); @@ -733,13 +756,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - SendMessagesHelper.getInstance().sendMessage(UserConfig.getCurrentUser(), dialog_id); - chatListView.post(new Runnable() { - @Override - public void run() { - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); - } - }); + SendMessagesHelper.getInstance().sendMessage(UserConfig.getCurrentUser(), dialog_id, replyingMessageObject); + moveScrollToLastMessage(); + showReplyForMessageObjectOrForward(false, null, null, true); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -806,6 +825,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } NotificationsController.updateServerNotificationsSettings(dialog_id); } + } else if (id == reply) { + if (selectedMessagesIds.size() == 1) { + ArrayList ids = new ArrayList<>(selectedMessagesIds.keySet()); + MessageObject messageObject = messagesDict.get(ids.get(0)); + if (messageObject != null && messageObject.messageOwner.id > 0) { + showReplyForMessageObjectOrForward(true, messageObject, null, true); + } + } + selectedMessagesIds.clear(); + selectedMessagesCanCopyIds.clear(); + actionBar.hideActionMode(); + updateVisibleRows(); } } }); @@ -996,6 +1027,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentEncryptedChat == null) { actionModeViews.add(actionMode.addItem(copy, R.drawable.ic_ab_fwd_copy, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); + if (!isBroadcast) { + actionModeViews.add(actionMode.addItem(reply, R.drawable.ic_ab_reply, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); + } actionModeViews.add(actionMode.addItem(forward, R.drawable.ic_ab_fwd_forward, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); actionModeViews.add(actionMode.addItem(delete, R.drawable.ic_ab_fwd_delete, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); } else { @@ -1003,13 +1037,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionModeViews.add(actionMode.addItem(delete, R.drawable.ic_ab_fwd_delete, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); } actionMode.getItem(copy).setVisibility(selectedMessagesCanCopyIds.size() != 0 ? View.VISIBLE : View.GONE); + if (actionMode.getItem(reply) != null) { + actionMode.getItem(reply).setVisibility(selectedMessagesIds.size() == 1 ? View.VISIBLE : View.GONE); + } checkActionBarMenu(); fragmentView = new SizeNotifierRelativeLayout(getParentActivity()); SizeNotifierRelativeLayout contentView = (SizeNotifierRelativeLayout) fragmentView; contentView.setBackgroundImage(ApplicationLoader.getCachedWallpaper()); - isCustomTheme = ApplicationLoader.isCustomTheme(); emptyViewContainer = new FrameLayout(getParentActivity()); emptyViewContainer.setPadding(0, 0, 0, AndroidUtilities.dp(48)); @@ -1033,11 +1069,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { emptyView.setText(LocaleController.getString("NoMessages", R.string.NoMessages)); } - emptyView.setPadding(AndroidUtilities.dp(7), AndroidUtilities.dp(1), AndroidUtilities.dp(7), AndroidUtilities.dp(1)); emptyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); emptyView.setGravity(Gravity.CENTER); emptyView.setTextColor(0xffffffff); - emptyView.setBackgroundResource(isCustomTheme ? R.drawable.system_black : R.drawable.system_blue); + emptyView.setBackgroundResource(ApplicationLoader.isCustomTheme() ? R.drawable.system_black : R.drawable.system_blue); + emptyView.setPadding(AndroidUtilities.dp(7), AndroidUtilities.dp(1), AndroidUtilities.dp(7), AndroidUtilities.dp(1)); emptyViewContainer.addView(emptyView); layoutParams2 = (FrameLayout.LayoutParams) emptyView.getLayoutParams(); layoutParams2.width = FrameLayout.LayoutParams.WRAP_CONTENT; @@ -1046,7 +1082,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not emptyView.setLayoutParams(layoutParams2); } else { LinearLayout secretChatPlaceholder = new LinearLayout(getParentActivity()); - secretChatPlaceholder.setBackgroundResource(isCustomTheme ? R.drawable.system_black : R.drawable.system_blue); + secretChatPlaceholder.setBackgroundResource(ApplicationLoader.isCustomTheme() ? R.drawable.system_black : R.drawable.system_blue); secretChatPlaceholder.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(12), AndroidUtilities.dp(16), AndroidUtilities.dp(12)); secretChatPlaceholder.setOrientation(LinearLayout.VERTICAL); emptyViewContainer.addView(secretChatPlaceholder); @@ -1324,7 +1360,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not progressView = new FrameLayout(getParentActivity()); progressView.setVisibility(View.INVISIBLE); - progressView.setBackgroundResource(isCustomTheme ? R.drawable.system_loader2 : R.drawable.system_loader1); + progressView.setBackgroundResource(ApplicationLoader.isCustomTheme() ? R.drawable.system_loader2 : R.drawable.system_loader1); contentView.addView(progressView); layoutParams3 = (RelativeLayout.LayoutParams) progressView.getLayoutParams(); layoutParams3.width = AndroidUtilities.dp(36); @@ -1348,6 +1384,113 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not layoutParams2.gravity = Gravity.CENTER; progressBar.setLayoutParams(layoutParams2); + if (currentChat != null && !isBroadcast) { + mentionListView = new ListView(getParentActivity()); + mentionListView.setBackgroundResource(R.drawable.compose_panel); + mentionListView.setVisibility(View.GONE); + mentionListView.setPadding(0, AndroidUtilities.dp(2), 0, 0); + mentionListView.setClipToPadding(true); + mentionListView.setDividerHeight(0); + mentionListView.setDivider(null); + if (Build.VERSION.SDK_INT > 8) { + mentionListView.setOverScrollMode(ListView.OVER_SCROLL_NEVER); + } + contentView.addView(mentionListView); + layoutParams3 = (RelativeLayout.LayoutParams) mentionListView.getLayoutParams(); + layoutParams3.width = RelativeLayout.LayoutParams.MATCH_PARENT; + layoutParams3.height = AndroidUtilities.dp(110); + layoutParams3.topMargin = -AndroidUtilities.dp(108); + layoutParams3.addRule(RelativeLayout.ALIGN_TOP, id_chat_compose_panel); + mentionListView.setLayoutParams(layoutParams3); + + mentionListView.setAdapter(mentionsAdapter = new MentionsAdapter(getParentActivity(), new MentionsAdapter.MentionsAdapterDelegate() { + @Override + public void needChangePanelVisibility(boolean show) { + if (show) { + RelativeLayout.LayoutParams layoutParams3 = (RelativeLayout.LayoutParams) mentionListView.getLayoutParams(); + layoutParams3.height = AndroidUtilities.dp(2 + 36 * Math.min(3, mentionsAdapter.getCount())); + layoutParams3.topMargin = -AndroidUtilities.dp(36 * Math.min(3, mentionsAdapter.getCount())); + mentionListView.setLayoutParams(layoutParams3); + + if (mentionListAnimation != null) { + mentionListAnimation.cancel(); + mentionListAnimation = null; + } + + if (mentionListView.getVisibility() == View.VISIBLE) { + ViewProxy.setAlpha(mentionListView, 1.0f); + return; + } + if (allowStickersPanel) { + mentionListView.setVisibility(View.VISIBLE); + mentionListAnimation = new AnimatorSetProxy(); + mentionListAnimation.playTogether( + ObjectAnimatorProxy.ofFloat(mentionListView, "alpha", 0.0f, 1.0f) + ); + mentionListAnimation.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { + mentionListView.clearAnimation(); + mentionListAnimation = null; + } + } + }); + mentionListAnimation.setDuration(200); + mentionListAnimation.start(); + } else { + ViewProxy.setAlpha(mentionListView, 1.0f); + mentionListView.clearAnimation(); + mentionListView.setVisibility(View.INVISIBLE); + } + } else { + if (mentionListAnimation != null) { + mentionListAnimation.cancel(); + mentionListAnimation = null; + } + + if (mentionListView.getVisibility() == View.GONE) { + return; + } + if (allowStickersPanel) { + mentionListAnimation = new AnimatorSetProxy(); + mentionListAnimation.playTogether( + ObjectAnimatorProxy.ofFloat(mentionListView, "alpha", 0.0f) + ); + mentionListAnimation.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { + mentionListView.clearAnimation(); + mentionListView.setVisibility(View.GONE); + mentionListAnimation = null; + } + } + }); + mentionListAnimation.setDuration(200); + mentionListAnimation.start(); + } else { + mentionListView.clearAnimation(); + mentionListView.setVisibility(View.GONE); + } + } + } + })); + mentionsAdapter.setChatInfo(info); + + mentionListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + TLRPC.User user = mentionsAdapter.getItem(position); + if (user != null) { + int start = mentionsAdapter.getUsernameStartPosition(); + int len = mentionsAdapter.getUsernameLength(); + chatActivityEnterView.replaceWithText(start, len, "@" + user.username + " "); + } + } + }); + } + if (chatActivityEnterView != null) { chatActivityEnterView.onDestroy(); } @@ -1364,12 +1507,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { @Override public void onMessageSend() { - chatListView.post(new Runnable() { - @Override - public void run() { - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); - } - }); + moveScrollToLastMessage(); + showReplyForMessageObjectOrForward(false, null, null, true); } @Override @@ -1377,6 +1516,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (stickersAdapter != null) { stickersAdapter.loadStikersForEmoji(text); } + if (mentionsAdapter != null) { + mentionsAdapter.searchUsername(text.toString(), chatActivityEnterView.getCursorPosition(), messages); + } } @Override @@ -1412,16 +1554,110 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not stickersPanel.clearAnimation(); stickersPanel.setVisibility(View.INVISIBLE); } + if (mentionListView != null && mentionListView.getVisibility() == View.VISIBLE) { + mentionListView.clearAnimation(); + mentionListView.setVisibility(View.INVISIBLE); + } } else { allowStickersPanel = true; if (stickersPanel.getVisibility() == View.INVISIBLE) { stickersPanel.clearAnimation(); stickersPanel.setVisibility(View.VISIBLE); } + if (mentionListView != null && mentionListView.getVisibility() == View.INVISIBLE) { + mentionListView.clearAnimation(); + mentionListView.setVisibility(View.VISIBLE); + } } } }); + FrameLayout replyLayout = new FrameLayout(getParentActivity()); + replyLayout.setClickable(true); + chatActivityEnterView.addTopView(replyLayout, AndroidUtilities.dp(48)); + + View lineView = new View(getParentActivity()); + lineView.setBackgroundColor(0xffe8e8e8); + replyLayout.addView(lineView); + layoutParams2 = (FrameLayout.LayoutParams) lineView.getLayoutParams(); + layoutParams2.gravity = Gravity.BOTTOM; + layoutParams2.width = FrameLayout.LayoutParams.MATCH_PARENT; + layoutParams2.height = AndroidUtilities.dp(1); + lineView.setLayoutParams(layoutParams2); + + replyIconImageView = new ImageView(getParentActivity()); + replyIconImageView.setScaleType(ImageView.ScaleType.CENTER); + replyLayout.addView(replyIconImageView); + layoutParams2 = (FrameLayout.LayoutParams) replyIconImageView.getLayoutParams(); + layoutParams2.gravity = Gravity.TOP | Gravity.LEFT; + layoutParams2.width = AndroidUtilities.dp(52); + layoutParams2.height = AndroidUtilities.dp(46); + replyIconImageView.setLayoutParams(layoutParams2); + + ImageView imageView = new ImageView(getParentActivity()); + imageView.setImageResource(R.drawable.delete_reply); + imageView.setScaleType(ImageView.ScaleType.CENTER); + replyLayout.addView(imageView); + layoutParams2 = (FrameLayout.LayoutParams) imageView.getLayoutParams(); + layoutParams2.topMargin = AndroidUtilities.dp(0.5f); + layoutParams2.width = AndroidUtilities.dp(52); + layoutParams2.height = AndroidUtilities.dp(46); + layoutParams2.gravity = Gravity.RIGHT | Gravity.TOP; + imageView.setLayoutParams(layoutParams2); + imageView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (forwardingMessages != null) { + forwardingMessages.clear(); + } + showReplyForMessageObjectOrForward(false, null, null, true); + } + }); + + replyNameTextView = new TextView(getParentActivity()); + replyNameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + replyNameTextView.setTextColor(0xff377aae); + replyNameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + replyNameTextView.setSingleLine(true); + replyNameTextView.setEllipsize(TextUtils.TruncateAt.END); + replyNameTextView.setMaxLines(1); + replyLayout.addView(replyNameTextView); + layoutParams2 = (FrameLayout.LayoutParams) replyNameTextView.getLayoutParams(); + layoutParams2.leftMargin = AndroidUtilities.dp(52); + layoutParams2.rightMargin = AndroidUtilities.dp(52); + layoutParams2.topMargin = AndroidUtilities.dp(4); + layoutParams2.width = FrameLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.height = FrameLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.gravity = Gravity.TOP | Gravity.LEFT; + replyNameTextView.setLayoutParams(layoutParams2); + + replyObjectTextView = new TextView(getParentActivity()); + replyObjectTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + replyObjectTextView.setTextColor(0xff999999); + replyObjectTextView.setSingleLine(true); + replyObjectTextView.setEllipsize(TextUtils.TruncateAt.END); + replyObjectTextView.setMaxLines(1); + replyLayout.addView(replyObjectTextView); + layoutParams2 = (FrameLayout.LayoutParams) replyObjectTextView.getLayoutParams(); + layoutParams2.leftMargin = AndroidUtilities.dp(52); + layoutParams2.rightMargin = AndroidUtilities.dp(52); + layoutParams2.topMargin = AndroidUtilities.dp(22); + layoutParams2.width = FrameLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.height = FrameLayout.LayoutParams.WRAP_CONTENT; + layoutParams2.gravity = Gravity.TOP | Gravity.LEFT; + replyObjectTextView.setLayoutParams(layoutParams2); + + replyImageView = new BackupImageView(getParentActivity()); + replyImageView.processDetach = false; + replyLayout.addView(replyImageView); + layoutParams2 = (FrameLayout.LayoutParams) replyImageView.getLayoutParams(); + layoutParams2.leftMargin = AndroidUtilities.dp(52); + layoutParams2.topMargin = AndroidUtilities.dp(6); + layoutParams2.width = AndroidUtilities.dp(34); + layoutParams2.height = AndroidUtilities.dp(34); + layoutParams2.gravity = Gravity.TOP | Gravity.LEFT; + replyImageView.setLayoutParams(layoutParams2); + stickersPanel = new FrameLayout(getParentActivity()); stickersPanel.setVisibility(View.GONE); contentView.addView(stickersPanel); @@ -1525,14 +1761,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - SendMessagesHelper.getInstance().sendMessage((TLRPC.TL_document) document, null, null, dialog_id); + SendMessagesHelper.getInstance().sendMessage((TLRPC.TL_document) document, null, null, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } chatActivityEnterView.setFieldText(""); } })); } - ImageView imageView = new ImageView(getParentActivity()); + imageView = new ImageView(getParentActivity()); imageView.setImageResource(R.drawable.stickers_back_arrow); stickersPanel.addView(imageView); layoutParams2 = (FrameLayout.LayoutParams) imageView.getLayoutParams(); @@ -1654,6 +1891,179 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return fragmentView; } + private void forwardMessages(ArrayList arrayList, boolean fromMyName) { + if (arrayList == null || arrayList.isEmpty()) { + return; + } + for (MessageObject object : arrayList) { + if (!fromMyName) { + SendMessagesHelper.getInstance().sendMessage(object, dialog_id); + } else { + SendMessagesHelper.getInstance().processForwardFromMyName(object, dialog_id); + } + } + } + + public void showReplyForMessageObjectOrForward(boolean show, MessageObject messageObject, ArrayList messageObjects, boolean animated) { + if (show) { + if (messageObject == null && messageObjects == null) { + return; + } + if (messageObject != null) { + TLRPC.User user = MessagesController.getInstance().getUser(messageObject.messageOwner.from_id); + if (user == null) { + return; + } + forwardingMessages = null; + replyIconImageView.setImageResource(R.drawable.reply); + replyingMessageObject = messageObject; + chatActivityEnterView.setReplyingMessageObject(messageObject); + replyNameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); + if (messageObject.messageText != null) { + String mess = messageObject.messageText.toString(); + if (mess.length() > 150) { + mess = mess.substring(0, 150); + } + mess = mess.replace("\n", " "); + replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14))); + } + } else if (messageObjects != null) { + if (messageObjects.isEmpty()) { + return; + } + chatActivityEnterView.setForceShowSendButton(true, animated); + chatActivityEnterView.setReplyingMessageObject(null); + replyingMessageObject = null; + ArrayList uids = new ArrayList<>(); + replyIconImageView.setImageResource(R.drawable.forward_blue); + forwardingMessages = messageObjects; + uids.add(messageObjects.get(0).messageOwner.from_id); + int type = messageObjects.get(0).type; + for (int a = 1; a < messageObjects.size(); a++) { + Integer uid = messageObjects.get(a).messageOwner.from_id; + if (!uids.contains(uid)) { + uids.add(uid); + } + if (messageObjects.get(a).type != type) { + type = -1; + } + } + StringBuilder userNames = new StringBuilder(); + for (int a = 0; a < uids.size(); a++) { + Integer uid = uids.get(a); + TLRPC.User user = MessagesController.getInstance().getUser(uid); + if (user == null) { + continue; + } + if (uids.size() == 1) { + userNames.append(ContactsController.formatName(user.first_name, user.last_name)); + } else if (uids.size() == 2 || userNames.length() == 0) { + if (userNames.length() > 0) { + userNames.append(", "); + } + if (user.first_name != null && user.first_name.length() > 0) { + userNames.append(user.first_name); + } else if (user.last_name != null && user.last_name.length() > 0) { + userNames.append(user.last_name); + } else { + userNames.append(" "); + } + } else { + userNames.append(" "); + userNames.append(LocaleController.formatPluralString("AndOther", uids.size() - 1)); + break; + } + } + replyNameTextView.setText(userNames); + if (type == -1 || type == 0) { + if (messageObjects.size() == 1 && messageObjects.get(0).messageText != null) { + String mess = messageObjects.get(0).messageText.toString(); + if (mess.length() > 150) { + mess = mess.substring(0, 150); + } + mess = mess.replace("\n", " "); + replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14))); + } else { + replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedMessage", messageObjects.size())); + } + } else { + if (type == 1) { + replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedPhoto", messageObjects.size())); + if (messageObjects.size() == 1) { + messageObject = messageObjects.get(0); + } + } else if (type == 4) { + replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedLocation", messageObjects.size())); + } else if (type == 3) { + replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedVideo", messageObjects.size())); + if (messageObjects.size() == 1) { + messageObject = messageObjects.get(0); + } + } else if (type == 12) { + replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedContact", messageObjects.size())); + } else if (type == 2) { + replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedAudio", messageObjects.size())); + } else if (type == 13) { + replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedSticker", messageObjects.size())); + } else if (type == 8 || type == 9) { + if (messageObjects.size() == 1) { + String name = null; + if ((name = FileLoader.getDocumentFileName(messageObjects.get(0).messageOwner.media.document)).length() != 0) { + replyObjectTextView.setText(name); + } + messageObject = messageObjects.get(0); + } else { + replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedFile", messageObjects.size())); + } + } + } + } + FrameLayout.LayoutParams layoutParams1 = (FrameLayout.LayoutParams) replyNameTextView.getLayoutParams(); + FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) replyObjectTextView.getLayoutParams(); + TLRPC.PhotoSize photoSize = messageObject != null ? FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, 80) : null; + if (photoSize == null || messageObject.type == 13) { + replyImageView.setImageBitmap(null); + replyImageView.setVisibility(View.INVISIBLE); + layoutParams1.leftMargin = layoutParams2.leftMargin = AndroidUtilities.dp(52); + } else { + replyImageView.setImage(photoSize.location, "50_50", (Drawable) null); + replyImageView.setVisibility(View.VISIBLE); + layoutParams1.leftMargin = layoutParams2.leftMargin = AndroidUtilities.dp(96); + } + replyNameTextView.setLayoutParams(layoutParams1); + replyObjectTextView.setLayoutParams(layoutParams2); + chatActivityEnterView.showTopView(animated); + } else { + if (replyingMessageObject == null && forwardingMessages == null) { + return; + } + if (forwardingMessages != null) { + forwardMessages(forwardingMessages, false); + } + chatActivityEnterView.setForceShowSendButton(false, animated); + chatActivityEnterView.hideTopView(animated); + chatActivityEnterView.setReplyingMessageObject(null); + replyingMessageObject = null; + forwardingMessages = null; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + preferences.edit().remove("reply_" + dialog_id).commit(); + } + } + + private void moveScrollToLastMessage() { + if (chatListView != null) { + chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); + chatListView.setForceTop(-100000 - chatListView.getPaddingTop()); + chatListView.post(new Runnable() { + @Override + public void run() { + chatListView.setForceTop(-100000 - chatListView.getPaddingTop()); + chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); + } + }); + } + } + private boolean sendSecretMessageRead(MessageObject messageObject) { if (messageObject == null || messageObject.isOut() || !messageObject.isSecretMedia() || messageObject.messageOwner.destroyTime != 0 || messageObject.messageOwner.ttl <= 0) { return false; @@ -1808,8 +2218,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return -1; } if (currentEncryptedChat == null) { - boolean isBroadcastError = isBroadcast && messageObject.messageOwner.id <= 0 && messageObject.isSendError(); - if (!isBroadcast && messageObject.messageOwner.id <= 0 && messageObject.isOut() || isBroadcastError) { + boolean isBroadcastError = isBroadcast && messageObject.getId() <= 0 && messageObject.isSendError(); + if (!isBroadcast && messageObject.getId() <= 0 && messageObject.isOut() || isBroadcastError) { if (messageObject.isSendError()) { if (!(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaEmpty)) { return 0; @@ -1823,7 +2233,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject.type == 6) { return -1; } else if (messageObject.type == 10 || messageObject.type == 11) { - if (messageObject.messageOwner.id == 0) { + if (messageObject.getId() == 0) { return -1; } return 1; @@ -1922,15 +2332,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void addToSelectedMessages(MessageObject messageObject) { - if (selectedMessagesIds.containsKey(messageObject.messageOwner.id)) { - selectedMessagesIds.remove(messageObject.messageOwner.id); + if (selectedMessagesIds.containsKey(messageObject.getId())) { + selectedMessagesIds.remove(messageObject.getId()); if (messageObject.type == 0) { - selectedMessagesCanCopyIds.remove(messageObject.messageOwner.id); + selectedMessagesCanCopyIds.remove(messageObject.getId()); } } else { - selectedMessagesIds.put(messageObject.messageOwner.id, messageObject); + selectedMessagesIds.put(messageObject.getId(), messageObject); if (messageObject.type == 0) { - selectedMessagesCanCopyIds.put(messageObject.messageOwner.id, messageObject); + selectedMessagesCanCopyIds.put(messageObject.getId(), messageObject); } } if (actionBar.isActionModeShowed()) { @@ -1938,6 +2348,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionBar.hideActionMode(); } actionBar.createActionMode().getItem(copy).setVisibility(selectedMessagesCanCopyIds.size() != 0 ? View.VISIBLE : View.GONE); + if (actionBar.createActionMode().getItem(reply) != null) { + actionBar.createActionMode().getItem(reply).setVisibility(selectedMessagesIds.size() == 1 ? View.VISIBLE : View.GONE); + } } } @@ -2124,12 +2537,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not videoEditedInfo.resultWidth = resultWidth; videoEditedInfo.resultHeight = resultHeight; videoEditedInfo.originalPath = videoPath; - SendMessagesHelper.prepareSendingVideo(videoPath, estimatedSize, estimatedDuration, resultWidth, resultHeight, videoEditedInfo, dialog_id); + SendMessagesHelper.prepareSendingVideo(videoPath, estimatedSize, estimatedDuration, resultWidth, resultHeight, videoEditedInfo, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } }); if (parentLayout == null || !fragment.onFragmentCreate()) { - SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id); + SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); return false; } parentLayout.presentFragment(fragment, removeLast, true, true); @@ -2175,9 +2590,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void sendButtonPressed(int index) { MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) arrayList.get(0); if (photoEntry.imagePath != null) { - SendMessagesHelper.prepareSendingPhoto(photoEntry.imagePath, null, dialog_id); + SendMessagesHelper.prepareSendingPhoto(photoEntry.imagePath, null, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } else if (photoEntry.path != null) { - SendMessagesHelper.prepareSendingPhoto(photoEntry.path, null, dialog_id); + SendMessagesHelper.prepareSendingPhoto(photoEntry.path, null, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } } }); @@ -2188,7 +2605,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showAttachmentError(); return; } - SendMessagesHelper.prepareSendingPhoto(null, data.getData(), dialog_id); + SendMessagesHelper.prepareSendingPhoto(null, data.getData(), dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } else if (requestCode == 2) { String videoPath = null; if (data != null) { @@ -2229,7 +2647,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not openVideoEditor(videoPath, false); } } else { - SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id); + SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } } else if (requestCode == 21) { if (data == null || data.getData() == null) { @@ -2246,7 +2665,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showAttachmentError(); return; } - SendMessagesHelper.prepareSendingDocument(tempPath, originalPath, null, null, dialog_id); + SendMessagesHelper.prepareSendingDocument(tempPath, originalPath, null, null, dialog_id, replyingMessageObject); + showReplyForMessageObjectOrForward(false, null, null, true); } } } @@ -2334,19 +2754,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (load_type == 1) { Collections.reverse(messArr); } + ReplyMessageQuery.loadReplyMessagesForMessages(messArr, dialog_id); for (int a = 0; a < messArr.size(); a++) { MessageObject obj = messArr.get(a); - if (messagesDict.containsKey(obj.messageOwner.id)) { + if (messagesDict.containsKey(obj.getId())) { continue; } - if (obj.messageOwner.id > 0) { - maxMessageId = Math.min(obj.messageOwner.id, maxMessageId); - minMessageId = Math.max(obj.messageOwner.id, minMessageId); + if (obj.getId() > 0) { + maxMessageId = Math.min(obj.getId(), maxMessageId); + minMessageId = Math.max(obj.getId(), minMessageId); } else if (currentEncryptedChat != null) { - maxMessageId = Math.max(obj.messageOwner.id, maxMessageId); - minMessageId = Math.min(obj.messageOwner.id, minMessageId); + maxMessageId = Math.max(obj.getId(), maxMessageId); + minMessageId = Math.min(obj.getId(), minMessageId); } if (obj.messageOwner.date != 0) { maxDate = Math.max(maxDate, obj.messageOwner.date); @@ -2362,7 +2783,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!obj.isOut() && obj.isUnread()) { wasUnread = true; } - messagesDict.put(obj.messageOwner.id, obj); + messagesDict.put(obj.getId(), obj); ArrayList dayArray = messagesByDays.get(obj.dateKey); if (dayArray == null) { @@ -2391,7 +2812,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messages.add(messages.size() - 1, obj); } - if (load_type == 2 && obj.messageOwner.id == first_unread_id) { + if (load_type == 2 && obj.getId() == first_unread_id) { TLRPC.Message dateMsg = new TLRPC.Message(); dateMsg.message = ""; dateMsg.id = 0; @@ -2407,18 +2828,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrollToMessage = unreadMessageObject; scrollToMessageMiddleScreen = false; newRowsCount++; - } else if (load_type == 3 && obj.messageOwner.id == startLoadFromMessageId) { - highlightMessageId = obj.messageOwner.id; + } else if (load_type == 3 && obj.getId() == startLoadFromMessageId) { + highlightMessageId = obj.getId(); scrollToMessage = obj; if (isCache) { startLoadFromMessageId = 0; } scrollToMessageMiddleScreen = true; - } else if (load_type == 1 && startLoadFromMessageId != 0 && first_message_id != 0 && obj.messageOwner.id >= first_message_id) { + } else if (load_type == 1 && startLoadFromMessageId != 0 && first_message_id != 0 && obj.getId() >= first_message_id) { startLoadFromMessageId = 0; } - if (obj.messageOwner.id == last_message_id) { + if (obj.getId() == last_message_id) { forward_end_reached = true; } } @@ -2458,7 +2879,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (first || scrollToTopOnResume) { chatAdapter.notifyDataSetChanged(); if (scrollToMessage != null) { - final int yOffset = scrollToMessageMiddleScreen ? Math.max(0, (AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - scrollToMessage.textHeight - AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2) : 0; + final int yOffset = scrollToMessageMiddleScreen ? Math.max(0, (chatListView.getHeight() - scrollToMessage.getApproximateHeight()) / 2) : 0; if (messages.get(messages.size() - 1) == scrollToMessage) { chatListView.setSelectionFromTop(0, AndroidUtilities.dp(-11) + yOffset); } else { @@ -2482,12 +2903,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.invalidate(); showPagedownButton(true, true); } else { - chatListView.post(new Runnable() { - @Override - public void run() { - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); - } - }); + moveScrollToLastMessage(); } } else { int firstVisPos = chatListView.getLastVisiblePosition(); @@ -2520,7 +2936,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (first && messages.size() > 0) { final boolean wasUnreadFinal = wasUnread; final int last_unread_date_final = last_unread_date; - final int lastid = messages.get(0).messageOwner.id; + final int lastid = messages.get(0).getId(); AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { @@ -2542,6 +2958,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatListView != null) { chatListView.invalidateViews(); } + if (replyObjectTextView != null) { + replyObjectTextView.invalidate(); + } } else if (id == NotificationCenter.updateInterfaces) { int updateMask = (Integer)args[0]; if ((updateMask & MessagesController.UPDATE_MASK_NAME) != 0 || (updateMask & MessagesController.UPDATE_MASK_CHAT_NAME) != 0) { @@ -2591,7 +3010,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 17 && currentEncryptedChat.ttl > 0 && currentEncryptedChat.ttl <= 60) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setPositiveButton(R.string.OK, null); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(LocaleController.formatString("CompatibilityChat", R.string.CompatibilityChat, currentUser.first_name, currentUser.first_name)); showAlertDialog(builder); } @@ -2616,16 +3035,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrollToLastMessage(); return; } - if (messagesDict.containsKey(obj.messageOwner.id)) { + if (messagesDict.containsKey(obj.getId())) { continue; } currentMaxDate = Math.max(currentMaxDate, obj.messageOwner.date); - if (obj.messageOwner.id > 0) { - currentMinMsgId = Math.max(obj.messageOwner.id, currentMinMsgId); - last_message_id = Math.max(last_message_id, obj.messageOwner.id); + if (obj.getId() > 0) { + currentMinMsgId = Math.max(obj.getId(), currentMinMsgId); + last_message_id = Math.max(last_message_id, obj.getId()); } else if (currentEncryptedChat != null) { - currentMinMsgId = Math.min(obj.messageOwner.id, currentMinMsgId); - last_message_id = Math.min(last_message_id, obj.messageOwner.id); + currentMinMsgId = Math.min(obj.getId(), currentMinMsgId); + last_message_id = Math.min(last_message_id, obj.getId()); } if (!obj.isOut() && obj.isUnread()) { @@ -2644,12 +3063,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not readWithMid = currentMinMsgId; } else { if (messages.size() > 0) { - MessagesController.getInstance().markDialogAsRead(dialog_id, messages.get(0).messageOwner.id, currentMinMsgId, 0, currentMaxDate, true, false); + MessagesController.getInstance().markDialogAsRead(dialog_id, messages.get(0).getId(), currentMinMsgId, 0, currentMaxDate, true, false); } } } updateVisibleRows(); } else { + ReplyMessageQuery.loadReplyMessagesForMessages(arr, dialog_id); boolean markAsRead = false; int oldCount = messages.size(); for (MessageObject obj : arr) { @@ -2658,7 +3078,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not TLRPC.TL_decryptedMessageActionSetMessageTTL action = (TLRPC.TL_decryptedMessageActionSetMessageTTL)obj.messageOwner.action.encryptedAction; timerDrawable.setTime(action.ttl_seconds); } - if (messagesDict.containsKey(obj.messageOwner.id)) { + if (messagesDict.containsKey(obj.getId())) { continue; } if (minDate == 0 || obj.messageOwner.date < minDate) { @@ -2674,15 +3094,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not unread_to_load++; } - if (obj.messageOwner.id > 0) { - maxMessageId = Math.min(obj.messageOwner.id, maxMessageId); - minMessageId = Math.max(obj.messageOwner.id, minMessageId); + if (obj.getId() > 0) { + maxMessageId = Math.min(obj.getId(), maxMessageId); + minMessageId = Math.max(obj.getId(), minMessageId); } else if (currentEncryptedChat != null) { - maxMessageId = Math.max(obj.messageOwner.id, maxMessageId); - minMessageId = Math.min(obj.messageOwner.id, minMessageId); + maxMessageId = Math.max(obj.getId(), maxMessageId); + minMessageId = Math.min(obj.getId(), minMessageId); } maxDate = Math.max(maxDate, obj.messageOwner.date); - messagesDict.put(obj.messageOwner.id, obj); + messagesDict.put(obj.getId(), obj); ArrayList dayArray = messagesByDays.get(obj.dateKey); if (dayArray == null) { dayArray = new ArrayList<>(); @@ -2727,12 +3147,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (paused) { scrollToTopOnResume = true; } else { - chatListView.post(new Runnable() { - @Override - public void run() { - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); - } - }); + moveScrollToLastMessage(); } } } else { @@ -2748,7 +3163,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not readWithDate = maxDate; readWithMid = minMessageId; } else { - MessagesController.getInstance().markDialogAsRead(dialog_id, messages.get(0).messageOwner.id, minMessageId, 0, maxDate, true, false); + MessagesController.getInstance().markDialogAsRead(dialog_id, messages.get(0).getId(), minMessageId, 0, maxDate, true, false); } } } @@ -2767,14 +3182,40 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not removeSelfFromStack(); } } else if (id == NotificationCenter.messagesRead) { - ArrayList markAsReadMessages = (ArrayList)args[0]; + HashMap inbox = (HashMap) args[0]; + HashMap outbox = (HashMap) args[1]; boolean updated = false; - for (Integer ids : markAsReadMessages) { - MessageObject obj = messagesDict.get(ids); - if (obj != null) { - obj.setIsRead(); - updated = true; + for (HashMap.Entry entry : inbox.entrySet()) { + if (entry.getKey() != dialog_id) { + continue; } + for (int a = 0; a < messages.size(); a++) { + MessageObject obj = messages.get(a); + if (!obj.isOut() && obj.getId() > 0 && obj.getId() <= entry.getValue()) { + if (!obj.isUnread()) { + break; + } + obj.setIsRead(); + updated = true; + } + } + break; + } + for (HashMap.Entry entry : outbox.entrySet()) { + if (entry.getKey() != dialog_id) { + continue; + } + for (int a = 0; a < messages.size(); a++) { + MessageObject obj = messages.get(a); + if (obj.isOut() && obj.getId() > 0 && obj.getId() <= entry.getValue()) { + if (!obj.isUnread()) { + break; + } + obj.setIsRead(); + updated = true; + } + } + break; } if (updated) { updateVisibleRows(); @@ -2856,6 +3297,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int chatId = (Integer)args[0]; if (currentChat != null && chatId == currentChat.id) { info = (TLRPC.ChatParticipants)args[1]; + if (mentionsAdapter != null) { + mentionsAdapter.setChatInfo(info); + } updateOnlineCount(); updateSubtitle(); if (isBroadcast) { @@ -2897,7 +3341,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not View view = chatListView.getChildAt(a); if (view instanceof ChatAudioCell) { ChatAudioCell cell = (ChatAudioCell)view; - if (cell.getMessageObject() != null && cell.getMessageObject().messageOwner.id == mid) { + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { cell.updateButtonState(); break; } @@ -2912,7 +3356,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not View view = chatListView.getChildAt(a); if (view instanceof ChatAudioCell) { ChatAudioCell cell = (ChatAudioCell)view; - if (cell.getMessageObject() != null && cell.getMessageObject().messageOwner.id == mid) { + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { cell.updateProgress(); break; } @@ -2955,7 +3399,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject messageObject = (MessageObject)args[0]; long finalSize = (Long)args[2]; if (finalSize != 0 && dialog_id == messageObject.getDialogId()) { - MessageObject currentObject = messagesDict.get(messageObject.messageOwner.id); + MessageObject currentObject = messagesDict.get(messageObject.getId()); if (currentObject != null) { currentObject.messageOwner.media.video.size = (int)finalSize; updateVisibleRows(); @@ -2983,7 +3427,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not sendSecretMessageRead(messageObject); } else if (id == NotificationCenter.updateMessageMedia) { MessageObject messageObject = (MessageObject)args[0]; - MessageObject existMessageObject = messagesDict.get(messageObject.messageOwner.id); + MessageObject existMessageObject = messagesDict.get(messageObject.getId()); if (existMessageObject != null) { existMessageObject.messageOwner.media = messageObject.messageOwner.media; existMessageObject.messageOwner.attachPath = messageObject.messageOwner.attachPath; @@ -2995,9 +3439,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean changed = false; ArrayList messageObjects = (ArrayList) args[1]; for (MessageObject messageObject : messageObjects) { - MessageObject old = messagesDict.get(messageObject.messageOwner.id); + MessageObject old = messagesDict.get(messageObject.getId()); if (old != null) { - messagesDict.put(old.messageOwner.id, messageObject); + messagesDict.put(old.getId(), messageObject); int idx = messages.indexOf(old); if (idx >= 0) { messages.set(idx, messageObject); @@ -3011,6 +3455,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.notificationsSettingsUpdated) { updateTitleIcons(); + } else if (id == NotificationCenter.didLoadedReplyMessages) { + long did = (Long) args[0]; + if (did == dialog_id) { + updateVisibleRows(); + } } } @@ -3098,13 +3547,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (scrollToTopOnResume) { if (scrollToTopUnReadOnResume && scrollToMessage != null) { if (chatListView != null) { - final int yOffset = scrollToMessageMiddleScreen ? Math.max(0, (AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - scrollToMessage.textHeight - AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2) : 0; + final int yOffset = scrollToMessageMiddleScreen ? Math.max(0, (chatListView.getHeight() - scrollToMessage.getApproximateHeight()) / 2) : 0; chatListView.setSelectionFromTop(messages.size() - messages.indexOf(scrollToMessage), -chatListView.getPaddingTop() - AndroidUtilities.dp(7) + yOffset); } } else { - if (chatListView != null) { - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); - } + moveScrollToLastMessage(); } scrollToTopUnReadOnResume = false; scrollToTopOnResume = false; @@ -3121,7 +3568,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } readWhenResume = false; - MessagesController.getInstance().markDialogAsRead(dialog_id, messages.get(0).messageOwner.id, readWithMid, 0, readWithDate, true, false); + MessagesController.getInstance().markDialogAsRead(dialog_id, messages.get(0).getId(), readWithMid, 0, readWithDate, true, false); } fixLayout(true); @@ -3131,6 +3578,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not preferences.edit().remove("dialog_" + dialog_id).commit(); chatActivityEnterView.setFieldText(lastMessageText); } + String lastReplyMessage = preferences.getString("reply_" + dialog_id, null); + if (lastReplyMessage != null && lastReplyMessage.length() != 0) { + preferences.edit().remove("reply_" + dialog_id).commit(); + try { + byte[] bytes = Base64.decode(lastReplyMessage, Base64.DEFAULT); + if (bytes != null) { + SerializedData data = new SerializedData(bytes); + TLRPC.Message message = (TLRPC.Message) TLClassStore.Instance().TLdeserialize(data, data.readInt32()); + if (message != null) { + replyingMessageObject = new MessageObject(message, MessagesController.getInstance().getUsers(), false); + showReplyForMessageObjectOrForward(true, replyingMessageObject, null, false); + } + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } if (bottomOverlayChat.getVisibility() != View.VISIBLE) { chatActivityEnterView.setFieldFocused(true); } @@ -3179,6 +3643,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatActivityEnterView.setFieldFocused(false); } + if (replyingMessageObject != null) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + try { + SerializedData data = new SerializedData(); + replyingMessageObject.messageOwner.serializeToStream(data); + String string = Base64.encodeToString(data.toByteArray(), Base64.DEFAULT); + if (string != null && string.length() != 0) { + editor.putString("reply_" + dialog_id, string); + } + } catch (Exception e) { + editor.remove("reply_" + dialog_id); + FileLog.e("tmessages", e); + } + editor.commit(); + } MessagesController.getInstance().cancelTyping(dialog_id); @@ -3202,7 +3682,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ChatBaseCell cell = (ChatBaseCell) view; object = cell.getMessageObject(); } - if (object != null && object.messageOwner.id < 0 && object.messageOwner.random_id != 0) { + if (object != null && object.getId() < 0 && object.messageOwner.random_id != 0) { visibleMessages.add(object.messageOwner.random_id); } } @@ -3235,7 +3715,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } int padding = (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2; avatarContainer.setPadding(avatarContainer.getPaddingLeft(), padding, avatarContainer.getPaddingRight(), padding); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)avatarContainer.getLayoutParams(); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) avatarContainer.getLayoutParams(); layoutParams.topMargin = (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); avatarContainer.setLayoutParams(layoutParams); return false; @@ -3252,12 +3732,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatListView.getViewTreeObserver().removeOnPreDrawListener(this); if (lastPos >= messages.size() - 1) { - chatListView.post(new Runnable() { - @Override - public void run() { - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); - } - }); + moveScrollToLastMessage(); } return false; } @@ -3277,9 +3752,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MessageObject message = null; if (v instanceof ChatBaseCell) { - message = ((ChatBaseCell)v).getMessageObject(); + message = ((ChatBaseCell) v).getMessageObject(); } else if (v instanceof ChatActionCell) { - message = ((ChatActionCell)v).getMessageObject(); + message = ((ChatActionCell) v).getMessageObject(); } if (message == null) { return; @@ -3301,134 +3776,98 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); CharSequence[] items = null; + int[] options = null; if (type == 0) { - items = new CharSequence[] {LocaleController.getString("Retry", R.string.Retry), LocaleController.getString("Delete", R.string.Delete)}; + items = new CharSequence[]{LocaleController.getString("Retry", R.string.Retry), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{0, 1}; } else if (type == 1) { - items = new CharSequence[] {LocaleController.getString("Delete", R.string.Delete)}; + if (currentChat != null && !isBroadcast) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 1}; + } else { + items = new CharSequence[]{LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{1}; + } } else if (type == 7) { - items = new CharSequence[] {LocaleController.getString("Retry", R.string.Retry), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("Delete", R.string.Delete)}; + items = new CharSequence[]{LocaleController.getString("Retry", R.string.Retry), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{0, 3, 1}; } else { if (currentEncryptedChat == null) { - if (type == 2) { - items = new CharSequence[]{LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; - } else if (type == 3) { - items = new CharSequence[]{LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("Delete", R.string.Delete)}; - } else if (type == 4) { - items = new CharSequence[]{LocaleController.getString(selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument ? "ShareFile" : "SaveToGallery", - selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument ? R.string.ShareFile : R.string.SaveToGallery), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; - } else if (type == 5) { - items = new CharSequence[]{LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; - } else if (type == 6) { - items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + if (!isBroadcast && !(currentChat != null && (currentChat instanceof TLRPC.TL_chatForbidden || currentChat.left))) { + if (type == 2) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 2, 1}; + } else if (type == 3) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 2, 3, 1}; + } else if (type == 4) { + if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + } else { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + } + options = new int[]{8, 4, 2, 1}; + } else if (type == 5) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 5, 4, 2, 1}; + } else if (type == 6) { + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{8, 7, 6, 2, 1}; + } + } else { + if (type == 2) { + items = new CharSequence[]{LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{2, 1}; + } else if (type == 3) { + items = new CharSequence[]{LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{2, 3, 1}; + } else if (type == 4) { + if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + items = new CharSequence[]{LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + } else { + items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + } + options = new int[]{4, 2, 1}; + } else if (type == 5) { + items = new CharSequence[]{LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{5, 4, 2, 1}; + } else if (type == 6) { + items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{7, 6, 2, 1}; + } } } else { if (type == 2) { items = new CharSequence[]{LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{1}; } else if (type == 3) { items = new CharSequence[]{LocaleController.getString("Copy", R.string.Copy), LocaleController.getString("Delete", R.string.Delete)}; + options = new int[]{3, 1}; } else if (type == 4) { - items = new CharSequence[]{LocaleController.getString(selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument ? "ShareFile" : "SaveToGallery", - selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument ? R.string.ShareFile : R.string.SaveToGallery), LocaleController.getString("Delete", R.string.Delete)}; + if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { + items = new CharSequence[]{LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Delete", R.string.Delete)}; + } else { + items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Delete", R.string.Delete)}; + } + options = new int[]{4, 1}; } else if (type == 5) { items = new CharSequence[]{LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("Delete", R.string.Delete)}; - } + options = new int[]{5, 1}; + }/* else if (type == 6) { + options = new int[]{7, 6, 2, 1}; + }*/ } } + final int[] finalOptions = options; builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - if (selectedObject == null) { + if (finalOptions == null || selectedObject == null || i < 0 || i >= finalOptions.length) { return; } - if (type == 0) { - if (i == 0) { - processSelectedOption(0); - } else if (i == 1) { - processSelectedOption(1); - } - } else if (type == 1) { - processSelectedOption(1); - } else if (type == 2) { - if (currentEncryptedChat == null) { - if (i == 0) { - processSelectedOption(2); - } else if (i == 1) { - processSelectedOption(1); - } - } else { - processSelectedOption(1); - } - } else if (type == 3) { - if (currentEncryptedChat == null) { - if (i == 0) { - processSelectedOption(2); - } else if (i == 1) { - processSelectedOption(3); - } else if (i == 2) { - processSelectedOption(1); - } - } else { - if (i == 0) { - processSelectedOption(3); - } else if (i == 1) { - processSelectedOption(1); - } - } - } else if (type == 4) { - if (currentEncryptedChat == null) { - if (i == 0) { - processSelectedOption(4); - } else if (i == 1) { - processSelectedOption(2); - } else if (i == 2) { - processSelectedOption(1); - } - } else { - if (i == 0) { - processSelectedOption(4); - } else if (i == 1) { - processSelectedOption(1); - } - } - } else if (type == 5) { - if (i == 0) { - processSelectedOption(5); - } else { - if (currentEncryptedChat == null) { - if (i == 1) { - processSelectedOption(4); - } else if (i == 2) { - processSelectedOption(2); - } else if (i == 3) { - processSelectedOption(1); - } - } else { - if (i == 1) { - processSelectedOption(1); - } - } - } - } else if (type == 6) { - if (i == 0) { - processSelectedOption(7); - } else if (i == 1) { - processSelectedOption(6); - } else if (i == 2) { - processSelectedOption(2); - } else if (i == 3) { - processSelectedOption(1); - } - } else if (type == 7) { - if (i == 0) { - processSelectedOption(0); - } else if (i == 1) { - processSelectedOption(3); - } else if (i == 2) { - processSelectedOption(1); - } - } + processSelectedOption(finalOptions[i]); } }); @@ -3467,7 +3906,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (option == 0) { if (SendMessagesHelper.getInstance().retrySendMessage(selectedObject, false)) { - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); + moveScrollToLastMessage(); } } else if (option == 1) { final MessageObject finalSelectedObject = selectedObject; @@ -3478,7 +3917,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onClick(DialogInterface dialogInterface, int i) { ArrayList ids = new ArrayList<>(); - ids.add(finalSelectedObject.messageOwner.id); + ids.add(finalSelectedObject.getId()); removeUnreadPlane(true); ArrayList random_ids = null; if (currentEncryptedChat != null && finalSelectedObject.messageOwner.random_id != 0 && finalSelectedObject.type != 10) { @@ -3495,8 +3934,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putBoolean("serverOnly", true); - args.putString("selectAlertString", LocaleController.getString("ForwardMessagesTo", R.string.ForwardMessagesTo)); - args.putString("selectAlertStringGroup", LocaleController.getString("ForwardMessagesToGroup", R.string.ForwardMessagesToGroup)); MessagesActivity fragment = new MessagesActivity(args); fragment.setDelegate(this); presentFragment(fragment); @@ -3581,35 +4018,69 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MediaController.saveFile(path, getParentActivity(), 0, null); } } + } else if (option == 8) { + showReplyForMessageObjectOrForward(true, selectedObject, null, true); } selectedObject = null; } - private void forwardSelectedMessages(long did, boolean fromMyName) { - if (forwaringMessage != null) { - if (!fromMyName) { - if (forwaringMessage.messageOwner.id > 0) { - SendMessagesHelper.getInstance().sendMessage(forwaringMessage, did); - } - } else { - SendMessagesHelper.getInstance().processForwardFromMyName(forwaringMessage, did); - } - forwaringMessage = null; + private void openProfileWithUsername(String username) { + TLRPC.User user = MessagesController.getInstance().getUser(username); + if (user != null) { + Bundle args = new Bundle(); + args.putInt("user_id", user.id); + presentFragment(new ProfileActivity(args)); } else { - ArrayList ids = new ArrayList<>(selectedMessagesIds.keySet()); - Collections.sort(ids); - for (Integer id : ids) { - if (!fromMyName) { - if (id > 0) { - SendMessagesHelper.getInstance().sendMessage(selectedMessagesIds.get(id), did); - } - } else { - SendMessagesHelper.getInstance().processForwardFromMyName(selectedMessagesIds.get(id), did); - } + if (getParentActivity() == null) { + return; } - selectedMessagesCanCopyIds.clear(); - selectedMessagesIds.clear(); - actionBar.hideActionMode(); + final ProgressDialog progressDialog = new ProgressDialog(getParentActivity()); + 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() { + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + visibleDialog = null; + if (error == 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); + presentFragment(new ProfileActivity(args)); + } + } + }); + } + }); + 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); + } + visibleDialog = null; + } + }); + visibleDialog = progressDialog; + progressDialog.show(); } } @@ -3619,6 +4090,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (isBroadcast) { param = true; } + + ArrayList fmessages = new ArrayList<>(); + if (forwaringMessage != null) { + fmessages.add(forwaringMessage); + forwaringMessage = null; + } else { + ArrayList ids = new ArrayList<>(selectedMessagesIds.keySet()); + Collections.sort(ids); + for (Integer id : ids) { + MessageObject message = selectedMessagesIds.get(id); + if (message != null && id > 0) { + fmessages.add(message); + } + } + selectedMessagesCanCopyIds.clear(); + selectedMessagesIds.clear(); + actionBar.hideActionMode(); + } + if (did != dialog_id) { int lower_part = (int)did; if (lower_part != 0) { @@ -3631,6 +4121,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } ChatActivity chatActivity = new ChatActivity(args); presentFragment(chatActivity, true); + chatActivity.showReplyForMessageObjectOrForward(true, null, fmessages, false); if (!AndroidUtilities.isTablet()) { removeSelfFromStack(); Activity parentActivity = getParentActivity(); @@ -3641,15 +4132,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not parentActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); } } - forwardSelectedMessages(did, param); } else { activity.finishFragment(); } } else { activity.finishFragment(); - forwardSelectedMessages(did, param); - chatListView.setSelectionFromTop(messages.size() - 1, -100000 - chatListView.getPaddingTop()); - scrollToTopOnResume = true; + moveScrollToLastMessage(); + showReplyForMessageObjectOrForward(true, null, fmessages, AndroidUtilities.isTablet()); if (AndroidUtilities.isTablet()) { actionBar.hideActionMode(); } @@ -3694,7 +4183,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } }); - builder.setNegativeButton(R.string.Cancel, null); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showAlertDialog(builder); return false; } @@ -3713,7 +4202,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean disableSelection = false; boolean selected = false; if (actionBar.isActionModeShowed()) { - if (selectedMessagesIds.containsKey(cell.getMessageObject().messageOwner.id)) { + if (selectedMessagesIds.containsKey(cell.getMessageObject().getId())) { view.setBackgroundColor(0x6633b5e5); selected = true; } else { @@ -3725,12 +4214,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } cell.setMessageObject(cell.getMessageObject()); - cell.setCheckPressed(!disableSelection, disableSelection && selected); - - if (highlightMessageId != Integer.MAX_VALUE && cell.getMessageObject() != null && cell.getMessageObject().messageOwner.id == highlightMessageId) { - cell.setCheckPressed(false, true); - } + cell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && cell.getMessageObject() != null && cell.getMessageObject().getId() == highlightMessageId); } } } @@ -3769,14 +4254,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (view instanceof ChatMediaCell) { ChatMediaCell cell = (ChatMediaCell)view; MessageObject message = cell.getMessageObject(); - if (message != null && message.messageOwner.id == messageObject.messageOwner.id) { + if (message != null && message.getId() == messageObject.getId()) { messageToOpen = message; imageReceiver = cell.getPhotoImage(); } } else if (view instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell)view; MessageObject message = cell.getMessageObject(); - if (message != null && message.messageOwner.id == messageObject.messageOwner.id) { + if (message != null && message.getId() == messageObject.getId()) { messageToOpen = message; imageReceiver = cell.getPhotoImage(); } @@ -3884,7 +4369,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = li.inflate(R.layout.chat_loading_layout, viewGroup, false); progressBar = view.findViewById(R.id.progressLayout); - if (isCustomTheme) { + if (ApplicationLoader.isCustomTheme()) { progressBar.setBackgroundResource(R.drawable.system_loader2); } else { progressBar.setBackgroundResource(R.drawable.system_loader1); @@ -3947,6 +4432,78 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public boolean canPerformActions() { return actionBar != null && !actionBar.isActionModeShowed(); } + + @Override + public void didPressUrl(String url) { + if (url.startsWith("@")) { + openProfileWithUsername(url.substring(1)); + } else if (url.startsWith("#")) { + MessagesActivity fragment = new MessagesActivity(null); + fragment.setSearchString(url); + presentFragment(fragment); + } + } + + @Override + public void didPressReplyMessage(ChatBaseCell cell, int id) { + MessageObject object = messagesDict.get(id); + boolean query = false; + if (object != null) { + int index = messages.indexOf(object); + if (index != -1) { + highlightMessageId = id; + final int yOffset = Math.max(0, (chatListView.getHeight() - object.getApproximateHeight()) / 2); + if (messages.get(messages.size() - 1) == object) { + chatListView.setSelectionFromTop(0, AndroidUtilities.dp(-11) + yOffset); + } else { + chatListView.setSelectionFromTop(messages.size() - messages.indexOf(object), AndroidUtilities.dp(-11) + yOffset); + } + updateVisibleRows(); + showPagedownButton(true, true); + } else { + query = true; + } + } else { + query = true; + } + + if (query) { + messagesDict.clear(); + messagesByDays.clear(); + messages.clear(); + if (currentEncryptedChat == null) { + maxMessageId = Integer.MAX_VALUE; + minMessageId = Integer.MIN_VALUE; + } else { + maxMessageId = Integer.MIN_VALUE; + minMessageId = Integer.MAX_VALUE; + } + maxDate = Integer.MIN_VALUE; + endReached = false; + loading = false; + cacheEndReaced = false; + firstLoading = true; + loadsCount = 0; + minDate = 0; + first = true; + unread_to_load = 0; + first_unread_id = 0; + last_message_id = 0; + first_message_id = 0; + forward_end_reached = true; + loadingForward = false; + unreadMessageObject = null; + scrollToMessage = null; + highlightMessageId = Integer.MAX_VALUE; + scrollToMessageMiddleScreen = false; + loading = true; + startLoadFromMessageId = id; + MessagesController.getInstance().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, startLoadFromMessageId, true, 0, classGuid, 3, 0, 0, false); + chatAdapter.notifyDataSetChanged(); + progressView.setVisibility(View.VISIBLE); + chatListView.setEmptyView(null); + } + } }); if (view instanceof ChatMediaCell) { ((ChatMediaCell) view).setAllowedToSetPhoto(openAnimationEnded); @@ -4126,7 +4683,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean selected = false; boolean disableSelection = false; if (actionBar.isActionModeShowed()) { - if (selectedMessagesIds.containsKey(message.messageOwner.id)) { + if (selectedMessagesIds.containsKey(message.getId())) { view.setBackgroundColor(0x6633b5e5); selected = true; } else { @@ -4145,13 +4702,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (view instanceof ChatAudioCell && MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_AUDIO)) { ((ChatAudioCell)view).downloadAudioIfNeed(); } - if (highlightMessageId != Integer.MAX_VALUE && message.messageOwner.id == highlightMessageId) { - baseCell.setCheckPressed(false, true); - } + baseCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && message.getId() == highlightMessageId); } else if (view instanceof ChatActionCell) { ChatActionCell actionCell = (ChatActionCell)view; actionCell.setMessageObject(message); - actionCell.setUseBlackBackground(isCustomTheme); } if (type == 6) { TextView messageTextView = (TextView)view.findViewById(R.id.chat_message_text); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java index 962d8fe5c..e2a850391 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java @@ -31,6 +31,7 @@ public class AvatarDrawable extends Drawable { private static Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); private static TextPaint namePaint; + private static TextPaint namePaintSmall; private static int[] arrColors = {0xffe56555, 0xfff28c48, 0xffeec764, 0xff76c84d, 0xff5fbed5, 0xff549cdd, 0xff8e85ee, 0xfff2749a}; private static int[] arrColorsProfiles = {0xffd86f65, 0xfff69d61, 0xfffabb3c, 0xff67b35d, 0xff56a2bb, 0xff5c98cd, 0xff8c79d2, 0xfff37fa6}; private static int[] arrColorsProfilesBack = {0xffca6056, 0xfff18944, 0xff7d6ac4, 0xff56a14c, 0xff4492ac, 0xff4c84b6, 0xff7d6ac4, 0xff4c84b6}; @@ -39,8 +40,6 @@ public class AvatarDrawable extends Drawable { private static int[] arrColorsButtons = {R.drawable.bar_selector_red, R.drawable.bar_selector_orange, R.drawable.bar_selector_violet, R.drawable.bar_selector_green, R.drawable.bar_selector_cyan, R.drawable.bar_selector_blue, R.drawable.bar_selector_violet, R.drawable.bar_selector_blue}; - - private static Drawable broadcastDrawable; private static Drawable photoDrawable; @@ -52,6 +51,7 @@ public class AvatarDrawable extends Drawable { private boolean isProfile; private boolean drawBrodcast; private boolean drawPhoto; + private boolean smallStyle; public AvatarDrawable() { super(); @@ -61,6 +61,10 @@ public class AvatarDrawable extends Drawable { namePaint.setColor(0xffffffff); namePaint.setTextSize(AndroidUtilities.dp(20)); + namePaintSmall = new TextPaint(Paint.ANTI_ALIAS_FLAG); + namePaintSmall.setColor(0xffffffff); + namePaintSmall.setTextSize(AndroidUtilities.dp(14)); + broadcastDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.broadcast_w); } } @@ -89,6 +93,10 @@ public class AvatarDrawable extends Drawable { } } + public void setSmallStyle(boolean value) { + smallStyle = value; + } + public static int getColorIndex(int id) { if (id >= 0 && id < 8) { return id; @@ -205,7 +213,7 @@ public class AvatarDrawable extends Drawable { if (text.length() > 0) { text = text.toUpperCase(); try { - textLayout = new StaticLayout(text, namePaint, AndroidUtilities.dp(100), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + textLayout = new StaticLayout(text, (smallStyle ? namePaintSmall : namePaint), AndroidUtilities.dp(100), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (textLayout.getLineCount() > 0) { textLeft = textLayout.getLineLeft(0); textWidth = textLayout.getLineWidth(0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java index 0073edba1..a7472c6fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarUpdater.java @@ -45,8 +45,8 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg private boolean clearAfterUpdate = false; public boolean returnOnly = false; - public static abstract interface AvatarUpdaterDelegate { - public abstract void didUploadedPhoto(TLRPC.InputFile file, TLRPC.PhotoSize small, TLRPC.PhotoSize big); + public interface AvatarUpdaterDelegate { + void didUploadedPhoto(TLRPC.InputFile file, TLRPC.PhotoSize small, TLRPC.PhotoSize big); } public void clear() { @@ -76,18 +76,13 @@ public class AvatarUpdater implements NotificationCenter.NotificationCenterDeleg PhotoAlbumPickerActivity fragment = new PhotoAlbumPickerActivity(true); fragment.setDelegate(new PhotoAlbumPickerActivity.PhotoAlbumPickerActivityDelegate() { @Override - public void didSelectPhotos(ArrayList photos) { + public void didSelectPhotos(ArrayList photos, ArrayList webPhotos) { if (!photos.isEmpty()) { Bitmap bitmap = ImageLoader.loadBitmap(photos.get(0), null, 800, 800, true); processBitmap(bitmap); } } - @Override - public void didSelectWebPhotos(ArrayList photos) { - - } - @Override public void startPhotoSelectActivity() { try { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java index 33fd87355..e42561c3f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -11,7 +11,6 @@ package org.telegram.ui.Components; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; -import android.graphics.Rect; import android.media.AudioManager; import android.os.Build; import android.os.PowerManager; @@ -33,12 +32,14 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.PopupWindow; +import android.widget.RelativeLayout; import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.Emoji; import org.telegram.android.LocaleController; import org.telegram.android.MediaController; +import org.telegram.android.MessageObject; import org.telegram.android.MessagesController; import org.telegram.android.SendMessagesHelper; import org.telegram.messenger.ConnectionsManager; @@ -56,15 +57,15 @@ import org.telegram.messenger.ApplicationLoader; import java.lang.reflect.Field; -public class ChatActivityEnterView extends LinearLayout implements NotificationCenter.NotificationCenterDelegate, SizeNotifierRelativeLayout.SizeNotifierRelativeLayoutDelegate { +public class ChatActivityEnterView extends FrameLayoutFixed implements NotificationCenter.NotificationCenterDelegate, SizeNotifierRelativeLayout.SizeNotifierRelativeLayoutDelegate { - public static interface ChatActivityEnterViewDelegate { - public abstract void onMessageSend(); - public abstract void needSendTyping(); - public abstract void onTextChanged(CharSequence text); - public abstract void onAttachButtonHidden(); - public abstract void onAttachButtonShow(); - public abstract void onWindowSizeChanged(int size); + public interface ChatActivityEnterViewDelegate { + void onMessageSend(); + void needSendTyping(); + void onTextChanged(CharSequence text); + void onAttachButtonHidden(); + void onAttachButtonShow(); + void onWindowSizeChanged(int size); } private EditText messsageEditText; @@ -78,6 +79,8 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC private LinearLayout slideText; private SizeNotifierRelativeLayout sizeNotifierRelativeLayout; private FrameLayout attachButton; + private LinearLayout textFieldContainer; + private View topView; private PowerManager.WakeLock mWakeLock; private AnimatorSetProxy runningAnimation; @@ -95,16 +98,21 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC private float startedDraggingX = -1; private float distCanMove = AndroidUtilities.dp(80); private boolean recordingAudio; + private boolean forceShowSendButton; private Activity parentActivity; private BaseFragment parentFragment; private long dialog_id; private boolean ignoreTextChange; + private MessageObject replyingMessageObject; private ChatActivityEnterViewDelegate delegate; + private float topViewAnimation; + private boolean needShowTopView; + private boolean allowShowTopView; + public ChatActivityEnterView(Activity context, SizeNotifierRelativeLayout parent, BaseFragment fragment, boolean isChat) { super(context); - setOrientation(HORIZONTAL); setBackgroundResource(R.drawable.compose_panel); setFocusable(true); setFocusableInTouchMode(true); @@ -125,9 +133,20 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); sendByEnter = preferences.getBoolean("send_by_enter", false); + textFieldContainer = new LinearLayout(context); + textFieldContainer.setBackgroundColor(0xffffffff); + textFieldContainer.setOrientation(LinearLayout.HORIZONTAL); + addView(textFieldContainer); + LayoutParams layoutParams2 = (LayoutParams) textFieldContainer.getLayoutParams(); + layoutParams2.gravity = Gravity.LEFT | Gravity.TOP; + layoutParams2.width = LayoutParams.MATCH_PARENT; + layoutParams2.height = LayoutParams.WRAP_CONTENT; + layoutParams2.topMargin = AndroidUtilities.dp(2); + textFieldContainer.setLayoutParams(layoutParams2); + FrameLayoutFixed frameLayout = new FrameLayoutFixed(context); - addView(frameLayout); - LayoutParams layoutParams = (LayoutParams) frameLayout.getLayoutParams(); + textFieldContainer.addView(frameLayout); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) frameLayout.getLayoutParams(); layoutParams.width = 0; layoutParams.height = LayoutParams.WRAP_CONTENT; layoutParams.weight = 1; @@ -142,7 +161,6 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC layoutParams1.width = AndroidUtilities.dp(48); layoutParams1.height = AndroidUtilities.dp(48); layoutParams1.gravity = Gravity.BOTTOM; - layoutParams1.topMargin = AndroidUtilities.dp(2); emojiButton.setLayoutParams(layoutParams1); emojiButton.setOnClickListener(new View.OnClickListener() { @Override @@ -269,7 +287,6 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC layoutParams1.width = AndroidUtilities.dp(48); layoutParams1.height = AndroidUtilities.dp(48); layoutParams1.gravity = Gravity.BOTTOM | Gravity.RIGHT; - layoutParams1.topMargin = AndroidUtilities.dp(2); attachButton.setLayoutParams(layoutParams1); } @@ -281,11 +298,10 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC layoutParams1.width = FrameLayout.LayoutParams.MATCH_PARENT; layoutParams1.height = AndroidUtilities.dp(48); layoutParams1.gravity = Gravity.BOTTOM; - layoutParams1.topMargin = AndroidUtilities.dp(2); recordPanel.setLayoutParams(layoutParams1); slideText = new LinearLayout(context); - slideText.setOrientation(HORIZONTAL); + slideText.setOrientation(LinearLayout.HORIZONTAL); recordPanel.addView(slideText); layoutParams1 = (FrameLayout.LayoutParams) slideText.getLayoutParams(); layoutParams1.width = FrameLayout.LayoutParams.WRAP_CONTENT; @@ -297,7 +313,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC ImageView imageView = new ImageView(context); imageView.setImageResource(R.drawable.slidearrow); slideText.addView(imageView); - layoutParams = (LayoutParams) imageView.getLayoutParams(); + layoutParams = (LinearLayout.LayoutParams) imageView.getLayoutParams(); layoutParams.width = LayoutParams.WRAP_CONTENT; layoutParams.height = LayoutParams.WRAP_CONTENT; layoutParams.gravity = Gravity.CENTER_VERTICAL; @@ -309,7 +325,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC textView.setTextColor(0xff999999); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); slideText.addView(textView); - layoutParams = (LayoutParams) textView.getLayoutParams(); + layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams(); layoutParams.width = LayoutParams.WRAP_CONTENT; layoutParams.height = LayoutParams.WRAP_CONTENT; layoutParams.gravity = Gravity.CENTER_VERTICAL; @@ -317,7 +333,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC textView.setLayoutParams(layoutParams); LinearLayout linearLayout = new LinearLayout(context); - linearLayout.setOrientation(HORIZONTAL); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); linearLayout.setPadding(AndroidUtilities.dp(13), 0, 0, 0); linearLayout.setBackgroundColor(0xffffffff); recordPanel.addView(linearLayout); @@ -330,7 +346,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC imageView = new ImageView(context); imageView.setImageResource(R.drawable.rec); linearLayout.addView(imageView); - layoutParams = (LayoutParams) imageView.getLayoutParams(); + layoutParams = (LinearLayout.LayoutParams) imageView.getLayoutParams(); layoutParams.width = LayoutParams.WRAP_CONTENT; layoutParams.height = LayoutParams.WRAP_CONTENT; layoutParams.gravity = Gravity.CENTER_VERTICAL; @@ -342,7 +358,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC recordTimeText.setTextColor(0xff4d4c4b); recordTimeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); linearLayout.addView(recordTimeText); - layoutParams = (LayoutParams) recordTimeText.getLayoutParams(); + layoutParams = (LinearLayout.LayoutParams) recordTimeText.getLayoutParams(); layoutParams.width = LayoutParams.WRAP_CONTENT; layoutParams.height = LayoutParams.WRAP_CONTENT; layoutParams.gravity = Gravity.CENTER_VERTICAL; @@ -350,12 +366,11 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC recordTimeText.setLayoutParams(layoutParams); FrameLayout frameLayout1 = new FrameLayout(context); - addView(frameLayout1); - layoutParams = (LayoutParams) frameLayout1.getLayoutParams(); + textFieldContainer.addView(frameLayout1); + layoutParams = (LinearLayout.LayoutParams) frameLayout1.getLayoutParams(); layoutParams.width = AndroidUtilities.dp(48); layoutParams.height = AndroidUtilities.dp(48); layoutParams.gravity = Gravity.BOTTOM; - layoutParams.topMargin = AndroidUtilities.dp(2); frameLayout1.setLayoutParams(layoutParams); audioSendButton = new ImageView(context); @@ -390,7 +405,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC } } startedDraggingX = -1; - MediaController.getInstance().startRecording(dialog_id); + MediaController.getInstance().startRecording(dialog_id, replyingMessageObject); updateAudioRecordIntefrace(); audioSendButton.getParent().requestDisallowInterceptTouchEvent(true); } else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) { @@ -466,6 +481,135 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC checkSendButton(false); } + public void addTopView(View view, int height) { + if (view == null) { + return; + } + addView(view, 0); + topView = view; + topView.setVisibility(GONE); + needShowTopView = false; + LayoutParams layoutParams = (LayoutParams) topView.getLayoutParams(); + layoutParams.width = RelativeLayout.LayoutParams.MATCH_PARENT; + layoutParams.height = height; + layoutParams.topMargin = AndroidUtilities.dp(2); + layoutParams.gravity = Gravity.TOP | Gravity.LEFT; + topView.setLayoutParams(layoutParams); + } + + public void setTopViewAnimation(float progress) { + LayoutParams layoutParams2 = (LayoutParams) textFieldContainer.getLayoutParams(); + layoutParams2.topMargin = AndroidUtilities.dp(2) + (int) (topView.getLayoutParams().height * progress); + textFieldContainer.setLayoutParams(layoutParams2); + } + + public float getTopViewAnimation() { + return topViewAnimation; + } + + public void setForceShowSendButton(boolean value, boolean animated) { + forceShowSendButton = value; + checkSendButton(animated); + } + + public void showTopView(boolean animated) { + if (topView == null) { + return; + } + needShowTopView = true; + if (allowShowTopView) { + topView.setVisibility(VISIBLE); + if (animated) { + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(ChatActivityEnterView.this, "topViewAnimation", 0.0f, 1.0f) + ); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + LayoutParams layoutParams2 = (LayoutParams) textFieldContainer.getLayoutParams(); + layoutParams2.topMargin = AndroidUtilities.dp(2) + topView.getLayoutParams().height; + textFieldContainer.setLayoutParams(layoutParams2); + if (!forceShowSendButton) { + openKeyboard(); + } + } + }); + animatorSetProxy.setDuration(200); + animatorSetProxy.start(); + } else { + LayoutParams layoutParams2 = (LayoutParams) textFieldContainer.getLayoutParams(); + layoutParams2.topMargin = AndroidUtilities.dp(2) + topView.getLayoutParams().height; + textFieldContainer.setLayoutParams(layoutParams2); + } + } + } + + public void hideTopView(boolean animated) { + if (topView == null) { + return; + } + + needShowTopView = false; + if (allowShowTopView) { + if (animated) { + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(ChatActivityEnterView.this, "topViewAnimation", 1.0f, 0.0f) + ); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + topView.setVisibility(GONE); + LayoutParams layoutParams2 = (LayoutParams) textFieldContainer.getLayoutParams(); + layoutParams2.topMargin = AndroidUtilities.dp(2); + textFieldContainer.setLayoutParams(layoutParams2); + } + }); + animatorSetProxy.setDuration(200); + animatorSetProxy.start(); + } else { + topView.setVisibility(GONE); + LayoutParams layoutParams2 = (LayoutParams) textFieldContainer.getLayoutParams(); + layoutParams2.topMargin = AndroidUtilities.dp(2); + textFieldContainer.setLayoutParams(layoutParams2); + } + } + } + + public boolean isTopViewVisible() { + return topView != null && topView.getVisibility() == VISIBLE; + } + + private void onWindowSizeChanged(int size) { + if (delegate != null) { + delegate.onWindowSizeChanged(size); + } + if (topView != null) { + if (size < AndroidUtilities.dp(72) + AndroidUtilities.getCurrentActionBarHeight()) { + if (allowShowTopView) { + allowShowTopView = false; + if (needShowTopView) { + topView.setVisibility(View.GONE); + LayoutParams layoutParams2 = (LayoutParams) textFieldContainer.getLayoutParams(); + layoutParams2.topMargin = AndroidUtilities.dp(2); + textFieldContainer.setLayoutParams(layoutParams2); + } + } + } else { + if (!allowShowTopView) { + allowShowTopView = true; + if (needShowTopView) { + topView.setVisibility(View.VISIBLE); + LayoutParams layoutParams2 = (LayoutParams) textFieldContainer.getLayoutParams(); + layoutParams2.topMargin = AndroidUtilities.dp(2) + topView.getLayoutParams().height; + textFieldContainer.setLayoutParams(layoutParams2); + } + } + } + } + } + public void onDestroy() { NotificationCenter.getInstance().removeObserver(this, NotificationCenter.recordStarted); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.recordStartError); @@ -493,6 +637,10 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC dialog_id = id; } + public void setReplyingMessageObject(MessageObject messageObject) { + replyingMessageObject = messageObject; + } + private void sendMessage() { if (parentFragment != null) { String action = null; @@ -517,6 +665,10 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC if (delegate != null) { delegate.onMessageSend(); } + } else if (forceShowSendButton) { + if (delegate != null) { + delegate.onMessageSend(); + } } } @@ -526,7 +678,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC int count = (int) Math.ceil(text.length() / 4096.0f); for (int a = 0; a < count; a++) { String mess = text.substring(a * 4096, Math.min((a + 1) * 4096, text.length())); - SendMessagesHelper.getInstance().sendMessage(mess, dialog_id); + SendMessagesHelper.getInstance().sendMessage(mess, dialog_id, replyingMessageObject); } return true; } @@ -549,7 +701,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC private void checkSendButton(final boolean animated) { String message = getTrimmedString(messsageEditText.getText().toString()); - if (message.length() > 0) { + if (message.length() > 0 || forceShowSendButton) { if (audioSendButton.getVisibility() == View.VISIBLE) { if (animated) { if (runningAnimationType == 1) { @@ -631,7 +783,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC if (attachButton != null) { attachButton.setVisibility(View.GONE); attachButton.clearAnimation(); - + delegate.onAttachButtonHidden(); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messsageEditText.getLayoutParams(); layoutParams.rightMargin = AndroidUtilities.dp(0); messsageEditText.setLayoutParams(layoutParams); @@ -710,6 +862,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC sendButton.clearAnimation(); audioSendButton.setVisibility(View.VISIBLE); if (attachButton != null) { + delegate.onAttachButtonShow(); attachButton.setVisibility(View.VISIBLE); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messsageEditText.getLayoutParams(); layoutParams.rightMargin = AndroidUtilities.dp(50); @@ -825,12 +978,16 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC emojiPopup = new PopupWindow(emojiView); if (Build.VERSION.SDK_INT >= 21) { + /*emojiPopup.setAnimationStyle(0); + emojiPopup.setClippingEnabled(true); + emojiPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); + emojiPopup.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED);*/ try { Field field = PopupWindow.class.getDeclaredField("mWindowLayoutType"); field.setAccessible(true); field.set(emojiPopup, WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); } catch (Exception e) { - /* ignored */ + //ignored } } } @@ -853,22 +1010,43 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC emojiPopup.setWidth(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.EXACTLY)); } - try { - emojiPopup.showAtLocation(parentActivity.getWindow().getDecorView(), Gravity.BOTTOM | Gravity.LEFT, 0, 0); - } catch (Exception e) { - FileLog.e("tmessages", e); - return; - } + emojiPopup.showAtLocation(parentActivity.getWindow().getDecorView(), Gravity.BOTTOM | Gravity.LEFT, 0, 0); + + /*if (Build.VERSION.SDK_INT < 21) { + try { + + } catch (Exception e) { + FileLog.e("tmessages", e); + return; + } + }*/ if (!keyboardVisible) { + /*if (Build.VERSION.SDK_INT >= 21) { + try { + emojiPopup.showAsDropDown(this, 0, 0); + } catch (Exception e) { + FileLog.e("tmessages", e); + return; + } + }*/ if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.setPadding(0, 0, 0, currentHeight); emojiButton.setImageResource(R.drawable.ic_msg_panel_hide); - if (delegate != null) { - delegate.onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); - } + onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); } return; + } else { + /*if (Build.VERSION.SDK_INT >= 21) { + try { + emojiPopup.showAsDropDown(this, 0, -currentHeight - getHeight()); + emojiPopup.update(this, 0, -currentHeight - getHeight(), -1, -1); + AndroidUtilities.hideKeyboard(messsageEditText); + } catch (Exception e) { + FileLog.e("tmessages", e); + return; + } + }*/ } emojiButton.setImageResource(R.drawable.ic_msg_panel_kb); return; @@ -888,9 +1066,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC public void run() { if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.setPadding(0, 0, 0, 0); - if (delegate != null) { - delegate.onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); - } + onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); } } }); @@ -903,6 +1079,10 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC } } + public void openKeyboard() { + AndroidUtilities.showKeyboard(messsageEditText); + } + public void setDelegate(ChatActivityEnterViewDelegate delegate) { this.delegate = delegate; } @@ -915,6 +1095,27 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC messsageEditText.setText(text); messsageEditText.setSelection(messsageEditText.getText().length()); ignoreTextChange = false; + if (delegate != null) { + delegate.onTextChanged(messsageEditText.getText()); + } + } + + public int getCursorPosition() { + if (messsageEditText == null) { + return 0; + } + return messsageEditText.getSelectionStart(); + } + + public void replaceWithText(int start, int len, String text) { + try { + StringBuilder builder = new StringBuilder(messsageEditText.getText()); + builder.replace(start, start + len, text); + messsageEditText.setText(builder); + messsageEditText.setSelection(messsageEditText.length()); + } catch (Exception e) { + FileLog.e("tmessages", e); + } } public void setFieldFocused(boolean focus) { @@ -976,9 +1177,6 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC @Override public void onSizeChanged(int height) { - Rect localRect = new Rect(); - parentActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(localRect); - WindowManager wm = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Activity.WINDOW_SERVICE); if (wm == null || wm.getDefaultDisplay() == null) { return; @@ -1004,6 +1202,13 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC } final WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) emojiPopup.getContentView().getLayoutParams(); if (layoutParams.width != AndroidUtilities.displaySize.x || layoutParams.height != newHeight) { + /*if (Build.VERSION.SDK_INT >= 21) { + if (!keyboardVisible) { + emojiPopup.update(this, 0, 0, -1, -1); + } else { + emojiPopup.update(this, 0, -newHeight - getHeight(), -1, -1); + } + }*/ layoutParams.width = AndroidUtilities.displaySize.x; layoutParams.height = newHeight; wm.updateViewLayout(emojiPopup.getContentView(), layoutParams); @@ -1014,9 +1219,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC if (sizeNotifierRelativeLayout != null) { sizeNotifierRelativeLayout.setPadding(0, 0, 0, layoutParams.height); sizeNotifierRelativeLayout.requestLayout(); - if (delegate != null) { - delegate.onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); - } + onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); } } }); @@ -1031,9 +1234,7 @@ public class ChatActivityEnterView extends LinearLayout implements NotificationC } else if (!keyboardVisible && keyboardVisible != oldValue && emojiPopup != null && emojiPopup.isShowing()) { showEmojiPopup(false); } - if (delegate != null) { - delegate.onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); - } + onWindowSizeChanged(sizeNotifierRelativeLayout.getHeight() - sizeNotifierRelativeLayout.getPaddingBottom()); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java index d5441b706..6d6709781 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java @@ -41,8 +41,8 @@ public class ClippingImageView extends View { private RectF bitmapRect; private Matrix shaderMatrix; - public static interface onDrawListener { - public abstract void onDraw(); + public interface onDrawListener { + void onDraw(); } public ClippingImageView(Context context) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPickerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPickerView.java index ef7319a03..35ce2c4e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPickerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPickerView.java @@ -89,11 +89,11 @@ public class ColorPickerView extends View { } public interface OnColorChangedListener { - public void onColorChanged(int color); + void onColorChanged(int color); } public interface OnColorSelectedListener { - public void onColorSelected(int color); + void onColorSelected(int color); } public void setOnColorChangedListener(OnColorChangedListener listener) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 708e00f0b..28bdc149a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -299,8 +299,8 @@ public class EmojiView extends LinearLayout { } } - public static abstract interface Listener { - public abstract void onBackspace(); - public abstract void onEmojiSelected(String paramString); + public interface Listener { + void onBackspace(); + void onEmojiSelected(String paramString); } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java index b158dcac3..a1f4cf2f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForegroundDetector.java @@ -20,8 +20,8 @@ import java.util.concurrent.CopyOnWriteArrayList; public class ForegroundDetector implements Application.ActivityLifecycleCallbacks { public interface Listener { - public void onBecameForeground(); - public void onBecameBackground(); + void onBecameForeground(); + void onBecameBackground(); } private int refs; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java index 4cc5b0915..38728e89b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/HorizontalListView.java @@ -35,7 +35,7 @@ public class HorizontalListView extends AdapterView { private int mDisplayOffset = 0; protected Scroller mScroller; private GestureDetector mGesture; - private HashMap> mRemovedViewQueue = new HashMap>(); + private HashMap> mRemovedViewQueue = new HashMap<>(); private OnItemSelectedListener mOnItemSelected; private OnItemClickListener mOnItemClicked; private OnItemLongClickListener mOnItemLongClicked; @@ -251,7 +251,7 @@ public class HorizontalListView extends AdapterView { int type = (Integer) child.getTag(); LinkedList list = mRemovedViewQueue.get(type); if (list == null) { - list = new LinkedList(); + list = new LinkedList<>(); mRemovedViewQueue.put(type, list); } list.add(child); @@ -266,7 +266,7 @@ public class HorizontalListView extends AdapterView { int type = (Integer) child.getTag(); LinkedList list = mRemovedViewQueue.get(type); if (list == null) { - list = new LinkedList(); + list = new LinkedList<>(); mRemovedViewQueue.put(type, list); } list.add(child); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutListView.java index 6712cf6fb..1ed6f83b6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutListView.java @@ -8,6 +8,7 @@ package org.telegram.ui.Components; +import android.annotation.SuppressLint; import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; @@ -16,12 +17,13 @@ import android.widget.ListView; public class LayoutListView extends ListView { - public static interface OnInterceptTouchEventListener { - public abstract boolean onInterceptTouchEvent(MotionEvent event); + public interface OnInterceptTouchEventListener { + boolean onInterceptTouchEvent(MotionEvent event); } private OnInterceptTouchEventListener onInterceptTouchEventListener; private int height = -1; + private int forceTop = Integer.MIN_VALUE; public LayoutListView(Context context) { super(context); @@ -39,6 +41,10 @@ public class LayoutListView extends ListView { onInterceptTouchEventListener = listener; } + public void setForceTop(int value) { + forceTop = value; + } + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (onInterceptTouchEventListener != null) { @@ -47,25 +53,32 @@ public class LayoutListView extends ListView { return super.onInterceptTouchEvent(ev); } + @SuppressLint("DrawAllocation") @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { View v = getChildAt(getChildCount() - 1); + int scrollTo = getLastVisiblePosition(); if (v != null && height > 0 && changed && ((bottom - top) < height)) { - int b = height - v.getTop(); - final int scrollTo = getLastVisiblePosition(); + int lastTop = forceTop == Integer.MIN_VALUE ? (bottom - top) - (height - v.getTop()) - getPaddingTop() : forceTop; + forceTop = Integer.MIN_VALUE; + setSelectionFromTop(scrollTo, lastTop); super.onLayout(changed, left, top, right, bottom); - final int offset = (bottom - top) - b; - post(new Runnable() { - @Override - public void run() { - try { - setSelectionFromTop(scrollTo, offset - getPaddingTop()); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); + +// post(new Runnable() { +// @Override +// public void run() { +// try { +// setSelectionFromTop(scrollTo, lastTop); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// }); } else { + if (forceTop != Integer.MIN_VALUE) { + setSelectionFromTop(scrollTo, forceTop); + forceTop = Integer.MIN_VALUE; + } try { super.onLayout(changed, left, top, right, bottom); } catch (Exception e) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java index 37efc31a6..e87f71c0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java @@ -110,15 +110,15 @@ public class NumberPicker extends LinearLayout { } public interface OnScrollListener { - public static int SCROLL_STATE_IDLE = 0; - public static int SCROLL_STATE_TOUCH_SCROLL = 1; - public static int SCROLL_STATE_FLING = 2; + int SCROLL_STATE_IDLE = 0; + int SCROLL_STATE_TOUCH_SCROLL = 1; + int SCROLL_STATE_FLING = 2; - public void onScrollStateChange(NumberPicker view, int scrollState); + void onScrollStateChange(NumberPicker view, int scrollState); } public interface Formatter { - public String format(int value); + String format(int value); } private void init() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java index c568f4a78..33b34963e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java @@ -38,7 +38,7 @@ import org.telegram.messenger.R; public class PagerSlidingTabStrip extends HorizontalScrollView { public interface IconTabProvider { - public int getPageIconResId(int position); + int getPageIconResId(int position); } private LinearLayout.LayoutParams defaultTabLayoutParams; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java index dfd03904d..e314602c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java @@ -59,8 +59,8 @@ import java.util.Locale; public class PasscodeView extends FrameLayout { - public static interface PasscodeViewDelegate { - public abstract void didAcceptedPassword(); + public interface PasscodeViewDelegate { + void didAcceptedPassword(); } private class AnimatingTextView extends FrameLayout { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java index 4bd9ba572..5c19b596b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java @@ -22,8 +22,8 @@ import org.telegram.messenger.FileLog; public class PhotoCropView extends FrameLayout { - public static interface PhotoCropViewDelegate { - public abstract void needMoveImageTo(float x, float y, float s, boolean animated); + public interface PhotoCropViewDelegate { + void needMoveImageTo(float x, float y, float s, boolean animated); } private boolean freeformCrop = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java index 1d7687df3..bb92aa8ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoEditorSeekBar.java @@ -28,8 +28,8 @@ public class PhotoEditorSeekBar extends View { private int maxValue; private PhotoEditorSeekBarDelegate delegate; - public abstract interface PhotoEditorSeekBarDelegate { - public void onProgressChanged(); + public interface PhotoEditorSeekBarDelegate { + void onProgressChanged(); } public PhotoEditorSeekBar(Context context) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java new file mode 100644 index 000000000..8fb291765 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterBlurControl.java @@ -0,0 +1,499 @@ +/* + * This is the source code of Telegram for Android v. 2.x + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.view.MotionEvent; +import android.widget.FrameLayout; + +import org.telegram.android.AndroidUtilities; + +public class PhotoFilterBlurControl extends FrameLayout { + + public interface PhotoFilterLinearBlurControlDelegate { + void valueChanged(Point centerPoint, float falloff, float size, float angle); + } + + private final static float BlurInsetProximity = AndroidUtilities.dp(20); + private final static float BlurMinimumFalloff = 0.1f; + private final static float BlurMinimumDifference = 0.02f; + private final static float BlurViewCenterInset = AndroidUtilities.dp(30.0f); + private final static float BlurViewRadiusInset = AndroidUtilities.dp(30.0f); + + private enum BlurViewActiveControl { + BlurViewActiveControlNone, + BlurViewActiveControlCenter, + BlurViewActiveControlInnerRadius, + BlurViewActiveControlOuterRadius, + BlurViewActiveControlWholeArea, + BlurViewActiveControlRotation + } + + private final int GestureStateBegan = 1; + private final int GestureStateChanged = 2; + private final int GestureStateEnded = 3; + private final int GestureStateCancelled = 4; + private final int GestureStateFailed = 5; + + private BlurViewActiveControl activeControl; + private Point startCenterPoint = new Point(); + private float startDistance; + private float startRadius; + private Size actualAreaSize = new Size(); + private Point centerPoint = new Point(0.5f, 0.5f); + private float falloff = 0.15f; + private float size = 0.35f; + private float angle; + private RectF arcRect = new RectF(); + + private float pointerStartX; + private float pointerStartY; + private float startPointerDistance; + private float pointerScale = 1; + private boolean isMoving; + private boolean isZooming; + private boolean checkForMoving; + private boolean checkForZooming; + + private int type; + + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint arcPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private PhotoFilterLinearBlurControlDelegate delegate; + + public PhotoFilterBlurControl(Context context) { + super(context); + setWillNotDraw(false); + paint.setColor(0xffffffff); + arcPaint.setColor(0xffffffff); + arcPaint.setStrokeWidth(AndroidUtilities.dp(2)); + arcPaint.setStyle(Paint.Style.STROKE); + } + + public void setType(int blurType) { + type = blurType; + } + + public void setDelegate(PhotoFilterLinearBlurControlDelegate delegate) { + this.delegate = delegate; + } + + private float getDistance(MotionEvent event) { + if (event.getPointerCount() != 2) { + return 0; + } + float x1 = event.getX(0); + float y1 = event.getY(0); + float x2 = event.getX(1); + float y2 = event.getY(1); + return (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + } + + private float degreesToRadians(float degrees) { + return degrees * (float) Math.PI / 180.0f; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getActionMasked(); + + switch (action) { + case MotionEvent.ACTION_POINTER_DOWN: + case MotionEvent.ACTION_DOWN: { + if (event.getPointerCount() == 1) { + if (checkForMoving && !isMoving) { + float locationX = event.getX(); + float locationY = event.getY(); + Point centerPoint = getActualCenterPoint(); + Point delta = new Point(locationX - centerPoint.x, locationY - centerPoint.y); + float radialDistance = (float) Math.sqrt(delta.x * delta.x + delta.y * delta.y); + float innerRadius = getActualInnerRadius(); + float outerRadius = getActualOuterRadius(); + boolean close = Math.abs(outerRadius - innerRadius) < BlurInsetProximity; + float innerRadiusOuterInset = close ? 0 : BlurViewRadiusInset; + float outerRadiusInnerInset = close ? 0 : BlurViewRadiusInset; + + if (type == 0) { + float distance = (float) Math.abs(delta.x * Math.cos(degreesToRadians(angle) + Math.PI / 2) + delta.y * Math.sin(degreesToRadians(angle) + Math.PI / 2)); + if (radialDistance < BlurViewCenterInset) { + isMoving = true; + } else if (distance > innerRadius - BlurViewRadiusInset && distance < innerRadius + innerRadiusOuterInset) { + isMoving = true; + } else if (distance > outerRadius - outerRadiusInnerInset && distance < outerRadius + BlurViewRadiusInset) { + isMoving = true; + } else if ((distance <= innerRadius - BlurViewRadiusInset) || distance >= outerRadius + BlurViewRadiusInset) { + isMoving = true; + } + } else if (type == 1) { + if (radialDistance < BlurViewCenterInset) { + isMoving = true; + } else if (radialDistance > innerRadius - BlurViewRadiusInset && radialDistance < innerRadius + innerRadiusOuterInset) { + isMoving = true; + } else if (radialDistance > outerRadius - outerRadiusInnerInset && radialDistance < outerRadius + BlurViewRadiusInset) { + isMoving = true; + } + } + checkForMoving = false; + if (isMoving) { + handlePan(GestureStateBegan, event); + } + } + } else { + if (isMoving) { + handlePan(GestureStateEnded, event); + checkForMoving = true; + isMoving = false; + } + if (event.getPointerCount() == 2) { + if (checkForZooming && !isZooming) { + handlePinch(GestureStateBegan, event); + isZooming = true; + } + } else { + handlePinch(GestureStateEnded, event); + checkForZooming = true; + isZooming = false; + } + } + break; + } + + case MotionEvent.ACTION_POINTER_UP: + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: { + if (isMoving) { + handlePan(GestureStateEnded, event); + isMoving = false; + } else if (isZooming) { + handlePinch(GestureStateEnded, event); + isZooming = false; + } + checkForMoving = true; + checkForZooming = true; + break; + } + + case MotionEvent.ACTION_MOVE: { + if (isMoving) { + handlePan(GestureStateChanged, event); + } else if (isZooming) { + handlePinch(GestureStateChanged, event); + } + } + } + return true; + } + + private void handlePan(int state, MotionEvent event) { + float locationX = event.getX(); + float locationY = event.getY(); + Point actualCenterPoint = getActualCenterPoint(); + Point delta = new Point(locationX - actualCenterPoint.x, locationY - actualCenterPoint.y); + float radialDistance = (float) Math.sqrt(delta.x * delta.x + delta.y * delta.y); + float shorterSide = (actualAreaSize.width > actualAreaSize.height) ? actualAreaSize.height : actualAreaSize.width; + float innerRadius = shorterSide * falloff; + float outerRadius = shorterSide * size; + float distance = (float) Math.abs(delta.x * Math.cos(degreesToRadians(angle) + Math.PI / 2.0f) + delta.y * Math.sin(degreesToRadians(angle) + Math.PI / 2.0f)); + + switch (state) { + case GestureStateBegan: { + pointerStartX = event.getX(); + pointerStartY = event.getY(); + + boolean close = Math.abs(outerRadius - innerRadius) < BlurInsetProximity; + float innerRadiusOuterInset = close ? 0 : BlurViewRadiusInset; + float outerRadiusInnerInset = close ? 0 : BlurViewRadiusInset; + + if (type == 0) { + if (radialDistance < BlurViewCenterInset) { + activeControl = BlurViewActiveControl.BlurViewActiveControlCenter; + startCenterPoint = actualCenterPoint; + } else if (distance > innerRadius - BlurViewRadiusInset && distance < innerRadius + innerRadiusOuterInset) { + activeControl = BlurViewActiveControl.BlurViewActiveControlInnerRadius; + startDistance = distance; + startRadius = innerRadius; + } else if (distance > outerRadius - outerRadiusInnerInset && distance < outerRadius + BlurViewRadiusInset) { + activeControl = BlurViewActiveControl.BlurViewActiveControlOuterRadius; + startDistance = distance; + startRadius = outerRadius; + } else if (distance <= innerRadius - BlurViewRadiusInset || distance >= outerRadius + BlurViewRadiusInset) { + activeControl = BlurViewActiveControl.BlurViewActiveControlRotation; + } + } else if (type == 1) { + if (radialDistance < BlurViewCenterInset) { + activeControl = BlurViewActiveControl.BlurViewActiveControlCenter; + startCenterPoint = actualCenterPoint; + } else if (radialDistance > innerRadius - BlurViewRadiusInset && radialDistance < innerRadius + innerRadiusOuterInset) { + activeControl = BlurViewActiveControl.BlurViewActiveControlInnerRadius; + startDistance = radialDistance; + startRadius = innerRadius; + } else if (radialDistance > outerRadius - outerRadiusInnerInset && radialDistance < outerRadius + BlurViewRadiusInset) { + activeControl = BlurViewActiveControl.BlurViewActiveControlOuterRadius; + startDistance = radialDistance; + startRadius = outerRadius; + } + } + setSelected(true, true); + } + break; + + case GestureStateChanged: { + if (type == 0) { + switch (activeControl) { + case BlurViewActiveControlCenter: { + float translationX = locationX - pointerStartX; + float translationY = locationY - pointerStartY; + Rect actualArea = new Rect((getWidth() - actualAreaSize.width) / 2, (getHeight() - actualAreaSize.height) / 2, actualAreaSize.width, actualAreaSize.height); + Point newPoint = new Point(Math.max(actualArea.x, Math.min(actualArea.x + actualArea.width, startCenterPoint.x + translationX)), Math.max(actualArea.y, Math.min(actualArea.y + actualArea.height, startCenterPoint.y + translationY))); + centerPoint = new Point((newPoint.x - actualArea.x) / actualAreaSize.width, ((newPoint.y - actualArea.y) + (actualAreaSize.width - actualAreaSize.height) / 2) / actualAreaSize.width); + } + break; + + case BlurViewActiveControlInnerRadius: { + float d = distance - startDistance; + falloff = Math.min(Math.max(BlurMinimumFalloff, (startRadius + d) / shorterSide), size - BlurMinimumDifference); + } + break; + + case BlurViewActiveControlOuterRadius: { + float d = distance - startDistance; + size = Math.max(falloff + BlurMinimumDifference, (startRadius + d) / shorterSide); + } + break; + + case BlurViewActiveControlRotation: { + float translationX = locationX - pointerStartX; + float translationY = locationY - pointerStartY; + + boolean clockwise = false; + + boolean right = locationX > actualCenterPoint.x; + boolean bottom = locationY > actualCenterPoint.y; + + if (!right && !bottom) { + if (Math.abs(translationY) > Math.abs(translationX)) { + if (translationY < 0) { + clockwise = true; + } + } else { + if (translationX > 0) { + clockwise = true; + } + } + } else if (right && !bottom) { + if (Math.abs(translationY) > Math.abs(translationX)) { + if (translationY > 0) { + clockwise = true; + } + } else { + if (translationX > 0) { + clockwise = true; + } + } + } else if (right && bottom) { + if (Math.abs(translationY) > Math.abs(translationX)) { + if (translationY > 0) { + clockwise = true; + } + } else { + if (translationX < 0) { + clockwise = true; + } + } + } else { + if (Math.abs(translationY) > Math.abs(translationX)) { + if (translationY < 0) { + clockwise = true; + } + } else { + if (translationX < 0) { + clockwise = true; + } + } + } + + float d = (float) Math.sqrt(translationX * translationX + translationY * translationY); + angle += d * ((clockwise ? 1 : 0) * 2 - 1) / (float) Math.PI / 1.15f; + + pointerStartX = locationX; + pointerStartY = locationY; + } + break; + + default: + break; + } + } else if (type == 1) { + switch (activeControl) { + case BlurViewActiveControlCenter: { + float translationX = locationX - pointerStartX; + float translationY = locationY - pointerStartY; + Rect actualArea = new Rect((getWidth() - actualAreaSize.width) / 2, (getHeight() - actualAreaSize.height) / 2, actualAreaSize.width, actualAreaSize.height); + Point newPoint = new Point(Math.max(actualArea.x, Math.min(actualArea.x + actualArea.width, startCenterPoint.x + translationX)), Math.max(actualArea.y, Math.min(actualArea.y + actualArea.height, startCenterPoint.y + translationY))); + centerPoint = new Point((newPoint.x - actualArea.x) / actualAreaSize.width, ((newPoint.y - actualArea.y) + (actualAreaSize.width - actualAreaSize.height) / 2) / actualAreaSize.width); + } + break; + + case BlurViewActiveControlInnerRadius: { + float d = radialDistance - startDistance; + falloff = Math.min(Math.max(BlurMinimumFalloff, (startRadius + d) / shorterSide), size - BlurMinimumDifference); + } + break; + + case BlurViewActiveControlOuterRadius: { + float d = radialDistance - startDistance; + size = Math.max(falloff + BlurMinimumDifference, (startRadius + d) / shorterSide); + } + break; + + default: + break; + } + } + invalidate(); + + if (delegate != null) { + delegate.valueChanged(centerPoint, falloff, size, degreesToRadians(angle) + (float) Math.PI / 2.0f); + } + } + break; + + case GestureStateEnded: + case GestureStateCancelled: + case GestureStateFailed: { + activeControl = BlurViewActiveControl.BlurViewActiveControlNone; + setSelected(false, true); + } + break; + + default: + break; + } + } + + private void handlePinch(int state, MotionEvent event) { + + switch (state) { + case GestureStateBegan: { + startPointerDistance = getDistance(event); + pointerScale = 1; + activeControl = BlurViewActiveControl.BlurViewActiveControlWholeArea; + setSelected(true, true); + } + case GestureStateChanged: { + float newDistance = getDistance(event); + pointerScale += (newDistance - startPointerDistance) / AndroidUtilities.density * 0.01f; + + falloff = Math.max(BlurMinimumFalloff, falloff * pointerScale); + size = Math.max(falloff + BlurMinimumDifference, size * pointerScale); + + pointerScale = 1; + startPointerDistance = newDistance; + + invalidate(); + + if (delegate != null) { + delegate.valueChanged(centerPoint, falloff, size, degreesToRadians(angle) + (float) Math.PI / 2.0f); + } + } + break; + + case GestureStateEnded: + case GestureStateCancelled: + case GestureStateFailed: { + activeControl = BlurViewActiveControl.BlurViewActiveControlNone; + setSelected(false, true); + } + break; + + default: + break; + } + } + + private void setSelected(boolean selected, boolean animated) { + /*if (animated) { + [UIView animateWithDuration:0.16f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^ + { + self.alpha = selected ? 0.6f : 1.0f; + } completion:nil]; + } else { + self.alpha = selected ? 0.6f : 1.0f; + }*/ + } + + public void setActualAreaSize(float width, float height) { + actualAreaSize.width = width; + actualAreaSize.height = height; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + Point centerPoint = getActualCenterPoint(); + float innerRadius = getActualInnerRadius(); + float outerRadius = getActualOuterRadius(); + canvas.translate(centerPoint.x, centerPoint.y); + + if (type == 0) { + canvas.rotate(angle); + + float space = AndroidUtilities.dp(6.0f); + float length = AndroidUtilities.dp(12.0f); + float thickness = AndroidUtilities.dp(1.5f); + for (int i = 0; i < 30; i++) { + canvas.drawRect(i * (length + space), -innerRadius, i * (length + space) + length, thickness - innerRadius, paint); + canvas.drawRect(-i * (length + space) - space - length, -innerRadius, -i * (length + space) - space, thickness - innerRadius, paint); + + canvas.drawRect(i * (length + space), innerRadius, length + i * (length + space), thickness + innerRadius, paint); + canvas.drawRect(-i * (length + space) - space - length, innerRadius, -i * (length + space) - space, thickness + innerRadius, paint); + } + + length = AndroidUtilities.dp(6.0f); + for (int i = 0; i < 64; i++) { + canvas.drawRect(i * (length + space), -outerRadius, length + i * (length + space), thickness - outerRadius, paint); + canvas.drawRect(-i * (length + space) - space - length, -outerRadius, -i * (length + space) - space, thickness - outerRadius, paint); + + canvas.drawRect(i * (length + space), outerRadius, length + i * (length + space), thickness + outerRadius, paint); + canvas.drawRect(-i * (length + space) - space - length, outerRadius, -i * (length + space) - space, thickness + outerRadius, paint); + } + } else if (type == 1) { + float radSpace = 6.15f; + float radLen = 10.2f; + arcRect.set(-innerRadius, -innerRadius, innerRadius, innerRadius); + for (int i = 0; i < 22; i++) { + canvas.drawArc(arcRect, i * (radSpace + radLen), radLen, false, arcPaint); + } + + radSpace = 2.02f; + radLen = 3.6f; + arcRect.set(-outerRadius, -outerRadius, outerRadius, outerRadius); + for (int i = 0; i < 64; i++) { + canvas.drawArc(arcRect, i * (radSpace + radLen), radLen, false, arcPaint); + } + } + canvas.drawCircle(0, 0, AndroidUtilities.dp(8), paint); + } + + private Point getActualCenterPoint() { + return new Point((getWidth() - actualAreaSize.width) / 2 + centerPoint.x * actualAreaSize.width, (getHeight() - actualAreaSize.height) / 2 - (actualAreaSize.width - actualAreaSize.height) / 2 + centerPoint.y * actualAreaSize.width); + } + + private float getActualInnerRadius() { + return (actualAreaSize.width > actualAreaSize.height ? actualAreaSize.height : actualAreaSize.width) * falloff; + } + + private float getActualOuterRadius() { + return (actualAreaSize.width > actualAreaSize.height ? actualAreaSize.height : actualAreaSize.width) * size; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterLinearBlurControl.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterLinearBlurControl.java deleted file mode 100644 index 86e4505f7..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterLinearBlurControl.java +++ /dev/null @@ -1,417 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 2.x - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2015. - */ - -package org.telegram.ui.Components; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.PointF; -import android.graphics.RectF; -import android.util.SizeF; -import android.widget.FrameLayout; - -public class PhotoFilterLinearBlurControl extends FrameLayout { - - private final static float LinearBlurInsetProximity = 20; - private final static float LinearBlurMinimumFalloff = 0.1f; - private final static float LinearBlurMinimumDifference = 0.02f; - private final static float LinearBlurViewCenterInset = 30.0f; - private final static float LinearBlurViewRadiusInset = 30.0f; - - private enum LinearBlurViewActiveControl { - TGLinearBlurViewActiveControlNone, - TGLinearBlurViewActiveControlCenter, - TGLinearBlurViewActiveControlInnerRadius, - TGLinearBlurViewActiveControlOuterRadius, - TGLinearBlurViewActiveControlWholeArea, - TGLinearBlurViewActiveControlRotation - } - - private LinearBlurViewActiveControl activeControl; - private PointF startCenterPoint = new PointF(); - private PointF startDistance = new PointF(); - private PointF startRadius = new PointF(); - private boolean isTracking; - private SizeF actualAreaSize; - private PointF centerPoint; - private float falloff; - private float size; - private float angle; - - //@property (nonatomic, copy) void (^valueChanged)(CGPoint centerPoint, CGFloat falloff, CGFloat size, CGFloat angle); - //@property (nonatomic, copy) void(^interactionEnded)(void); - //UILongPressGestureRecognizer *_pressGestureRecognizer; - //UIPanGestureRecognizer *_panGestureRecognizer; - //UIPinchGestureRecognizer *_pinchGestureRecognizer; - - public PhotoFilterLinearBlurControl(Context context) { - super(context); - - setWillNotDraw(false); - - centerPoint = new PointF(0.5f, 0.5f); - falloff = 0.15f; - size = 0.35f; - - /*_pressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePress:)]; - _pressGestureRecognizer.delegate = self; - _pressGestureRecognizer.minimumPressDuration = 0.1f; - [self addGestureRecognizer:_pressGestureRecognizer]; - - _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; - _panGestureRecognizer.delegate = self; - [self addGestureRecognizer:_panGestureRecognizer]; - - _pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)]; - _pinchGestureRecognizer.delegate = self; - [self addGestureRecognizer:_pinchGestureRecognizer];*/ - } - - - private void handlePress() { - /*switch (gestureRecognizer.state) { - case UIGestureRecognizerStateBegan: - [self setSelected:true animated:true]; - break; - - case UIGestureRecognizerStateEnded: - case UIGestureRecognizerStateCancelled: - case UIGestureRecognizerStateFailed: - [self setSelected:false animated:true]; - break; - - default: - break; - }*/ - } - - private void handlePan() { - /*CGPoint location = [gestureRecognizer locationInView:self]; - CGPoint centerPoint = [self _actualCenterPoint]; - CGPoint delta = CGPointMake(location.x - centerPoint.x, location.y - centerPoint.y); - CGFloat radialDistance = sqrtf(delta.x * delta.x + delta.y * delta.y); - CGFloat distance = fabsf(delta.x * cosf(self.angle + (CGFloat)M_PI_2) + delta.y * sinf(self.angle + (CGFloat)M_PI_2)); - - CGFloat shorterSide = (self.actualAreaSize.width > self.actualAreaSize.height) ? self.actualAreaSize.height : self.actualAreaSize.width; - - CGFloat innerRadius = shorterSide * self.falloff; - CGFloat outerRadius = shorterSide * self.size; - - switch (gestureRecognizer.state) { - case UIGestureRecognizerStateBegan: - { - bool close = fabsf(outerRadius - innerRadius) < TGLinearBlurInsetProximity; - CGFloat innerRadiusOuterInset = close ? 0 : TGLinearBlurViewRadiusInset; - CGFloat outerRadiusInnerInset = close ? 0 : TGLinearBlurViewRadiusInset; - - if (radialDistance < TGLinearBlurViewCenterInset) - { - _activeControl = TGLinearBlurViewActiveControlCenter; - _startCenterPoint = centerPoint; - } - else if (distance > innerRadius - TGLinearBlurViewRadiusInset && distance < innerRadius + innerRadiusOuterInset) - { - _activeControl = TGLinearBlurViewActiveControlInnerRadius; - _startDistance = distance; - _startRadius = innerRadius; - } - else if (distance > outerRadius - outerRadiusInnerInset && distance < outerRadius + TGLinearBlurViewRadiusInset) - { - _activeControl = TGLinearBlurViewActiveControlOuterRadius; - _startDistance = distance; - _startRadius = outerRadius; - } - else if (distance <= innerRadius - TGLinearBlurViewRadiusInset || distance >= outerRadius + TGLinearBlurViewRadiusInset) - { - _activeControl = TGLinearBlurViewActiveControlRotation; - } - - [self setSelected:true animated:true]; - } - break; - - case UIGestureRecognizerStateChanged: - { - switch (_activeControl) - { - case TGLinearBlurViewActiveControlCenter: - { - CGPoint translation = [gestureRecognizer translationInView:self]; - - CGRect actualArea = CGRectMake((self.frame.size.width - self.actualAreaSize.width) / 2, (self.frame.size.height - self.actualAreaSize.height) / 2, self.actualAreaSize.width, self.actualAreaSize.height); - - CGPoint newPoint = CGPointMake(MAX(CGRectGetMinX(actualArea), MIN(CGRectGetMaxX(actualArea), _startCenterPoint.x + translation.x)), - MAX(CGRectGetMinY(actualArea), MIN(CGRectGetMaxY(actualArea), _startCenterPoint.y + translation.y))); - - CGPoint offset = CGPointMake(0, (self.actualAreaSize.width - self.actualAreaSize.height) / 2); - CGPoint actualPoint = CGPointMake(newPoint.x - actualArea.origin.x, newPoint.y - actualArea.origin.y); - self.centerPoint = CGPointMake((actualPoint.x + offset.x) / self.actualAreaSize.width, (actualPoint.y + offset.y) / self.actualAreaSize.width); - } - break; - - case TGLinearBlurViewActiveControlInnerRadius: - { - CGFloat delta = distance - _startDistance; - self.falloff = MIN(MAX(TGLinearBlurMinimumFalloff, (_startRadius + delta) / shorterSide), self.size - TGLinearBlurMinimumDifference); - } - break; - - case TGLinearBlurViewActiveControlOuterRadius: - { - CGFloat delta = distance - _startDistance; - self.size = MAX(self.falloff + TGLinearBlurMinimumDifference, (_startRadius + delta) / shorterSide); - } - break; - - case TGLinearBlurViewActiveControlRotation: - { - CGPoint translation = [gestureRecognizer translationInView:self]; - bool clockwise = false; - - bool right = location.x > centerPoint.x; - bool bottom = location.y > centerPoint.y; - - if (!right && !bottom) - { - if (fabsf(translation.y) > fabsf(translation.x)) - { - if (translation.y < 0) - clockwise = true; - } - else - { - if (translation.x > 0) - clockwise = true; - } - } - else if (right && !bottom) - { - if (fabsf(translation.y) > fabsf(translation.x)) - { - if (translation.y > 0) - clockwise = true; - } - else - { - if (translation.x > 0) - clockwise = true; - } - } - else if (right && bottom) - { - if (fabsf(translation.y) > fabsf(translation.x)) - { - if (translation.y > 0) - clockwise = true; - } - else - { - if (translation.x < 0) - clockwise = true; - } - } - else - { - if (fabsf(translation.y) > fabsf(translation.x)) - { - if (translation.y < 0) - clockwise = true; - } - else - { - if (translation.x < 0) - clockwise = true; - } - } - - CGFloat delta = sqrtf(translation.x * translation.x + translation.y * translation.y); - - CGFloat angleInDegrees = TGRadiansToDegrees(_angle); - CGFloat newAngleInDegrees = angleInDegrees + delta * (clockwise * 2 - 1) / (CGFloat)M_PI / 1.15f; - - _angle = TGDegreesToRadians(newAngleInDegrees); - - [gestureRecognizer setTranslation:CGPointZero inView:self]; - } - break; - - default: - break; - } - - [self setNeedsDisplay]; - - if (self.valueChanged != nil) - self.valueChanged(self.centerPoint, self.falloff, self.size, self.angle); - } - break; - - case UIGestureRecognizerStateEnded: - case UIGestureRecognizerStateCancelled: - case UIGestureRecognizerStateFailed: - { - _activeControl = TGLinearBlurViewActiveControlNone; - - [self setSelected:false animated:true]; - - if (self.interactionEnded != nil) - self.interactionEnded(); - } - break; - - default: - break; - }*/ - } - - private void handlePinch() { - /*switch (gestureRecognizer.state) { - case UIGestureRecognizerStateBegan: { - _activeControl = TGLinearBlurViewActiveControlWholeArea; - [self setSelected:true animated:true]; - } - case UIGestureRecognizerStateChanged: { - CGFloat scale = gestureRecognizer.scale; - - self.falloff = MAX(TGLinearBlurMinimumFalloff, self.falloff * scale); - self.size = MAX(self.falloff + TGLinearBlurMinimumDifference, self.size * scale); - - gestureRecognizer.scale = 1.0f; - - [self setNeedsDisplay]; - - if (self.valueChanged != nil) - self.valueChanged(self.centerPoint, self.falloff, self.size, self.angle); - } - break; - - case UIGestureRecognizerStateEnded: { - _activeControl = TGLinearBlurViewActiveControlNone; - [self setSelected:false animated:true]; - } - break; - - case UIGestureRecognizerStateCancelled: - case UIGestureRecognizerStateFailed: { - _activeControl = TGLinearBlurViewActiveControlNone; - [self setSelected:false animated:true]; - } - break; - - default: - break; - }*/ - } - - /*- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer - { - if (gestureRecognizer == _pressGestureRecognizer || gestureRecognizer == _panGestureRecognizer) - { - CGPoint location = [gestureRecognizer locationInView:self]; - CGPoint centerPoint = [self _actualCenterPoint]; - CGPoint delta = CGPointMake(location.x - centerPoint.x, location.y - centerPoint.y); - CGFloat radialDistance = sqrtf(delta.x * delta.x + delta.y * delta.y); - CGFloat distance = fabsf(delta.x * cosf(self.angle + (CGFloat)M_PI_2) + delta.y * sinf(self.angle + (CGFloat)M_PI_2)); - - CGFloat innerRadius = [self _actualInnerRadius]; - CGFloat outerRadius = [self _actualOuterRadius]; - - bool close = fabsf(outerRadius - innerRadius) < TGLinearBlurInsetProximity; - CGFloat innerRadiusOuterInset = close ? 0 : TGLinearBlurViewRadiusInset; - CGFloat outerRadiusInnerInset = close ? 0 : TGLinearBlurViewRadiusInset; - - if (radialDistance < TGLinearBlurViewCenterInset && gestureRecognizer == _panGestureRecognizer) - return true; - else if (distance > innerRadius - TGLinearBlurViewRadiusInset && distance < innerRadius + innerRadiusOuterInset) - return true; - else if (distance > outerRadius - outerRadiusInnerInset && distance < outerRadius + TGLinearBlurViewRadiusInset) - return true; - else if ((distance <= innerRadius - TGLinearBlurViewRadiusInset) || distance >= outerRadius + TGLinearBlurViewRadiusInset) - return true; - - return false; - } - - return true; - } - - - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer - { - if (gestureRecognizer == _pressGestureRecognizer || otherGestureRecognizer == _pressGestureRecognizer) - return true; - - return false; - }*/ - - private void setSelected(boolean selected, boolean animated) { - /*if (animated) { - [UIView animateWithDuration:0.16f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^ - { - self.alpha = selected ? 0.6f : 1.0f; - } completion:nil]; - } else { - self.alpha = selected ? 0.6f : 1.0f; - }*/ - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - /*PointF centerPoint = getActualCenterPoint(); - float innerRadius = getActualInnerRadius(); - float outerRadius = getActualOuterRadius(); - - CGContextTranslateCTM(context, centerPoint.x, centerPoint.y); - CGContextRotateCTM(context, self.angle); - - CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); - CGContextSetShadowWithColor(context, CGSizeZero, 2.5f, [UIColor colorWithWhite:0.0f alpha:0.3f].CGColor); - - float space = 6.0f; - float length = 12.0f; - float thickness = 1.5f; - for (int i = 0; i < 30; i++) { - CGContextAddRect(context, CGRectMake(i * (length + space), -innerRadius, length, thickness)); - CGContextAddRect(context, CGRectMake(-i * (length + space) - space - length, -innerRadius, length, thickness)); - - CGContextAddRect(context, CGRectMake(i * (length + space), innerRadius, length, thickness)); - CGContextAddRect(context, CGRectMake(-i * (length + space) - space - length, innerRadius, length, thickness)); - } - - length = 6.0f; - thickness = 1.5f; - for (int i = 0; i < 64; i++) { - CGContextAddRect(context, CGRectMake(i * (length + space), -outerRadius, length, thickness)); - CGContextAddRect(context, CGRectMake(-i * (length + space) - space - length, -outerRadius, length, thickness)); - - CGContextAddRect(context, CGRectMake(i * (length + space), outerRadius, length, thickness)); - CGContextAddRect(context, CGRectMake(-i * (length + space) - space - length, outerRadius, length, thickness)); - } - - CGContextFillPath(context); - - CGContextFillEllipseInRect(context, CGRectMake(-16 / 2, - 16 / 2, 16, 16));*/ - } - - private PointF getActualCenterPoint() { - RectF actualArea = new RectF((getWidth() - actualAreaSize.getWidth()) / 2, (getHeight() - actualAreaSize.getHeight()) / 2, actualAreaSize.getWidth(), actualAreaSize.getHeight()); - PointF offset = new PointF(0, (actualAreaSize.getWidth() - actualAreaSize.getHeight()) / 2); - return new PointF(actualArea.left - offset.x + centerPoint.x * actualAreaSize.getWidth(), actualArea.top - offset.y + centerPoint.y * actualAreaSize.getWidth()); - } - - private float getActualInnerRadius() { - float shorterSide = (actualAreaSize.getWidth() > actualAreaSize.getHeight()) ? actualAreaSize.getHeight() : actualAreaSize.getWidth(); - return shorterSide * falloff; - } - - private float getActualOuterRadius() { - float shorterSide = (actualAreaSize.getWidth() > actualAreaSize.getHeight()) ? actualAreaSize.getHeight() : actualAreaSize.getWidth(); - return shorterSide * size; - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java index 2037f1d13..da9ac0662 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java @@ -71,8 +71,8 @@ public class PhotoFilterView extends FrameLayout { private int shadowsTool = 6; private int vignetteTool = 7; private int grainTool = 8; - private int blurTool = -1; - private int sharpenTool = 9; + private int blurTool = 9; + private int sharpenTool = 10; private float highlightsValue = 0; //0 100 private float contrastValue = 0; //-100 100 @@ -84,18 +84,29 @@ public class PhotoFilterView extends FrameLayout { private float vignetteValue = 0; //0 100 private float grainValue = 0; //0 100 private float sharpenValue = 0; //0 100 + private int blurType = 0; //0 none, 1 radial, 2 linear + private float blurExcludeSize = 0.35f; + private Point blurExcludePoint = new Point(0.5f, 0.5f); + private float blurExcludeBlurSize = 0.15f; + private float blurAngle = (float) Math.PI / 2.0f; private ToolsAdapter toolsAdapter; private PhotoEditorSeekBar valueSeekBar; private FrameLayout toolsView; private FrameLayout editView; private TextView paramTextView; + private TextView blurTextView; private TextView valueTextView; private TextView doneTextView; private TextView cancelTextView; private TextureView textureView; private EGLThread eglThread; private RecyclerListView recyclerListView; + private FrameLayout blurLayout; + private PhotoFilterBlurControl blurControl; + private TextView blurOffButton; + private TextView blurRadialButton; + private TextView blurLinearButton; private Bitmap bitmapToEdit; private int orientation; @@ -112,6 +123,7 @@ public class PhotoFilterView extends FrameLayout { private EGLSurface eglSurface; private GL gl; private boolean initied; + private boolean needUpdateBlurTexture = true; private Bitmap currentBitmap; @@ -142,6 +154,34 @@ public class PhotoFilterView extends FrameLayout { private int widthHandle; private int heightHandle; + private int blurShaderProgram; + private int blurPositionHandle; + private int blurInputTexCoordHandle; + private int blurSourceImageHandle; + private int blurWidthHandle; + private int blurHeightHandle; + + private int linearBlurShaderProgram; + private int linearBlurPositionHandle; + private int linearBlurInputTexCoordHandle; + private int linearBlurSourceImageHandle; + private int linearBlurSourceImage2Handle; + private int linearBlurExcludeSizeHandle; + private int linearBlurExcludePointHandle; + private int linearBlurExcludeBlurSizeHandle; + private int linearBlurAngleHandle; + private int linearBlurAspectRatioHandle; + + private int radialBlurShaderProgram; + private int radialBlurPositionHandle; + private int radialBlurInputTexCoordHandle; + private int radialBlurSourceImageHandle; + private int radialBlurSourceImage2Handle; + private int radialBlurExcludeSizeHandle; + private int radialBlurExcludePointHandle; + private int radialBlurExcludeBlurSizeHandle; + private int radialBlurAspectRatioHandle; + private int sharpenShaderProgram; private int sharpenHandle; private int sharpenWidthHandle; @@ -156,8 +196,8 @@ public class PhotoFilterView extends FrameLayout { private int simpleSourceImageHandle; private int[] enhanceTextures = new int[2]; - private int[] renderTexture = new int[2]; - private int[] renderFrameBuffer = new int[2]; + private int[] renderTexture = new int[3]; + private int[] renderFrameBuffer = new int[3]; private boolean hsvGenerated; private int renderBufferWidth; private int renderBufferHeight; @@ -168,9 +208,81 @@ public class PhotoFilterView extends FrameLayout { private FloatBuffer textureBuffer; private FloatBuffer vertexInvertBuffer; + private boolean blured; + private final static int PGPhotoEnhanceHistogramBins = 256; private final static int PGPhotoEnhanceSegments = 4; + private static final String radialBlurFragmentShaderCode = + "varying highp vec2 texCoord;" + + "uniform sampler2D sourceImage;" + + "uniform sampler2D inputImageTexture2;" + + "uniform lowp float excludeSize;" + + "uniform lowp vec2 excludePoint;" + + "uniform lowp float excludeBlurSize;" + + "uniform highp float aspectRatio;" + + "void main() {" + + "lowp vec4 sharpImageColor = texture2D(sourceImage, texCoord);" + + "lowp vec4 blurredImageColor = texture2D(inputImageTexture2, texCoord);" + + "highp vec2 texCoordToUse = vec2(texCoord.x, (texCoord.y * aspectRatio + 0.5 - 0.5 * aspectRatio));" + + "highp float distanceFromCenter = distance(excludePoint, texCoordToUse);" + + "gl_FragColor = mix(sharpImageColor, blurredImageColor, smoothstep(excludeSize - excludeBlurSize, excludeSize, distanceFromCenter));" + + "}"; + + private static final String linearBlurFragmentShaderCode = + "varying highp vec2 texCoord;" + + "uniform sampler2D sourceImage;" + + "uniform sampler2D inputImageTexture2;" + + "uniform lowp float excludeSize;" + + "uniform lowp vec2 excludePoint;" + + "uniform lowp float excludeBlurSize;" + + "uniform highp float angle;" + + "uniform highp float aspectRatio;" + + "void main() {" + + "lowp vec4 sharpImageColor = texture2D(sourceImage, texCoord);" + + "lowp vec4 blurredImageColor = texture2D(inputImageTexture2, texCoord);" + + "highp vec2 texCoordToUse = vec2(texCoord.x, (texCoord.y * aspectRatio + 0.5 - 0.5 * aspectRatio));" + + "highp float distanceFromCenter = abs((texCoordToUse.x - excludePoint.x) * aspectRatio * cos(angle) + (texCoordToUse.y - excludePoint.y) * sin(angle));" + + "gl_FragColor = mix(sharpImageColor, blurredImageColor, smoothstep(excludeSize - excludeBlurSize, excludeSize, distanceFromCenter));" + + "}"; + + private static final String blurVertexShaderCode = + "attribute vec4 position;" + + "attribute vec4 inputTexCoord;" + + "uniform highp float texelWidthOffset;" + + "uniform highp float texelHeightOffset;" + + "varying vec2 blurCoordinates[9];" + + "void main() {" + + "gl_Position = position;" + + "vec2 singleStepOffset = vec2(texelWidthOffset, texelHeightOffset);" + + "blurCoordinates[0] = inputTexCoord.xy;" + + "blurCoordinates[1] = inputTexCoord.xy + singleStepOffset * 1.458430;" + + "blurCoordinates[2] = inputTexCoord.xy - singleStepOffset * 1.458430;" + + "blurCoordinates[3] = inputTexCoord.xy + singleStepOffset * 3.403985;" + + "blurCoordinates[4] = inputTexCoord.xy - singleStepOffset * 3.403985;" + + "blurCoordinates[5] = inputTexCoord.xy + singleStepOffset * 5.351806;" + + "blurCoordinates[6] = inputTexCoord.xy - singleStepOffset * 5.351806;" + + "blurCoordinates[7] = inputTexCoord.xy + singleStepOffset * 7.302940;" + + "blurCoordinates[8] = inputTexCoord.xy - singleStepOffset * 7.302940;" + + "}"; + + private static final String blurFragmentShaderCode = + "uniform sampler2D sourceImage;" + + "varying highp vec2 blurCoordinates[9];" + + "void main() {" + + "lowp vec4 sum = vec4(0.0);" + + "sum += texture2D(sourceImage, blurCoordinates[0]) * 0.133571;" + + "sum += texture2D(sourceImage, blurCoordinates[1]) * 0.233308;" + + "sum += texture2D(sourceImage, blurCoordinates[2]) * 0.233308;" + + "sum += texture2D(sourceImage, blurCoordinates[3]) * 0.135928;" + + "sum += texture2D(sourceImage, blurCoordinates[4]) * 0.135928;" + + "sum += texture2D(sourceImage, blurCoordinates[5]) * 0.051383;" + + "sum += texture2D(sourceImage, blurCoordinates[6]) * 0.051383;" + + "sum += texture2D(sourceImage, blurCoordinates[7]) * 0.012595;" + + "sum += texture2D(sourceImage, blurCoordinates[8]) * 0.012595;" + + "gl_FragColor = sum;" + + "}"; + private static final String rgbToHsvFragmentShaderCode = "precision highp float;" + "varying vec2 texCoord;" + @@ -628,6 +740,97 @@ public class PhotoFilterView extends FrameLayout { return false; } + vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, blurVertexShaderCode); + fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, blurFragmentShaderCode); + + if (vertexShader != 0 && fragmentShader != 0) { + blurShaderProgram = GLES20.glCreateProgram(); + GLES20.glAttachShader(blurShaderProgram, vertexShader); + GLES20.glAttachShader(blurShaderProgram, fragmentShader); + GLES20.glBindAttribLocation(blurShaderProgram, 0, "position"); + GLES20.glBindAttribLocation(blurShaderProgram, 1, "inputTexCoord"); + + GLES20.glLinkProgram(blurShaderProgram); + int[] linkStatus = new int[1]; + GLES20.glGetProgramiv(blurShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0); + if (linkStatus[0] == 0) { + GLES20.glDeleteProgram(blurShaderProgram); + blurShaderProgram = 0; + } else { + blurPositionHandle = GLES20.glGetAttribLocation(blurShaderProgram, "position"); + blurInputTexCoordHandle = GLES20.glGetAttribLocation(blurShaderProgram, "inputTexCoord"); + blurSourceImageHandle = GLES20.glGetUniformLocation(blurShaderProgram, "sourceImage"); + blurWidthHandle = GLES20.glGetUniformLocation(blurShaderProgram, "texelWidthOffset"); + blurHeightHandle = GLES20.glGetUniformLocation(blurShaderProgram, "texelHeightOffset"); + } + } else { + finish(); + return false; + } + + vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexShaderCode); + fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, linearBlurFragmentShaderCode); + + if (vertexShader != 0 && fragmentShader != 0) { + linearBlurShaderProgram = GLES20.glCreateProgram(); + GLES20.glAttachShader(linearBlurShaderProgram, vertexShader); + GLES20.glAttachShader(linearBlurShaderProgram, fragmentShader); + GLES20.glBindAttribLocation(linearBlurShaderProgram, 0, "position"); + GLES20.glBindAttribLocation(linearBlurShaderProgram, 1, "inputTexCoord"); + + GLES20.glLinkProgram(linearBlurShaderProgram); + int[] linkStatus = new int[1]; + GLES20.glGetProgramiv(linearBlurShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0); + if (linkStatus[0] == 0) { + GLES20.glDeleteProgram(linearBlurShaderProgram); + linearBlurShaderProgram = 0; + } else { + linearBlurPositionHandle = GLES20.glGetAttribLocation(linearBlurShaderProgram, "position"); + linearBlurInputTexCoordHandle = GLES20.glGetAttribLocation(linearBlurShaderProgram, "inputTexCoord"); + linearBlurSourceImageHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "sourceImage"); + linearBlurSourceImage2Handle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "inputImageTexture2"); + linearBlurExcludeSizeHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "excludeSize"); + linearBlurExcludePointHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "excludePoint"); + linearBlurExcludeBlurSizeHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "excludeBlurSize"); + linearBlurAngleHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "angle"); + linearBlurAspectRatioHandle = GLES20.glGetUniformLocation(linearBlurShaderProgram, "aspectRatio"); + } + } else { + finish(); + return false; + } + + vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexShaderCode); + fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, radialBlurFragmentShaderCode); + + if (vertexShader != 0 && fragmentShader != 0) { + radialBlurShaderProgram = GLES20.glCreateProgram(); + GLES20.glAttachShader(radialBlurShaderProgram, vertexShader); + GLES20.glAttachShader(radialBlurShaderProgram, fragmentShader); + GLES20.glBindAttribLocation(radialBlurShaderProgram, 0, "position"); + GLES20.glBindAttribLocation(radialBlurShaderProgram, 1, "inputTexCoord"); + + GLES20.glLinkProgram(radialBlurShaderProgram); + int[] linkStatus = new int[1]; + GLES20.glGetProgramiv(radialBlurShaderProgram, GLES20.GL_LINK_STATUS, linkStatus, 0); + if (linkStatus[0] == 0) { + GLES20.glDeleteProgram(radialBlurShaderProgram); + radialBlurShaderProgram = 0; + } else { + radialBlurPositionHandle = GLES20.glGetAttribLocation(radialBlurShaderProgram, "position"); + radialBlurInputTexCoordHandle = GLES20.glGetAttribLocation(radialBlurShaderProgram, "inputTexCoord"); + radialBlurSourceImageHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "sourceImage"); + radialBlurSourceImage2Handle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "inputImageTexture2"); + radialBlurExcludeSizeHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "excludeSize"); + radialBlurExcludePointHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "excludePoint"); + radialBlurExcludeBlurSizeHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "excludeBlurSize"); + radialBlurAspectRatioHandle = GLES20.glGetUniformLocation(radialBlurShaderProgram, "aspectRatio"); + } + } else { + finish(); + return false; + } + vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, simpleVertexShaderCode); fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, rgbToHsvFragmentShaderCode); if (vertexShader != 0 && fragmentShader != 0) { @@ -728,6 +931,205 @@ public class PhotoFilterView extends FrameLayout { } } + private void drawEnhancePass() { + if (!hsvGenerated) { + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0); + GLES20.glClear(0); + + GLES20.glUseProgram(rgbToHsvShaderProgram); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]); + GLES20.glUniform1i(rgbToHsvSourceImageHandle, 0); + GLES20.glEnableVertexAttribArray(rgbToHsvInputTexCoordHandle); + GLES20.glVertexAttribPointer(rgbToHsvInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); + GLES20.glEnableVertexAttribArray(rgbToHsvPositionHandle); + GLES20.glVertexAttribPointer(rgbToHsvPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + + ByteBuffer hsvBuffer = ByteBuffer.allocateDirect(renderBufferWidth * renderBufferHeight * 4); + GLES20.glReadPixels(0, 0, renderBufferWidth, renderBufferHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, hsvBuffer); + + GLES20.glBindTexture(GL10.GL_TEXTURE_2D, enhanceTextures[0]); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, renderBufferWidth, renderBufferHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, hsvBuffer); + + ByteBuffer buffer = null; + try { + buffer = ByteBuffer.allocateDirect(PGPhotoEnhanceSegments * PGPhotoEnhanceSegments * PGPhotoEnhanceHistogramBins * 4); + Utilities.calcCDT(hsvBuffer, renderBufferWidth, renderBufferHeight, buffer); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + + GLES20.glBindTexture(GL10.GL_TEXTURE_2D, enhanceTextures[1]); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 256, 16, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer); + + hsvGenerated = true; + } + + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[1]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[1], 0); + GLES20.glClear(0); + + GLES20.glUseProgram(enhanceShaderProgram); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, enhanceTextures[0]); + GLES20.glUniform1i(enhanceSourceImageHandle, 0); + GLES20.glActiveTexture(GLES20.GL_TEXTURE1); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, enhanceTextures[1]); + GLES20.glUniform1i(enhanceInputImageTexture2Handle, 1); + if (showOriginal) { + GLES20.glUniform1f(enhanceIntensityHandle, 0); + } else { + GLES20.glUniform1f(enhanceIntensityHandle, getEnhanceValue()); + } + + GLES20.glEnableVertexAttribArray(enhanceInputTexCoordHandle); + GLES20.glVertexAttribPointer(enhanceInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); + GLES20.glEnableVertexAttribArray(enhancePositionHandle); + GLES20.glVertexAttribPointer(enhancePositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + } + + private void drawSharpenPass() { + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0); + GLES20.glClear(0); + + GLES20.glUseProgram(sharpenShaderProgram); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]); + GLES20.glUniform1i(sharpenSourceImageHandle, 0); + if (showOriginal) { + GLES20.glUniform1f(sharpenHandle, 0); + } else { + GLES20.glUniform1f(sharpenHandle, getSharpenValue()); + } + GLES20.glUniform1f(sharpenWidthHandle, renderBufferWidth); + GLES20.glUniform1f(sharpenHeightHandle, renderBufferHeight); + GLES20.glEnableVertexAttribArray(sharpenInputTexCoordHandle); + GLES20.glVertexAttribPointer(sharpenInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); + GLES20.glEnableVertexAttribArray(sharpenPositionHandle); + GLES20.glVertexAttribPointer(sharpenPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + } + + private void drawCustomParamsPass() { + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[1]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[1], 0); + GLES20.glClear(0); + + GLES20.glUseProgram(toolsShaderProgram); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[0]); + GLES20.glUniform1i(sourceImageHandle, 0); + if (showOriginal) { + GLES20.glUniform1f(shadowsHandle, 0); + GLES20.glUniform1f(highlightsHandle, 1); + GLES20.glUniform1f(exposureHandle, 0); + GLES20.glUniform1f(contrastHandle, 1); + GLES20.glUniform1f(saturationHandle, 1); + GLES20.glUniform1f(warmthHandle, 0); + GLES20.glUniform1f(vignetteHandle, 0); + GLES20.glUniform1f(grainHandle, 0); + } else { + GLES20.glUniform1f(shadowsHandle, getShadowsValue()); + GLES20.glUniform1f(highlightsHandle, getHighlightsValue()); + GLES20.glUniform1f(exposureHandle, getExposureValue()); + GLES20.glUniform1f(contrastHandle, getContrastValue()); + GLES20.glUniform1f(saturationHandle, getSaturationValue()); + GLES20.glUniform1f(warmthHandle, getWarmthValue()); + GLES20.glUniform1f(vignetteHandle, getVignetteValue()); + GLES20.glUniform1f(grainHandle, getGrainValue()); + } + GLES20.glUniform1f(widthHandle, renderBufferWidth); + GLES20.glUniform1f(heightHandle, renderBufferHeight); + GLES20.glEnableVertexAttribArray(inputTexCoordHandle); + GLES20.glVertexAttribPointer(inputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); + GLES20.glEnableVertexAttribArray(positionHandle); + GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + } + + private boolean drawBlurPass() { + if (showOriginal || blurType == 0) { + return false; + } + if (needUpdateBlurTexture) { + GLES20.glUseProgram(blurShaderProgram); + GLES20.glUniform1i(blurSourceImageHandle, 0); + GLES20.glEnableVertexAttribArray(blurInputTexCoordHandle); + GLES20.glVertexAttribPointer(blurInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); + GLES20.glEnableVertexAttribArray(blurPositionHandle); + GLES20.glVertexAttribPointer(blurPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer); + + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0); + GLES20.glClear(0); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]); + GLES20.glUniform1f(blurWidthHandle, 0.0f); + GLES20.glUniform1f(blurHeightHandle, 1.0f / renderBufferHeight); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[2]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[2], 0); + GLES20.glClear(0); + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[0]); + GLES20.glUniform1f(blurWidthHandle, 1.0f / renderBufferWidth); + GLES20.glUniform1f(blurHeightHandle, 0.0f); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + needUpdateBlurTexture = false; + } + + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0); + GLES20.glClear(0); + if (blurType == 1) { + GLES20.glUseProgram(radialBlurShaderProgram); + GLES20.glUniform1i(radialBlurSourceImageHandle, 0); + GLES20.glUniform1i(radialBlurSourceImage2Handle, 1); + GLES20.glUniform1f(radialBlurExcludeSizeHandle, blurExcludeSize); + GLES20.glUniform1f(radialBlurExcludeBlurSizeHandle, blurExcludeBlurSize); + GLES20.glUniform2f(radialBlurExcludePointHandle, blurExcludePoint.x, blurExcludePoint.y); + GLES20.glUniform1f(radialBlurAspectRatioHandle, (float) renderBufferHeight / (float) renderBufferWidth); + GLES20.glEnableVertexAttribArray(radialBlurInputTexCoordHandle); + GLES20.glVertexAttribPointer(radialBlurInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); + GLES20.glEnableVertexAttribArray(radialBlurPositionHandle); + GLES20.glVertexAttribPointer(radialBlurPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer); + } else if (blurType == 2) { + GLES20.glUseProgram(linearBlurShaderProgram); + GLES20.glUniform1i(linearBlurSourceImageHandle, 0); + GLES20.glUniform1i(linearBlurSourceImage2Handle, 1); + GLES20.glUniform1f(linearBlurExcludeSizeHandle, blurExcludeSize); + GLES20.glUniform1f(linearBlurExcludeBlurSizeHandle, blurExcludeBlurSize); + GLES20.glUniform1f(linearBlurAngleHandle, blurAngle); + GLES20.glUniform2f(linearBlurExcludePointHandle, blurExcludePoint.x, blurExcludePoint.y); + GLES20.glUniform1f(linearBlurAspectRatioHandle, (float) renderBufferHeight / (float) renderBufferWidth); + GLES20.glEnableVertexAttribArray(linearBlurInputTexCoordHandle); + GLES20.glVertexAttribPointer(linearBlurInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); + GLES20.glEnableVertexAttribArray(linearBlurPositionHandle); + GLES20.glVertexAttribPointer(linearBlurPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer); + } + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]); + GLES20.glActiveTexture(GLES20.GL_TEXTURE1); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[2]); + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + + return true; + } + private Runnable drawRunnable = new Runnable() { @Override public void run() { @@ -743,130 +1145,10 @@ public class PhotoFilterView extends FrameLayout { } GLES20.glViewport(0, 0, renderBufferWidth, renderBufferHeight); - //enhance draw - if (!hsvGenerated) { - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]); - GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0); - GLES20.glClear(0); - - GLES20.glUseProgram(rgbToHsvShaderProgram); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]); - GLES20.glUniform1i(rgbToHsvSourceImageHandle, 0); - GLES20.glEnableVertexAttribArray(rgbToHsvInputTexCoordHandle); - GLES20.glVertexAttribPointer(rgbToHsvInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); - GLES20.glEnableVertexAttribArray(rgbToHsvPositionHandle); - GLES20.glVertexAttribPointer(rgbToHsvPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); - - ByteBuffer hsvBuffer = ByteBuffer.allocateDirect(renderBufferWidth * renderBufferHeight * 4); - GLES20.glReadPixels(0, 0, renderBufferWidth, renderBufferHeight, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, hsvBuffer); - - GLES20.glBindTexture(GL10.GL_TEXTURE_2D, enhanceTextures[0]); - GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); - GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); - GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); - GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, renderBufferWidth, renderBufferHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, hsvBuffer); - - ByteBuffer buffer = null; - try { - buffer = ByteBuffer.allocateDirect(PGPhotoEnhanceSegments * PGPhotoEnhanceSegments * PGPhotoEnhanceHistogramBins * 4); - Utilities.calcCDT(hsvBuffer, renderBufferWidth, renderBufferHeight, buffer); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - - GLES20.glBindTexture(GL10.GL_TEXTURE_2D, enhanceTextures[1]); - GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); - GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); - GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); - GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 256, 16, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer); - - hsvGenerated = true; - } - - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[1]); - GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[1], 0); - GLES20.glClear(0); - - GLES20.glUseProgram(enhanceShaderProgram); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, enhanceTextures[0]); - GLES20.glUniform1i(enhanceSourceImageHandle, 0); - GLES20.glActiveTexture(GLES20.GL_TEXTURE1); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, enhanceTextures[1]); - GLES20.glUniform1i(enhanceInputImageTexture2Handle, 1); - if (showOriginal) { - GLES20.glUniform1f(enhanceIntensityHandle, 0); - } else { - GLES20.glUniform1f(enhanceIntensityHandle, getEnhanceValue()); - } - - GLES20.glEnableVertexAttribArray(enhanceInputTexCoordHandle); - GLES20.glVertexAttribPointer(enhanceInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); - GLES20.glEnableVertexAttribArray(enhancePositionHandle); - GLES20.glVertexAttribPointer(enhancePositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); - - //sharpen draw - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[0]); - GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[0], 0); - GLES20.glClear(0); - - GLES20.glUseProgram(sharpenShaderProgram); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]); - GLES20.glUniform1i(sharpenSourceImageHandle, 0); - if (showOriginal) { - GLES20.glUniform1f(sharpenHandle, 0); - } else { - GLES20.glUniform1f(sharpenHandle, getSharpenValue()); - } - GLES20.glUniform1f(sharpenWidthHandle, renderBufferWidth); - GLES20.glUniform1f(sharpenHeightHandle, renderBufferHeight); - GLES20.glEnableVertexAttribArray(sharpenInputTexCoordHandle); - GLES20.glVertexAttribPointer(sharpenInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); - GLES20.glEnableVertexAttribArray(sharpenPositionHandle); - GLES20.glVertexAttribPointer(sharpenPositionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); - - //custom params draw - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[1]); - GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[1], 0); - GLES20.glClear(0); - - GLES20.glUseProgram(toolsShaderProgram); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[0]); - GLES20.glUniform1i(sourceImageHandle, 0); - if (showOriginal) { - GLES20.glUniform1f(shadowsHandle, 0); - GLES20.glUniform1f(highlightsHandle, 1); - GLES20.glUniform1f(exposureHandle, 0); - GLES20.glUniform1f(contrastHandle, 1); - GLES20.glUniform1f(saturationHandle, 1); - GLES20.glUniform1f(warmthHandle, 0); - GLES20.glUniform1f(vignetteHandle, 0); - GLES20.glUniform1f(grainHandle, 0); - } else { - GLES20.glUniform1f(shadowsHandle, getShadowsValue()); - GLES20.glUniform1f(highlightsHandle, getHighlightsValue()); - GLES20.glUniform1f(exposureHandle, getExposureValue()); - GLES20.glUniform1f(contrastHandle, getContrastValue()); - GLES20.glUniform1f(saturationHandle, getSaturationValue()); - GLES20.glUniform1f(warmthHandle, getWarmthValue()); - GLES20.glUniform1f(vignetteHandle, getVignetteValue()); - GLES20.glUniform1f(grainHandle, getGrainValue()); - } - GLES20.glUniform1f(widthHandle, renderBufferWidth); - GLES20.glUniform1f(heightHandle, renderBufferHeight); - GLES20.glEnableVertexAttribArray(inputTexCoordHandle); - GLES20.glVertexAttribPointer(inputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); - GLES20.glEnableVertexAttribArray(positionHandle); - GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 8, vertexInvertBuffer); - GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + drawEnhancePass(); + drawSharpenPass(); + drawCustomParamsPass(); + blured = drawBlurPass(); //onscreen draw GLES20.glViewport(0, 0, surfaceWidth, surfaceHeight); @@ -875,7 +1157,7 @@ public class PhotoFilterView extends FrameLayout { GLES20.glUseProgram(simpleShaderProgram); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[1]); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[blured ? 0 : 1]); GLES20.glUniform1i(simpleSourceImageHandle, 0); GLES20.glEnableVertexAttribArray(simpleInputTexCoordHandle); GLES20.glVertexAttribPointer(simpleInputTexCoordHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer); @@ -905,7 +1187,7 @@ public class PhotoFilterView extends FrameLayout { @Override public void run() { GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, renderFrameBuffer[1]); - GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[1], 0); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, renderTexture[blured ? 0 : 1], 0); GLES20.glClear(0); object[0] = getRenderBufferBitmap(); semaphore.release(); @@ -973,8 +1255,8 @@ public class PhotoFilterView extends FrameLayout { currentBitmap = createBitmap(bitmap, renderBufferWidth, renderBufferHeight, scale); } - GLES20.glGenFramebuffers(2, renderFrameBuffer, 0); - GLES20.glGenTextures(2, renderTexture, 0); + GLES20.glGenFramebuffers(3, renderFrameBuffer, 0); + GLES20.glGenTextures(3, renderTexture, 0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[0]); GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); @@ -989,6 +1271,13 @@ public class PhotoFilterView extends FrameLayout { GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, currentBitmap, 0); + + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTexture[2]); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, renderBufferWidth, renderBufferHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); } public void shutdown() { @@ -1016,9 +1305,17 @@ public class PhotoFilterView extends FrameLayout { super.run(); } - public void requestRender() { - cancelRunnable(drawRunnable); - postRunnable(drawRunnable); + public void requestRender(final boolean updateBlur) { + postRunnable(new Runnable() { + @Override + public void run() { + if (!needUpdateBlurTexture) { + needUpdateBlurTexture = updateBlur; + } + cancelRunnable(drawRunnable); + postRunnable(drawRunnable); + } + }); } } @@ -1046,7 +1343,7 @@ public class PhotoFilterView extends FrameLayout { if (eglThread == null && surface != null) { eglThread = new EGLThread(surface, bitmapToEdit); eglThread.setSurfaceTextureSize(width, height); - eglThread.requestRender(); + eglThread.requestRender(true); } } @@ -1054,11 +1351,11 @@ public class PhotoFilterView extends FrameLayout { public void onSurfaceTextureSizeChanged(SurfaceTexture surface, final int width, final int height) { if (eglThread != null) { eglThread.setSurfaceTextureSize(width, height); - eglThread.requestRender(); + eglThread.requestRender(false); eglThread.postRunnable(new Runnable() { @Override public void run() { - eglThread.requestRender(); + eglThread.requestRender(false); } }); } @@ -1079,6 +1376,27 @@ public class PhotoFilterView extends FrameLayout { } }); + blurControl = new PhotoFilterBlurControl(context); + blurControl.setVisibility(INVISIBLE); + addView(blurControl); + layoutParams = (LayoutParams) blurControl.getLayoutParams(); + layoutParams.width = LayoutParams.MATCH_PARENT; + layoutParams.height = LayoutParams.MATCH_PARENT; + layoutParams.gravity = Gravity.LEFT | Gravity.TOP; + blurControl.setLayoutParams(layoutParams); + blurControl.setDelegate(new PhotoFilterBlurControl.PhotoFilterLinearBlurControlDelegate() { + @Override + public void valueChanged(Point centerPoint, float falloff, float size, float angle) { + blurExcludeSize = size; + blurExcludePoint = centerPoint; + blurExcludeBlurSize = falloff; + blurAngle = angle; + if (eglThread != null) { + eglThread.requestRender(false); + } + } + }); + toolsView = new FrameLayout(context); addView(toolsView); layoutParams = (LayoutParams) toolsView.getLayoutParams(); @@ -1186,7 +1504,7 @@ public class PhotoFilterView extends FrameLayout { valueSeekBar.setMinMax(0, 100); paramTextView.setText(LocaleController.getString("Sharpen", R.string.Sharpen)); } else if (i == blurTool) { - + previousValue = blurType; } valueSeekBar.setProgress((int) previousValue, false); updateValueTextView(); @@ -1245,9 +1563,11 @@ public class PhotoFilterView extends FrameLayout { grainValue = previousValue; } else if (selectedTool == sharpenTool) { sharpenValue = previousValue; + } else if (selectedTool == blurTool) { + blurType = (int) previousValue; } if (eglThread != null) { - eglThread.requestRender(); + eglThread.requestRender(selectedTool != blurTool); } switchToOrFromEditMode(); } @@ -1271,6 +1591,18 @@ public class PhotoFilterView extends FrameLayout { } }); + blurTextView = new TextView(context); + blurTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + blurTextView.setTextColor(0xffffffff); + blurTextView.setText(LocaleController.getString("Blur", R.string.Blur)); + frameLayout.addView(blurTextView); + layoutParams = (LayoutParams) blurTextView.getLayoutParams(); + layoutParams.width = LayoutParams.WRAP_CONTENT; + layoutParams.height = LayoutParams.WRAP_CONTENT; + layoutParams.gravity = Gravity.CENTER_HORIZONTAL; + layoutParams.topMargin = AndroidUtilities.dp(9); + blurTextView.setLayoutParams(layoutParams); + paramTextView = new TextView(context); paramTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); paramTextView.setTextColor(0xff808080); @@ -1321,12 +1653,12 @@ public class PhotoFilterView extends FrameLayout { } updateValueTextView(); if (eglThread != null) { - eglThread.requestRender(); + eglThread.requestRender(true); } } }); editView.addView(valueSeekBar); - layoutParams = (FrameLayout.LayoutParams) valueSeekBar.getLayoutParams(); + layoutParams = (LayoutParams) valueSeekBar.getLayoutParams(); layoutParams.height = AndroidUtilities.dp(60); layoutParams.leftMargin = AndroidUtilities.dp(14); layoutParams.rightMargin = AndroidUtilities.dp(14); @@ -1339,6 +1671,113 @@ public class PhotoFilterView extends FrameLayout { layoutParams.gravity = Gravity.LEFT | Gravity.TOP; } valueSeekBar.setLayoutParams(layoutParams); + + blurLayout = new FrameLayout(context); + editView.addView(blurLayout); + layoutParams = (LayoutParams) blurLayout.getLayoutParams(); + layoutParams.width = AndroidUtilities.dp(280); + layoutParams.height = AndroidUtilities.dp(60); + layoutParams.topMargin = AndroidUtilities.dp(10); + layoutParams.gravity = Gravity.CENTER_HORIZONTAL; + blurLayout.setLayoutParams(layoutParams); + + blurOffButton = new TextView(context); + blurOffButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_off_active, 0, 0); + blurOffButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + blurOffButton.setTextColor(0xff51bdf3); + blurOffButton.setGravity(Gravity.CENTER_HORIZONTAL); + blurOffButton.setText(LocaleController.getString("BlurOff", R.string.BlurOff)); + blurLayout.addView(blurOffButton); + layoutParams = (LayoutParams) blurOffButton.getLayoutParams(); + layoutParams.width = AndroidUtilities.dp(80); + layoutParams.height = AndroidUtilities.dp(60); + blurOffButton.setLayoutParams(layoutParams); + blurOffButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + blurType = 0; + updateSelectedBlurType(); + blurControl.setVisibility(INVISIBLE); + if (eglThread != null) { + eglThread.requestRender(false); + } + } + }); + + blurRadialButton = new TextView(context); + blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_radial, 0, 0); + blurRadialButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + blurRadialButton.setTextColor(0xffffffff); + blurRadialButton.setGravity(Gravity.CENTER_HORIZONTAL); + blurRadialButton.setText(LocaleController.getString("BlurRadial", R.string.BlurRadial)); + blurLayout.addView(blurRadialButton); + layoutParams = (LayoutParams) blurRadialButton.getLayoutParams(); + layoutParams.width = AndroidUtilities.dp(80); + layoutParams.height = AndroidUtilities.dp(60); + layoutParams.leftMargin = AndroidUtilities.dp(100); + blurRadialButton.setLayoutParams(layoutParams); + blurRadialButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + blurType = 1; + updateSelectedBlurType(); + blurControl.setVisibility(VISIBLE); + blurControl.setType(1); + if (eglThread != null) { + eglThread.requestRender(false); + } + } + }); + + blurLinearButton = new TextView(context); + blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_linear, 0, 0); + blurLinearButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + blurLinearButton.setTextColor(0xffffffff); + blurLinearButton.setGravity(Gravity.CENTER_HORIZONTAL); + blurLinearButton.setText(LocaleController.getString("BlurLinear", R.string.BlurLinear)); + blurLayout.addView(blurLinearButton); + layoutParams = (LayoutParams) blurLinearButton.getLayoutParams(); + layoutParams.width = AndroidUtilities.dp(80); + layoutParams.height = AndroidUtilities.dp(60); + layoutParams.leftMargin = AndroidUtilities.dp(200); + blurLinearButton.setLayoutParams(layoutParams); + blurLinearButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + blurType = 2; + updateSelectedBlurType(); + blurControl.setVisibility(VISIBLE); + blurControl.setType(0); + if (eglThread != null) { + eglThread.requestRender(false); + } + } + }); + } + + private void updateSelectedBlurType() { + if (blurType == 0) { + blurOffButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_off_active, 0, 0); + blurOffButton.setTextColor(0xff51bdf3); + blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_radial, 0, 0); + blurRadialButton.setTextColor(0xffffffff); + blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_linear, 0, 0); + blurLinearButton.setTextColor(0xffffffff); + } else if (blurType == 1) { + blurOffButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_off, 0, 0); + blurOffButton.setTextColor(0xffffffff); + blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_radial_active, 0, 0); + blurRadialButton.setTextColor(0xff51bdf3); + blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_linear, 0, 0); + blurLinearButton.setTextColor(0xffffffff); + } else if (blurType == 2) { + blurOffButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_off, 0, 0); + blurOffButton.setTextColor(0xffffffff); + blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_radial, 0, 0); + blurRadialButton.setTextColor(0xffffffff); + blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_linear_active, 0, 0); + blurLinearButton.setTextColor(0xff51bdf3); + } } private void updateValueTextView() { @@ -1387,13 +1826,13 @@ public class PhotoFilterView extends FrameLayout { } } - public void setShowOriginal(boolean value) { + private void setShowOriginal(boolean value) { if (showOriginal == value) { return; } showOriginal = value; if (eglThread != null) { - eglThread.requestRender(); + eglThread.requestRender(false); } } @@ -1403,10 +1842,30 @@ public class PhotoFilterView extends FrameLayout { if (editView.getVisibility() == GONE) { viewFrom = toolsView; viewTo = editView; + + if (selectedTool == blurTool) { + blurLayout.setVisibility(VISIBLE); + valueSeekBar.setVisibility(INVISIBLE); + blurTextView.setVisibility(VISIBLE); + paramTextView.setVisibility(INVISIBLE); + valueTextView.setVisibility(INVISIBLE); + if (blurType != 0) { + blurControl.setVisibility(VISIBLE); + } + updateSelectedBlurType(); + } else { + blurLayout.setVisibility(INVISIBLE); + valueSeekBar.setVisibility(VISIBLE); + blurTextView.setVisibility(INVISIBLE); + paramTextView.setVisibility(VISIBLE); + valueTextView.setVisibility(VISIBLE); + blurControl.setVisibility(INVISIBLE); + } } else { selectedTool = -1; viewFrom = editView; viewTo = toolsView; + blurControl.setVisibility(INVISIBLE); } AnimatorSetProxy animatorSet = new AnimatorSetProxy(); @@ -1495,6 +1954,11 @@ public class PhotoFilterView extends FrameLayout { layoutParams.height = (int) bitmapH; textureView.setLayoutParams(layoutParams); + blurControl.setActualAreaSize(layoutParams.width, layoutParams.height); + layoutParams = (LayoutParams) blurControl.getLayoutParams(); + layoutParams.height = viewHeight + AndroidUtilities.dp(28); + blurControl.setLayoutParams(layoutParams); + if (AndroidUtilities.isTablet()) { int total = AndroidUtilities.dp(86) * 10; layoutParams = (FrameLayout.LayoutParams) recyclerListView.getLayoutParams(); @@ -1613,7 +2077,7 @@ public class PhotoFilterView extends FrameLayout { @Override public int getItemCount() { - return 10; + return 11; } @Override @@ -1651,7 +2115,13 @@ public class PhotoFilterView extends FrameLayout { } else if (i == sharpenTool) { ((PhotoEditToolCell) holder.itemView).setIconAndTextAndValue(R.drawable.tool_details, LocaleController.getString("Sharpen", R.string.Sharpen), sharpenValue); } else if (i == blurTool) { - ((PhotoEditToolCell) holder.itemView).setIconAndTextAndValue(R.drawable.tool_details, LocaleController.getString("Blur", R.string.Blur), 0); //TODO add value + String value = ""; + if (blurType == 1) { + value = "R"; + } else if (blurType == 2) { + value = "L"; + } + ((PhotoEditToolCell) holder.itemView).setIconAndTextAndValue(R.drawable.tool_blur, LocaleController.getString("Blur", R.string.Blur), value); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterRadialBlurControl.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java similarity index 61% rename from TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterRadialBlurControl.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java index 1dd438fb0..f22dde478 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterRadialBlurControl.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Point.java @@ -8,5 +8,16 @@ package org.telegram.ui.Components; -public class PhotoFilterRadialBlurControl { +public class Point { + public float x; + public float y; + + public Point() { + + } + + public Point(float x, float y) { + this.x = x; + this.y = y; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java new file mode 100644 index 000000000..9dde354b9 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Rect.java @@ -0,0 +1,23 @@ +/* + * This is the source code of Telegram for Android v. 2.x + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +public class Rect { + public float x; + public float y; + public float width; + public float height; + + public Rect(float x, float y, float width, float height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index 9ef873436..08eea19d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -18,7 +18,7 @@ import android.view.View; public class RecyclerListView extends RecyclerView { public interface OnItemClickListener { - public void onItemClick(View view, int position); + void onItemClick(View view, int position); } public static class RecyclerListViewItemClickListener implements RecyclerView.OnItemTouchListener { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java index 8efc59c26..bc15136a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java @@ -19,8 +19,8 @@ import org.telegram.messenger.R; public class SeekBar { - public abstract interface SeekBarDelegate { - public void onSeekBarDrag(float progress); + public interface SeekBarDelegate { + void onSeekBarDrag(float progress); } private static Drawable thumbDrawable1; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java new file mode 100644 index 000000000..986c40703 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Size.java @@ -0,0 +1,23 @@ +/* + * This is the source code of Telegram for Android v. 2.x + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +public class Size { + public float width; + public float height; + + public Size() { + + } + + public Size(float width, float height) { + this.width = width; + this.height = height; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierRelativeLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierRelativeLayout.java index 61e685895..c2278bec5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierRelativeLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierRelativeLayout.java @@ -8,6 +8,7 @@ package org.telegram.ui.Components; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; @@ -26,8 +27,8 @@ public class SizeNotifierRelativeLayout extends RelativeLayout { private int keyboardHeight; private SizeNotifierRelativeLayoutDelegate delegate; - public abstract interface SizeNotifierRelativeLayoutDelegate { - public abstract void onSizeChanged(int keyboardHeight); + public interface SizeNotifierRelativeLayoutDelegate { + void onSizeChanged(int keyboardHeight); } public SizeNotifierRelativeLayout(Context context) { @@ -62,16 +63,24 @@ public class SizeNotifierRelativeLayout extends RelativeLayout { this.delegate = delegate; } + @SuppressLint("DrawAllocation") @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - if (delegate != null) { + if (changed && delegate != null) { View rootView = this.getRootView(); int usableViewHeight = rootView.getHeight() - AndroidUtilities.statusBarHeight - AndroidUtilities.getViewInset(rootView); this.getWindowVisibleDisplayFrame(rect); keyboardHeight = usableViewHeight - (rect.bottom - rect.top); - delegate.onSizeChanged(keyboardHeight); + post(new Runnable() { + @Override + public void run() { + if (delegate != null) { + delegate.onSizeChanged(keyboardHeight); + } + } + }); } + super.onLayout(changed, l, t, r, b); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java index 52c56e803..4c01ff275 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlidingTabView.java @@ -25,8 +25,8 @@ import org.telegram.messenger.R; public class SlidingTabView extends LinearLayout { - public static interface SlidingTabViewDelegate { - public abstract void didSelectTab(int tab); + public interface SlidingTabViewDelegate { + void didSelectTab(int tab); } private SlidingTabViewDelegate delegate; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java index c62ed5062..e97168ed5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekBarView.java @@ -30,8 +30,8 @@ public class VideoSeekBarView extends View { private boolean pressed = false; public SeekBarDelegate delegate; - public abstract interface SeekBarDelegate { - public void onSeekBarDrag(float progress); + public interface SeekBarDelegate { + void onSeekBarDrag(float progress); } private void init(Context context) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java index 33740781a..74da7e49f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java @@ -48,9 +48,9 @@ public class VideoTimelineView extends View { private int framesToLoad = 0; private Drawable pickDrawable = null; - public abstract interface VideoTimelineViewDelegate { - public void onLeftProgressChanged(float progress); - public void onRifhtProgressChanged(float progress); + public interface VideoTimelineViewDelegate { + void onLeftProgressChanged(float progress); + void onRifhtProgressChanged(float progress); } private void init(Context context) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index b41814bdd..288690a30 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -74,6 +74,9 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent @Override public void onFragmentDestroy() { super.onFragmentDestroy(); + if (avatarImage != null) { + avatarImage.setImageDrawable(null); + } NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index 6720dce7b..3dff4d25a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -73,8 +73,8 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter private boolean allowUsernameSearch = true; private ContactsActivityDelegate delegate; - public static interface ContactsActivityDelegate { - public abstract void didSelectContact(TLRPC.User user, String param); + public interface ContactsActivityDelegate { + void didSelectContact(TLRPC.User user, String param); } public ContactsActivity(Bundle args) { @@ -154,7 +154,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter } @Override - public void onSearchCollapse() { + public boolean onSearchCollapse() { searchListViewAdapter.searchDialogs(null); searching = false; searchWas = false; @@ -166,6 +166,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter listView.setFastScrollEnabled(true); listView.setVerticalScrollBarEnabled(false); emptyTextView.setText(LocaleController.getString("NoContacts", R.string.NoContacts)); + return true; } @Override @@ -416,13 +417,13 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter editText.setInputType(InputType.TYPE_CLASS_NUMBER); editText.setImeOptions(EditorInfo.IME_ACTION_DONE); builder.setView(editText); - builder.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() { + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { didSelectResult(user, false, editText.getText().toString()); } }); - builder.setNegativeButton(R.string.Cancel, null); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showAlertDialog(builder); ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)editText.getLayoutParams(); if (layoutParams != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java index 3b48f411e..414f93456 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java @@ -36,8 +36,8 @@ import org.telegram.ui.Components.LetterSectionsListView; public class CountrySelectActivity extends BaseFragment { - public static interface CountrySelectActivityDelegate { - public abstract void didSelectCountry(String name); + public interface CountrySelectActivityDelegate { + void didSelectCountry(String name); } private LetterSectionsListView listView; @@ -84,7 +84,7 @@ public class CountrySelectActivity extends BaseFragment { } @Override - public void onSearchCollapse() { + public boolean onSearchCollapse() { searchListViewAdapter.search(null); searching = false; searchWas = false; @@ -96,6 +96,8 @@ public class CountrySelectActivity extends BaseFragment { listView.setVerticalScrollBarEnabled(false); emptyTextView.setText(LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); + + return true; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java index b2229753d..1d7cc0920 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java @@ -51,9 +51,9 @@ import java.util.HashMap; public class DocumentSelectActivity extends BaseFragment { - public static abstract interface DocumentSelectActivityDelegate { - public void didSelectFiles(DocumentSelectActivity activity, ArrayList files); - public void startDocumentSelectActivity(); + public interface DocumentSelectActivityDelegate { + void didSelectFiles(DocumentSelectActivity activity, ArrayList files); + void startDocumentSelectActivity(); } private ListView listView; @@ -487,7 +487,7 @@ public class DocumentSelectActivity extends BaseFragment { if (getParentActivity() == null) { return; } - new AlertDialog.Builder(getParentActivity()).setTitle(LocaleController.getString("AppName", R.string.AppName)).setMessage(error).setPositiveButton(R.string.OK, null).show(); + new AlertDialog.Builder(getParentActivity()).setTitle(LocaleController.getString("AppName", R.string.AppName)).setMessage(error).setPositiveButton(LocaleController.getString("OK", R.string.OK), null).show(); } private void listRoots() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 02ee365c1..38d2ae1f2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -61,8 +61,8 @@ import java.util.HashMap; public class GroupCreateActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { - public static interface GroupCreateActivityDelegate { - public abstract void didSelectUsers(ArrayList ids); + public interface GroupCreateActivityDelegate { + void didSelectUsers(ArrayList ids); } private class XImageSpan extends ImageSpan { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index e73f58576..0ff48eb81 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -78,7 +78,7 @@ public class LanguageSelectActivity extends BaseFragment { } @Override - public void onSearchCollapse() { + public boolean onSearchCollapse() { search(null); searching = false; searchWas = false; @@ -86,6 +86,8 @@ public class LanguageSelectActivity extends BaseFragment { emptyTextView.setVisibility(View.GONE); listView.setAdapter(listAdapter); } + + return true; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java index a80b2d774..db8badfc5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java @@ -40,8 +40,8 @@ import java.util.ArrayList; public class LastSeenUsersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { - public static interface LastSeenUsersActivityDelegate { - public abstract void didUpdatedUserList(ArrayList ids, boolean added); + public interface LastSeenUsersActivityDelegate { + void didUpdatedUserList(ArrayList ids, boolean added); } private ListView listView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 2355535fb..02994fb49 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -345,14 +345,14 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (actionBarLayout.fragmentsStack.isEmpty()) { if (!UserConfig.isClientActivated() && !UserConfig.isWaitingForPasswordEnter()) { actionBarLayout.addFragmentToStack(new LoginActivity()); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } else { if (UserConfig.isWaitingForPasswordEnter()) { actionBarLayout.addFragmentToStack(new AccountPasswordActivity(1)); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } else { actionBarLayout.addFragmentToStack(new MessagesActivity(null)); - drawerLayoutContainer.setAllowOpenDrawer(true); + drawerLayoutContainer.setAllowOpenDrawer(true, false); } } @@ -414,7 +414,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (actionBarLayout.fragmentsStack.size() == 1 && (actionBarLayout.fragmentsStack.get(0) instanceof LoginActivity || actionBarLayout.fragmentsStack.get(0) instanceof AccountPasswordActivity)) { allowOpen = false; } - drawerLayoutContainer.setAllowOpenDrawer(allowOpen); + drawerLayoutContainer.setAllowOpenDrawer(allowOpen, false); } handleIntent(getIntent(), false, savedInstanceState != null, false); @@ -431,7 +431,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } passcodeView.onShow(); UserConfig.isWaitingForPasscodeEnter = true; - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); passcodeView.setDelegate(new PasscodeView.PasscodeViewDelegate() { @Override public void didAcceptedPassword() { @@ -440,7 +440,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa handleIntent(passcodeSaveIntent, passcodeSaveIntentIsNew, passcodeSaveIntentIsRestore, true); passcodeSaveIntent = null; } - drawerLayoutContainer.setAllowOpenDrawer(true); + drawerLayoutContainer.setAllowOpenDrawer(true, false); actionBarLayout.showLastFragment(); if (AndroidUtilities.isTablet()) { layersActionBarLayout.showLastFragment(); @@ -847,10 +847,10 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa actionBarLayout.showLastFragment(); rightActionBarLayout.showLastFragment(); } - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } else if (open_settings != 0) { actionBarLayout.presentFragment(new SettingsActivity(), false, true, true); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); if (AndroidUtilities.isTablet()) { actionBarLayout.showLastFragment(); rightActionBarLayout.showLastFragment(); @@ -863,16 +863,16 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (!UserConfig.isClientActivated() && !UserConfig.isWaitingForPasswordEnter()) { if (layersActionBarLayout.fragmentsStack.isEmpty()) { layersActionBarLayout.addFragmentToStack(new LoginActivity()); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } } else { if (actionBarLayout.fragmentsStack.isEmpty()) { if (UserConfig.isWaitingForPasswordEnter()) { layersActionBarLayout.addFragmentToStack(new AccountPasswordActivity(1)); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } else { actionBarLayout.addFragmentToStack(new MessagesActivity(null)); - drawerLayoutContainer.setAllowOpenDrawer(true); + drawerLayoutContainer.setAllowOpenDrawer(true, false); } } } @@ -880,14 +880,14 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa if (actionBarLayout.fragmentsStack.isEmpty()) { if (!UserConfig.isClientActivated() && !UserConfig.isWaitingForPasswordEnter()) { actionBarLayout.addFragmentToStack(new LoginActivity()); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } else { if (UserConfig.isWaitingForPasswordEnter()) { actionBarLayout.addFragmentToStack(new AccountPasswordActivity(1)); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } else { actionBarLayout.addFragmentToStack(new MessagesActivity(null)); - drawerLayoutContainer.setAllowOpenDrawer(true); + drawerLayoutContainer.setAllowOpenDrawer(true, false); } } } @@ -954,7 +954,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } else { actionBarLayout.presentFragment(fragment, true); - SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id); + SendMessagesHelper.prepareSendingVideo(videoPath, 0, 0, 0, 0, null, dialog_id, null); } } else { actionBarLayout.presentFragment(fragment, true); @@ -963,14 +963,14 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa fragment.processSendingText(sendingText); } if (photoPathsArray != null) { - SendMessagesHelper.prepareSendingPhotos(null, photoPathsArray, dialog_id); + SendMessagesHelper.prepareSendingPhotos(null, photoPathsArray, dialog_id, null); } if (documentsPathsArray != null || documentsUrisArray != null) { - SendMessagesHelper.prepareSendingDocuments(documentsPathsArray, documentsOriginalPathsArray, documentsUrisArray, documentsMimeType, dialog_id); + SendMessagesHelper.prepareSendingDocuments(documentsPathsArray, documentsOriginalPathsArray, documentsUrisArray, documentsMimeType, dialog_id, null); } if (contactsToSend != null && !contactsToSend.isEmpty()) { for (TLRPC.User user : contactsToSend) { - SendMessagesHelper.getInstance().sendMessage(user, dialog_id); + SendMessagesHelper.getInstance().sendMessage(user, dialog_id, null); } } } @@ -1227,14 +1227,14 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa rightActionBarLayout.closeLastFragment(false); actionBarLayout.closeLastFragment(false); layersActionBarLayout.presentFragment(new AccountPasswordActivity(1), false, true, true); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } else { for (int a = 0; a < actionBarLayout.fragmentsStack.size() - 1; a++) { actionBarLayout.removeFragmentFromStack(actionBarLayout.fragmentsStack.get(0)); a--; } actionBarLayout.presentFragment(new AccountPasswordActivity(1), true); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, false); } } else if (id == NotificationCenter.screenStateChanged) { if (!ApplicationLoader.mainInterfacePaused) { @@ -1448,15 +1448,15 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override public boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout) { if (AndroidUtilities.isTablet()) { - drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof AccountPasswordActivity) && !(fragment instanceof LoginActivity) && layersActionBarLayout.getVisibility() != View.VISIBLE); + drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof AccountPasswordActivity) && !(fragment instanceof LoginActivity) && layersActionBarLayout.getVisibility() != View.VISIBLE, true); if (fragment instanceof MessagesActivity) { MessagesActivity messagesActivity = (MessagesActivity)fragment; - if (messagesActivity.getDelegate() == null && layout != actionBarLayout) { + if (messagesActivity.isMainDialogList() && layout != actionBarLayout) { actionBarLayout.removeAllFragments(); actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, false); layersActionBarLayout.removeAllFragments(); layersActionBarLayout.setVisibility(View.GONE); - drawerLayoutContainer.setAllowOpenDrawer(true); + drawerLayoutContainer.setAllowOpenDrawer(true, false); if (!tabletFullSize) { shadowTabletSide.setVisibility(View.VISIBLE); if (rightActionBarLayout.fragmentsStack.isEmpty()) { @@ -1516,7 +1516,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } else if (layout != layersActionBarLayout) { layersActionBarLayout.setVisibility(View.VISIBLE); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, true); if (fragment instanceof LoginActivity || fragment instanceof AccountPasswordActivity) { backgroundTablet.setVisibility(View.VISIBLE); shadowTabletSide.setVisibility(View.GONE); @@ -1529,7 +1529,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } return true; } else { - drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity) && !(fragment instanceof AccountPasswordActivity)); + drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity) && !(fragment instanceof AccountPasswordActivity), false); return true; } } @@ -1537,15 +1537,15 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa @Override public boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout) { if (AndroidUtilities.isTablet()) { - drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity) && !(fragment instanceof AccountPasswordActivity) && layersActionBarLayout.getVisibility() != View.VISIBLE); + drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity) && !(fragment instanceof AccountPasswordActivity) && layersActionBarLayout.getVisibility() != View.VISIBLE, true); if (fragment instanceof MessagesActivity) { MessagesActivity messagesActivity = (MessagesActivity)fragment; - if (messagesActivity.getDelegate() == null && layout != actionBarLayout) { + if (messagesActivity.isMainDialogList() && layout != actionBarLayout) { actionBarLayout.removeAllFragments(); actionBarLayout.addFragmentToStack(fragment); layersActionBarLayout.removeAllFragments(); layersActionBarLayout.setVisibility(View.GONE); - drawerLayoutContainer.setAllowOpenDrawer(true); + drawerLayoutContainer.setAllowOpenDrawer(true, false); if (!tabletFullSize) { shadowTabletSide.setVisibility(View.VISIBLE); if (rightActionBarLayout.fragmentsStack.isEmpty()) { @@ -1581,7 +1581,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } else if (layout != layersActionBarLayout) { layersActionBarLayout.setVisibility(View.VISIBLE); - drawerLayoutContainer.setAllowOpenDrawer(false); + drawerLayoutContainer.setAllowOpenDrawer(false, true); if (fragment instanceof LoginActivity || fragment instanceof AccountPasswordActivity) { backgroundTablet.setVisibility(View.VISIBLE); shadowTabletSide.setVisibility(View.GONE); @@ -1594,7 +1594,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } return true; } else { - drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity) && !(fragment instanceof AccountPasswordActivity)); + drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity) && !(fragment instanceof AccountPasswordActivity), false); return true; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index c3efdf404..e9c476fee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -65,8 +65,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private final static int map_list_menu_satellite = 3; private final static int map_list_menu_hybrid = 4; - public static interface LocationActivityDelegate { - public abstract void didSelectLocation(double latitude, double longitude); + public interface LocationActivityDelegate { + void didSelectLocation(double latitude, double longitude); } @Override @@ -88,6 +88,9 @@ public class LocationActivity extends BaseFragment implements NotificationCenter if (mapView != null) { mapView.onDestroy(); } + if (avatarImageView != null) { + avatarImageView.setImageDrawable(null); + } } @Override @@ -268,7 +271,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private void updateUserData() { if (messageObject != null && avatarImageView != null) { int fromId = messageObject.messageOwner.from_id; - if (messageObject.messageOwner instanceof TLRPC.TL_messageForwarded) { + if (messageObject.isForwarded()) { fromId = messageObject.messageOwner.fwd_from_id; } TLRPC.User user = MessagesController.getInstance().getUser(fromId); @@ -279,6 +282,8 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } avatarImageView.setImage(photo, null, new AvatarDrawable(user)); nameTextView.setText(ContactsController.formatName(user.first_name, user.last_name)); + } else { + avatarImageView.setImageDrawable(null); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index 4b328481e..a34f7e354 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -41,7 +41,6 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.android.MessagesController; -import org.telegram.android.SendMessagesHelper; import org.telegram.android.query.SharedMediaQuery; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ConnectionsManager; @@ -118,7 +117,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No private int max_id; public boolean addMessage(MessageObject messageObject, boolean isNew, boolean enc) { - if (messagesDict.containsKey(messageObject.messageOwner.id)) { + if (messagesDict.containsKey(messageObject.getId())) { return false; } ArrayList messageObjects = sectionArrays.get(messageObject.monthKey); @@ -138,13 +137,13 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No messageObjects.add(messageObject); messages.add(messageObject); } - messagesDict.put(messageObject.messageOwner.id, messageObject); + messagesDict.put(messageObject.getId(), messageObject); if (!enc) { - if (messageObject.messageOwner.id > 0) { - max_id = Math.min(messageObject.messageOwner.id, max_id); + if (messageObject.getId() > 0) { + max_id = Math.min(messageObject.getId(), max_id); } } else { - max_id = Math.max(messageObject.messageOwner.id, max_id); + max_id = Math.max(messageObject.getId(), max_id); } return true; } @@ -160,7 +159,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } messageObjects.remove(messageObject); messages.remove(messageObject); - messagesDict.remove(messageObject.messageOwner.id); + messagesDict.remove(messageObject.getId()); if (messageObjects.isEmpty()) { sectionArrays.remove(messageObject.monthKey); sections.remove(messageObject.monthKey); @@ -285,8 +284,6 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putBoolean("serverOnly", true); - args.putString("selectAlertString", LocaleController.getString("ForwardMessagesTo", R.string.ForwardMessagesTo)); - args.putString("selectAlertStringGroup", LocaleController.getString("ForwardMessagesToGroup", R.string.ForwardMessagesToGroup)); MessagesActivity fragment = new MessagesActivity(args); fragment.setDelegate(new MessagesActivity.MessagesActivityDelegate() { @Override @@ -301,11 +298,12 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No args.putInt("chat_id", -lower_part); } + ArrayList fmessages = new ArrayList<>(); ArrayList ids = new ArrayList<>(selectedFiles.keySet()); Collections.sort(ids); for (Integer id : ids) { if (id > 0) { - SendMessagesHelper.getInstance().sendMessage(selectedFiles.get(id), did); + fmessages.add(selectedFiles.get(id)); } } selectedFiles.clear(); @@ -314,6 +312,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); ChatActivity chatActivity = new ChatActivity(args); presentFragment(chatActivity, true); + chatActivity.showReplyForMessageObjectOrForward(true, null, fmessages, false); if (!AndroidUtilities.isTablet()) { removeSelfFromStack(); @@ -347,12 +346,14 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } @Override - public void onSearchCollapse() { + public boolean onSearchCollapse() { dropDownContainer.setVisibility(View.VISIBLE); documentsSearchAdapter.searchDocuments(null); searching = false; searchWas = false; switchToCurrentSelectedMode(); + + return true; } @Override @@ -734,7 +735,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No break; } BackupImageView imageView = cell.getImageView(i); - if (message.messageOwner.id == messageObject.messageOwner.id) { + if (message.getId() == messageObject.getId()) { int coords[] = new int[2]; imageView.getLocationInWindow(coords); PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); @@ -836,7 +837,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (actionBar.isActionModeShowed()) { return false; } - selectedFiles.put(item.messageOwner.id, item); + selectedFiles.put(item.getId(), item); selectedMessagesCountTextView.setText(String.format("%d", selectedFiles.size())); if (Build.VERSION.SDK_INT >= 11) { AnimatorSetProxy animatorSet = new AnimatorSetProxy(); @@ -869,10 +870,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No return; } if (actionBar.isActionModeShowed()) { - if (selectedFiles.containsKey(message.messageOwner.id)) { - selectedFiles.remove(message.messageOwner.id); + if (selectedFiles.containsKey(message.getId())) { + selectedFiles.remove(message.getId()); } else { - selectedFiles.put(message.messageOwner.id, message); + selectedFiles.put(message.getId(), message); } if (selectedFiles.isEmpty()) { actionBar.hideActionMode(); @@ -881,9 +882,9 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } scrolling = false; if (view instanceof SharedDocumentCell) { - ((SharedDocumentCell) view).setChecked(selectedFiles.containsKey(message.messageOwner.id), true); + ((SharedDocumentCell) view).setChecked(selectedFiles.containsKey(message.getId()), true); } else if (view instanceof SharedPhotoVideoCell) { - ((SharedPhotoVideoCell) view).setChecked(a, selectedFiles.containsKey(message.messageOwner.id), true); + ((SharedPhotoVideoCell) view).setChecked(a, selectedFiles.containsKey(message.getId()), true); } } else { if (selectedMode == 0) { @@ -1056,7 +1057,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No MessageObject messageObject = messageObjects.get(position - 1); sharedDocumentCell.setDocument(messageObject, position != messageObjects.size() || section == sharedMediaData[1].sections.size() - 1 && sharedMediaData[1].loading); if (actionBar.isActionModeShowed()) { - sharedDocumentCell.setChecked(selectedFiles.containsKey(messageObject.messageOwner.id), !scrolling); + sharedDocumentCell.setChecked(selectedFiles.containsKey(messageObject.getId()), !scrolling); } else { sharedDocumentCell.setChecked(false, !scrolling); } @@ -1176,7 +1177,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No cell.setItem(a, sharedMediaData[0].messages.indexOf(messageObject), messageObject); if (actionBar.isActionModeShowed()) { - cell.setChecked(a, selectedFiles.containsKey(messageObject.messageOwner.id), !scrolling); + cell.setChecked(a, selectedFiles.containsKey(messageObject.getId()), !scrolling); } else { cell.setChecked(a, false, !scrolling); } @@ -1184,6 +1185,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No cell.setItem(a, index, null); } } + cell.requestLayout(); } } else { if (convertView == null) { @@ -1317,7 +1319,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No public void run() { if (!sharedMediaData[1].messages.isEmpty()) { MessageObject messageObject = sharedMediaData[1].messages.get(sharedMediaData[1].messages.size() - 1); - queryServerSearch(query, messageObject.messageOwner.id); + queryServerSearch(query, messageObject.getId()); } final ArrayList copy = new ArrayList<>(); copy.addAll(sharedMediaData[1].messages); @@ -1431,7 +1433,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No MessageObject messageObject = getItem(i); sharedDocumentCell.setDocument(messageObject, i != getCount() - 1); if (actionBar.isActionModeShowed()) { - sharedDocumentCell.setChecked(selectedFiles.containsKey(messageObject.messageOwner.id), !scrolling); + sharedDocumentCell.setChecked(selectedFiles.containsKey(messageObject.getId()), !scrolling); } else { sharedDocumentCell.setChecked(false, !scrolling); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java index 21bba0e4d..a504bbd4a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java @@ -83,6 +83,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter private boolean searchWas = false; private boolean onlySelect = false; private long selectedDialog; + private String searchString; private MessagesActivityDelegate delegate; @@ -90,8 +91,8 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter private static final int passcode_menu_item = 1; - public static interface MessagesActivityDelegate { - public abstract void didSelectDialog(MessagesActivity fragment, long dialog_id, boolean param); + public interface MessagesActivityDelegate { + void didSelectDialog(MessagesActivity fragment, long dialog_id, boolean param); } public MessagesActivity(Bundle args) { @@ -101,18 +102,6 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter @Override public boolean onFragmentCreate() { super.onFragmentCreate(); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.dialogsNeedReload); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.emojiDidLoaded); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.updateInterfaces); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatUpdated); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.contactsDidLoaded); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.appDidLogout); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.openedChatChanged); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.notificationsSettingsUpdated); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.messageReceivedByAck); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.messageReceivedByServer); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.messageSendError); - NotificationCenter.getInstance().addObserver(this, NotificationCenter.didSetPasscode); if (getArguments() != null) { onlySelect = arguments.getBoolean("onlySelect", false); @@ -120,6 +109,23 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter selectAlertString = arguments.getString("selectAlertString"); selectAlertStringGroup = arguments.getString("selectAlertStringGroup"); } + + if (searchString == null) { + NotificationCenter.getInstance().addObserver(this, NotificationCenter.dialogsNeedReload); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.emojiDidLoaded); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.updateInterfaces); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.encryptedChatUpdated); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.contactsDidLoaded); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.appDidLogout); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.openedChatChanged); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.notificationsSettingsUpdated); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.messageReceivedByAck); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.messageSendError); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.didSetPasscode); + } + + if (!dialogsLoaded) { MessagesController.getInstance().loadDialogs(0, 0, 100, true); ContactsController.getInstance().checkInviteText(); @@ -131,18 +137,20 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter @Override public void onFragmentDestroy() { super.onFragmentDestroy(); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.dialogsNeedReload); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.emojiDidLoaded); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.encryptedChatUpdated); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.contactsDidLoaded); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.appDidLogout); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.openedChatChanged); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.notificationsSettingsUpdated); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messageReceivedByAck); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messageReceivedByServer); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messageSendError); - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didSetPasscode); + if (searchString == null) { + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.dialogsNeedReload); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.emojiDidLoaded); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.encryptedChatUpdated); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.contactsDidLoaded); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.appDidLogout); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.openedChatChanged); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.notificationsSettingsUpdated); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messageReceivedByAck); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messageReceivedByServer); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.messageSendError); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.didSetPasscode); + } delegate = null; } @@ -153,7 +161,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter searchWas = false; ActionBarMenu menu = actionBar.createMenu(); - if (!onlySelect) { + if (!onlySelect && searchString == null) { passcodeItem = menu.addItem(passcode_menu_item, R.drawable.lock_close); updatePasscodeButton(); } @@ -162,9 +170,14 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter public void onSearchExpand() { searching = true; if (messagesListView != null) { - messagesListView.setEmptyView(searchEmptyView); + if (searchString != null) { + messagesListView.setEmptyView(progressView); + searchEmptyView.setVisibility(View.INVISIBLE); + } else { + messagesListView.setEmptyView(searchEmptyView); + progressView.setVisibility(View.INVISIBLE); + } emptyView.setVisibility(View.INVISIBLE); - progressView.setVisibility(View.INVISIBLE); if (!onlySelect) { floatingButton.setVisibility(View.GONE); } @@ -173,7 +186,11 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } @Override - public void onSearchCollapse() { + public boolean onSearchCollapse() { + if (searchString != null) { + finishFragment(); + return false; + } searching = false; searchWas = false; if (messagesListView != null) { @@ -202,6 +219,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter dialogsSearchAdapter.searchDialogs(null, false); } updatePasscodeButton(); + return true; } @Override @@ -229,7 +247,11 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setTitle(LocaleController.getString("SelectChat", R.string.SelectChat)); } else { - actionBar.setBackButtonDrawable(new MenuDrawable()); + if (searchString != null) { + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + } else { + actionBar.setBackButtonDrawable(new MenuDrawable()); + } actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName)); } actionBar.setAllowOverlayTitle(true); @@ -253,11 +275,19 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter fragmentView = inflater.inflate(R.layout.messages_list, null, false); - dialogsAdapter = new DialogsAdapter(getParentActivity(), serverOnly); - if (AndroidUtilities.isTablet() && openedDialogId != 0) { - dialogsAdapter.setOpenedDialogId(openedDialogId); + if (searchString == null) { + dialogsAdapter = new DialogsAdapter(getParentActivity(), serverOnly); + if (AndroidUtilities.isTablet() && openedDialogId != 0) { + dialogsAdapter.setOpenedDialogId(openedDialogId); + } } - dialogsSearchAdapter = new DialogsSearchAdapter(getParentActivity(), !onlySelect); + int type = 0; + if (searchString != null) { + type = 2; + } else if (!onlySelect) { + type = 1; + } + dialogsSearchAdapter = new DialogsSearchAdapter(getParentActivity(), type); dialogsSearchAdapter.setDelegate(new DialogsSearchAdapter.MessagesActivitySearchAdapterDelegate() { @Override public void searchStateChanged(boolean search) { @@ -270,13 +300,14 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter }); messagesListView = (ListView)fragmentView.findViewById(R.id.messages_list_view); - messagesListView.setAdapter(dialogsAdapter); + if (dialogsAdapter != null) { + messagesListView.setAdapter(dialogsAdapter); + } if (Build.VERSION.SDK_INT >= 11) { messagesListView.setVerticalScrollbarPosition(LocaleController.isRTL ? ListView.SCROLLBAR_POSITION_LEFT : ListView.SCROLLBAR_POSITION_RIGHT); } progressView = fragmentView.findViewById(R.id.progressLayout); - dialogsAdapter.notifyDataSetChanged(); searchEmptyView = fragmentView.findViewById(R.id.search_empty_view); searchEmptyView.setOnTouchListener(new View.OnTouchListener() { @Override @@ -296,7 +327,11 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter TextView textView = (TextView)fragmentView.findViewById(R.id.list_empty_view_text1); textView.setText(LocaleController.getString("NoChats", R.string.NoChats)); textView = (TextView)fragmentView.findViewById(R.id.list_empty_view_text2); - textView.setText(LocaleController.getString("NoChatsHelp", R.string.NoChatsHelp)); + String help = LocaleController.getString("NoChatsHelp", R.string.NoChatsHelp); + if (AndroidUtilities.isTablet() && !AndroidUtilities.isSmallTablet()) { + help = help.replace("\n", " "); + } + textView.setText(help); textView = (TextView)fragmentView.findViewById(R.id.search_empty_text); textView.setText(LocaleController.getString("NoResult", R.string.NoResult)); @@ -375,7 +410,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } else if (obj instanceof MessageObject) { MessageObject messageObject = (MessageObject)obj; dialog_id = messageObject.getDialogId(); - message_id = messageObject.messageOwner.id; + message_id = messageObject.getId(); } } @@ -413,10 +448,17 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter if (openedDialogId == dialog_id) { return; } - dialogsAdapter.setOpenedDialogId(openedDialogId = dialog_id); - updateVisibleRows(MessagesController.UPDATE_MASK_SELECT_DIALOG); + if (dialogsAdapter != null) { + dialogsAdapter.setOpenedDialogId(openedDialogId = dialog_id); + updateVisibleRows(MessagesController.UPDATE_MASK_SELECT_DIALOG); + } + } + if (searchString != null) { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); + presentFragment(new ChatActivity(args)); + } else { + presentFragment(new ChatActivity(args)); } - presentFragment(new ChatActivity(args)); } } }); @@ -533,6 +575,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } } }); + + if (searchString != null) { + actionBar.openSearchField(searchString); + } } else { ViewGroup parent = (ViewGroup)fragmentView.getParent(); if (parent != null) { @@ -703,8 +749,12 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter this.delegate = delegate; } - public MessagesActivityDelegate getDelegate() { - return delegate; + public void setSearchString(String string) { + searchString = string; + } + + public boolean isMainDialogList() { + return delegate == null && searchString == null; } private void didSelectResult(final long dialog_id, boolean useAlert, final boolean param) { @@ -754,13 +804,13 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter builder.setView(checkBox); }*/ final CheckBox checkBoxFinal = checkBox; - builder.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() { + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { didSelectResult(dialog_id, false, checkBoxFinal != null && checkBoxFinal.isChecked()); } }); - builder.setNegativeButton(R.string.Cancel, null); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showAlertDialog(builder); if (checkBox != null) { ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)checkBox.getLayoutParams(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index b35674fda..64d5befe8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -382,7 +382,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif listView.invalidateViews(); } }); - builder.setNeutralButton(LocaleController.getString("Disabled", R.string.Disabled), new DialogInterface.OnClickListener() { + builder.setNeutralButton(LocaleController.getString("LedDisabled", R.string.LedDisabled), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); @@ -427,7 +427,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("Vibrate", R.string.Vibrate)); builder.setItems(new CharSequence[] { - LocaleController.getString("Disabled", R.string.Disabled), + LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled), LocaleController.getString("Default", R.string.Default), LocaleController.getString("Short", R.string.Short), LocaleController.getString("Long", R.string.Long) @@ -484,7 +484,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("RepeatNotifications", R.string.RepeatNotifications)); builder.setItems(new CharSequence[] { - LocaleController.getString("ShortMessageLifetimeForever", R.string.ShortMessageLifetimeForever), + LocaleController.getString("RepeatDisabled", R.string.RepeatDisabled), LocaleController.formatPluralString("Minutes", 5), LocaleController.formatPluralString("Minutes", 10), LocaleController.formatPluralString("Minutes", 30), diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index 96c5cac9d..17f068e09 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -45,10 +45,9 @@ import java.util.HashMap; public class PhotoAlbumPickerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { - public static interface PhotoAlbumPickerActivityDelegate { - public abstract void didSelectPhotos(ArrayList photos); - public abstract void didSelectWebPhotos(ArrayList photos); - public abstract void startPhotoSelectActivity(); + public interface PhotoAlbumPickerActivityDelegate { + void didSelectPhotos(ArrayList photos, ArrayList webPhotos); + void startPhotoSelectActivity(); } private ArrayList albumsSorted = null; @@ -332,8 +331,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati MessagesStorage.getInstance().putWebRecent(recentGifImages); } - delegate.didSelectPhotos(photos); - delegate.didSelectWebPhotos(webPhotos); + delegate.didSelectPhotos(photos, webPhotos); } private void fixLayout() { @@ -466,6 +464,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati photoPickerAlbumsCell.setAlbum(a, null); } } + photoPickerAlbumsCell.requestLayout(); } else if (type == 1) { if (view == null) { view = new PhotoPickerSearchCell(mContext); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java index 26a04b4e0..43e856ee3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java @@ -36,7 +36,7 @@ import java.io.File; public class PhotoCropActivity extends BaseFragment { public interface PhotoEditActivityDelegate { - public abstract void didFinishEdit(Bitmap bitmap, Bundle args); + void didFinishEdit(Bitmap bitmap, Bundle args); } private class PhotoCropView extends FrameLayout { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index ccaef1c03..6d77c85b4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -67,9 +67,9 @@ import java.util.Map; public class PhotoPickerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, PhotoViewer.PhotoViewerProvider { - public static interface PhotoPickerActivityDelegate { - public abstract void selectedPhotosChanged(); - public abstract void actionButtonPressed(boolean canceled); + public interface PhotoPickerActivityDelegate { + void selectedPhotosChanged(); + void actionButtonPressed(boolean canceled); } private RequestQueue requestQueue; @@ -175,8 +175,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } @Override - public void onSearchCollapse() { + public boolean onSearchCollapse() { finishFragment(); + return false; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 4cf2e10aa..c44ed6e47 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -405,26 +405,26 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } - public static interface PhotoViewerProvider { - public PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index); + public interface PhotoViewerProvider { + PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index); - public Bitmap getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index); + Bitmap getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index); - public void willSwitchFromPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index); + void willSwitchFromPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index); - public void willHidePhotoViewer(); + void willHidePhotoViewer(); - public boolean isPhotoChecked(int index); + boolean isPhotoChecked(int index); - public void setPhotoChecked(int index); + void setPhotoChecked(int index); - public void cancelButtonPressed(); + void cancelButtonPressed(); - public void sendButtonPressed(int index); + void sendButtonPressed(int index); - public int getSelectedCount(); + int getSelectedCount(); - public void updatePhotoAtIndex(int index); + void updatePhotoAtIndex(int index); } private class FrameLayoutTouchListener extends FrameLayout { @@ -593,18 +593,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat int added = 0; for (MessageObject message : arr) { - if (!imagesByIdsTemp.containsKey(message.messageOwner.id)) { - imagesByIdsTemp.put(message.messageOwner.id, message); + if (!imagesByIdsTemp.containsKey(message.getId())) { + imagesByIdsTemp.put(message.getId(), message); if (opennedFromMedia) { imagesArrTemp.add(message); - if (message.messageOwner.id == currentMessage.messageOwner.id) { + if (message.getId() == currentMessage.getId()) { foundIndex = added; } added++; } else { added++; imagesArrTemp.add(0, message); - if (message.messageOwner.id == currentMessage.messageOwner.id) { + if (message.getId() == currentMessage.getId()) { foundIndex = arr.size() - added; } } @@ -631,23 +631,23 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (!cacheEndReached || !arr.isEmpty() && added != 0) { loadingMoreImages = true; if (opennedFromMedia) { - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, imagesArrTemp.get(imagesArrTemp.size() - 1).messageOwner.id, SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 100, imagesArrTemp.get(imagesArrTemp.size() - 1).getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); } else { - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, imagesArrTemp.get(0).messageOwner.id, SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 100, imagesArrTemp.get(0).getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, true, classGuid); } } } } else { int added = 0; for (MessageObject message : arr) { - if (!imagesByIds.containsKey(message.messageOwner.id)) { + if (!imagesByIds.containsKey(message.getId())) { added++; if (opennedFromMedia) { imagesArr.add(message); } else { imagesArr.add(0, message); } - imagesByIds.put(message.messageOwner.id, message); + imagesByIds.put(message.getId(), message); } } if (arr.isEmpty() && !fromCache) { @@ -740,7 +740,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setPositiveButton(R.string.OK, null); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(LocaleController.getString("PleaseDownload", R.string.PleaseDownload)); showAlertDialog(builder); } @@ -812,7 +812,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat MessageObject obj = imagesArr.get(currentIndex); if (obj.isSent()) { ArrayList arr = new ArrayList<>(); - arr.add(obj.messageOwner.id); + arr.add(obj.getId()); ArrayList random_ids = null; TLRPC.EncryptedChat encryptedChat = null; @@ -960,7 +960,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setPositiveButton(R.string.OK, null); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); builder.setMessage(LocaleController.getString("PleaseDownload", R.string.PleaseDownload)); showAlertDialog(builder); } @@ -1802,7 +1802,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imagesArr.add(messageObject); if (messageObject.messageOwner.action == null || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionEmpty) { needSearchImageInArr = true; - imagesByIds.put(messageObject.messageOwner.id, messageObject); + imagesByIds.put(messageObject.getId(), messageObject); if (messageObject.messageOwner.dialog_id != 0) { currentDialogId = messageObject.messageOwner.dialog_id; } else { @@ -1827,7 +1827,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imagesArrLocationsSizes.add(object.size); avatarsArr.add(new TLRPC.TL_photoEmpty()); bottomLayout.clearAnimation(); - bottomLayout.setVisibility(View.GONE); shareButton.setVisibility(View.VISIBLE); menuItem.hideSubItem(gallery_menu_showall); setImageIndex(0, true); @@ -1841,7 +1840,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat index = imagesArr.size() - index - 1; } for (MessageObject message : imagesArr) { - imagesByIds.put(message.messageOwner.id, message); + imagesByIds.put(message.getId(), message); } if (messageObject.messageOwner.dialog_id != 0) { @@ -1937,14 +1936,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (opennedFromMedia) { if (imagesArr.size() < totalImagesCount && !loadingMoreImages && currentIndex > imagesArr.size() - 5) { MessageObject lastMessage = imagesArr.get(imagesArr.size() - 1); - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, lastMessage.messageOwner.id, SharedMediaQuery.MEDIA_PHOTOVIDEO, !cacheEndReached, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 100, lastMessage.getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, !cacheEndReached, classGuid); loadingMoreImages = true; } actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, currentIndex + 1, totalImagesCount)); } else { if (imagesArr.size() < totalImagesCount && !loadingMoreImages && currentIndex < 5) { MessageObject lastMessage = imagesArr.get(0); - SharedMediaQuery.loadMedia(currentDialogId, 0, 100, lastMessage.messageOwner.id, SharedMediaQuery.MEDIA_PHOTOVIDEO, !cacheEndReached, classGuid); + SharedMediaQuery.loadMedia(currentDialogId, 0, 100, lastMessage.getId(), SharedMediaQuery.MEDIA_PHOTOVIDEO, !cacheEndReached, classGuid); loadingMoreImages = true; } actionBar.setTitle(LocaleController.formatString("Of", R.string.Of, (totalImagesCount - imagesArr.size()) + currentIndex + 1, totalImagesCount)); @@ -2258,7 +2257,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } public boolean isShowingImage(MessageObject object) { - return isVisible && !disableShowCheck && object != null && currentMessageObject != null && currentMessageObject.messageOwner.id == object.messageOwner.id; + return isVisible && !disableShowCheck && object != null && currentMessageObject != null && currentMessageObject.getId() == object.getId(); } public boolean isShowingImage(TLRPC.FileLocation object) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index 11c821ec0..ac1aeae09 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -185,7 +185,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC if (chatActivityEnterView != null) { chatActivityEnterView.onDestroy(); } - chatActivityEnterView = new ChatActivityEnterView(this, contentView, null, true); + chatActivityEnterView = new ChatActivityEnterView(this, contentView, null, false); popupContainer.addView(chatActivityEnterView); layoutParams3 = (RelativeLayout.LayoutParams) chatActivityEnterView.getLayoutParams(); layoutParams3.width = RelativeLayout.LayoutParams.MATCH_PARENT; @@ -201,7 +201,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC if (currentMessageNum >= 0 && currentMessageNum < NotificationsController.getInstance().popupMessages.size()) { NotificationsController.getInstance().popupMessages.remove(currentMessageNum); } - MessagesController.getInstance().markDialogAsRead(currentMessageObject.getDialogId(), currentMessageObject.messageOwner.id, Math.max(0, currentMessageObject.messageOwner.id), 0, currentMessageObject.messageOwner.date, true, true); + MessagesController.getInstance().markDialogAsRead(currentMessageObject.getDialogId(), currentMessageObject.getId(), Math.max(0, currentMessageObject.getId()), 0, currentMessageObject.messageOwner.date, true, true); currentMessageObject = null; getNewMessage(); } @@ -802,7 +802,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC boolean found = false; if ((currentMessageNum != 0 || chatActivityEnterView.hasText() || startedMoving) && currentMessageObject != null) { for (int a = 0; a < NotificationsController.getInstance().popupMessages.size(); a++) { - if (NotificationsController.getInstance().popupMessages.get(a).messageOwner.id == currentMessageObject.messageOwner.id) { + if (NotificationsController.getInstance().popupMessages.get(a).getId() == currentMessageObject.getId()) { currentMessageNum = a; found = true; break; @@ -1032,7 +1032,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC View view = messageContainer.getChildAt(a); if ((Integer)view.getTag() == 3) { PopupAudioView cell = (PopupAudioView)view.findViewWithTag(300); - if (cell.getMessageObject() != null && cell.getMessageObject().messageOwner.id == mid) { + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { cell.updateButtonState(); break; } @@ -1047,7 +1047,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC View view = messageContainer.getChildAt(a); if ((Integer)view.getTag() == 3) { PopupAudioView cell = (PopupAudioView)view.findViewWithTag(300); - if (cell.getMessageObject() != null && cell.getMessageObject().messageOwner.id == mid) { + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { cell.updateProgress(); break; } @@ -1079,6 +1079,9 @@ public class PopupNotificationActivity extends Activity implements NotificationC if (wakeLock.isHeld()) { wakeLock.release(); } + if (avatarImageView != null) { + avatarImageView.setImageDrawable(null); + } } protected void onFinish() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index ec241248f..f2cdcc351 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -208,6 +208,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override public void onFragmentDestroy() { super.onFragmentDestroy(); + if (avatarImage != null) { + avatarImage.setImageDrawable(null); + } NotificationCenter.getInstance().removeObserver(this, NotificationCenter.mediaCountDidLoaded); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeChats); @@ -1213,7 +1216,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. presentFragment(new ChatActivity(args), true); removeSelfFromStack(); TLRPC.User user = MessagesController.getInstance().getUser(user_id); - SendMessagesHelper.getInstance().sendMessage(user, dialog_id); + SendMessagesHelper.getInstance().sendMessage(user, dialog_id, null); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 9e30daadc..59514828c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -244,7 +244,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi listView.invalidateViews(); } }); - builder.setNeutralButton(LocaleController.getString("Disabled", R.string.Disabled), new DialogInterface.OnClickListener() { + builder.setNeutralButton(LocaleController.getString("LedDisabled", R.string.LedDisabled), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { final SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java index ef77d39e2..ee5928a7e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretPhotoViewer.java @@ -176,7 +176,7 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD return; } ArrayList markAsDeletedMessages = (ArrayList)args[0]; - if (markAsDeletedMessages.contains(currentMessageObject.messageOwner.id)) { + if (markAsDeletedMessages.contains(currentMessageObject.getId())) { closePhoto(); } } else if (id == NotificationCenter.didCreatedNewDeleteTask) { @@ -188,7 +188,7 @@ public class SecretPhotoViewer implements NotificationCenter.NotificationCenterD int key = mids.keyAt(i); ArrayList arr = mids.get(key); for (Integer mid : arr) { - if (currentMessageObject.messageOwner.id == mid) { + if (currentMessageObject.getId() == mid) { currentMessageObject.messageOwner.destroyTime = key; secretDeleteTimer.invalidate(); return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index a6c4ce3a8..a84164e86 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -254,6 +254,9 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter @Override public void onFragmentDestroy() { super.onFragmentDestroy(); + if (avatarImage != null) { + avatarImage.setImageDrawable(null); + } MessagesController.getInstance().cancelLoadFullUser(UserConfig.getClientUserId()); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.updateInterfaces); avatarUpdater.clear(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java index 3cf311d2b..440ee7616 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java @@ -43,6 +43,7 @@ import com.googlecode.mp4parser.util.Path; 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.FileLog; import org.telegram.messenger.R; @@ -57,7 +58,7 @@ import java.io.File; import java.util.List; @TargetApi(16) -public class VideoEditorActivity extends BaseFragment implements TextureView.SurfaceTextureListener { +public class VideoEditorActivity extends BaseFragment implements TextureView.SurfaceTextureListener, NotificationCenter.NotificationCenterDelegate { private boolean created = false; private MediaPlayer videoPlayer = null; @@ -97,7 +98,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur private long originalSize = 0; public interface VideoEditorActivityDelegate { - public abstract void didFinishEditVideo(String videoPath, long startTime, long endTime, int resultWidth, int resultHeight, int rotationValue, int originalWidth, int originalHeight, int bitrate, long estimatedSize, long estimatedDuration); + void didFinishEditVideo(String videoPath, long startTime, long endTime, int resultWidth, int resultHeight, int rotationValue, int originalWidth, int originalHeight, int bitrate, long estimatedSize, long estimatedDuration); } private Runnable progressRunnable = new Runnable() { @@ -198,6 +199,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur return false; } + NotificationCenter.getInstance().addObserver(this, NotificationCenter.closeChats); created = true; return super.onFragmentCreate(); @@ -217,6 +219,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur FileLog.e("tmessages", e); } } + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeChats); super.onFragmentDestroy(); } @@ -407,6 +410,13 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur return fragmentView; } + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.closeChats) { + removeSelfFromStack(); + } + } + private void setPlayerSurface() { if (textureView == null || !textureView.isAvailable() || videoPlayer == null) { return; diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png new file mode 100755 index 0000000000000000000000000000000000000000..7d255cf57f42b8a16c682eea0d5932041210cf24 GIT binary patch literal 974 zcmaJ=J#5oJ7}zAC_L=jAI2};b zp%M}U0wJ{<5;II}R8)+J1r`Q21~vo(EU=VwnxqT_%l6%OdhdO|cfVY^K0S4AisQIx zbJ?h{^+NKUIL`i`xt$%hoTW>3TE%O$V-v(JxVV9U>D%k5f^4^Y=Pk-}+$8jBby~M> zXb$#yJHha=A2K$_<>%wjc3Oyn23q$59e#hc4}s_Ea3y1jR#-qyZ+VlT>Sn3tY_^=7 z3+Jzbe5^46A5j~`{zedKu@3vX8rvtw0t9^sZRzkZsJc}K1xygg@Uv-0lq8_4yrg7Q zRk{LXQIZ9by=q!gw2Z3BSul7Y^G4h?tzr}hzL=%MCZ(Y!2%S!c@67U;tP4^umrFEc zIn5C1s2fl_P6ttHs9>PTAzny59Dqd8Zs0c6A&c}d1wS0g2GO8QtYAWHhl0e5NlHVY zW&I!O`y+HjE9fZRe+oynZis{mig24atZ{3p#8s#j2(l?AHH8#kpd3 z$ThIj_EA8GT=$5Z8Ou#Z!4H{d0}<~oa*G7}pr5kljgLhht2f}f<71f}%N1BKLekj3 z8a+H>)01pRW6O-u;G=*|J7HtJ{csnuE3s%A3$^&u*N<;ba^UpjwV7}Ggr1tY{q!L9 z>*b>drQK&Yd%fQ4$>-6B_pQfIwwclE?VZ2);~qCLF>&kNnN?2TI%e&C`T0A!VdhfF Jc(J&;^#_zzF-`yg literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_linear_active.png b/TMessagesProj/src/main/res/drawable-hdpi/blur_linear_active.png new file mode 100755 index 0000000000000000000000000000000000000000..9103cc6c20b632cea8580f4afabedf2b19de270d GIT binary patch literal 1004 zcmaJ=PiWIn9L^MU4#x`WK~Z>Q9;U4M*EBU@-PSejR$WGEE2{{yEO~3gmb@%^wOK(J ziU*lz*+~TN;z)l8G8`Szb8IIyi85hw4uInD8QYM;*AZP0pSb(~@vius3P}E-9 zDwT0rn^p{DGkS<&0^22QiW(UUT-{iN7|g?puv7^UMXMpk`aK$SO%!F?JP}t=H>JJ;orf z!t$~#hZ=$qC5WiM;$S_9I{si=L505ISuVDa142c89@TJ?CYkOW!FD^cj^8R1DHt2* zF3U4qc%(K^)BX>&?GD<<1-P5_dma5PhYw8r2gv7 z@y(ml!&{NcKyL($zZm$kfBV|6p5Dlvx8vtldnj4FxIx|i*$D4nE;FOvo0z-$2jw0< A-~a#s literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-hdpi/blur_off.png new file mode 100755 index 0000000000000000000000000000000000000000..172256dca3857ce245dc03c82e50073e2a3648bc GIT binary patch literal 1029 zcmaJ=O=#0l9FJD!+y@L#&VxKM4~jNv(l)hm-PSg(i!5Wdg%v?COWxM7B`+qgHmx3p z-wJvX+(|vD$WX+i2N6XOL{H8SP}oUDL2rJ6_|mnV2Wv?3{_pYo{r;ct?8Nw<-mcAE z6h-yQqf(BnTm7%IgZ!7Ng$1(o<4h6f(KN284y2Mgnu0(!)ft$Bs$MW+4VsaK^9_^p|`0X<+CHdNQhn6gv$|#%Rrf`Pz6v ztIcY0ogN+ngPuqPOo&zBnRAvadI`F&D-zp3W@%7|;MoMd5>!!{0BPhv5M{zaEyQs^ z5Ew2J6$EZ4;6ohGhR7=fxri7QL_P)@4^6x|`m~snvJGEkm!L}++ak+WDix*@W{@+( za`AZF*WmdeK?L2Zg;g(TxdTlF3A&nN*w{c8@D4cQ!YQQ6T*EY@$Msw2R@A9tLZCypYw&S1@CCg%uC7GL`^tM*TsaA;~E zB~OjZL51!;33_av2xt&Xz}6;oi?>5`NtY*k$IQ^61i|AWdMl{3I0&N1gdpJdxnvK^ z0*-UD{s70ZUBK&My^M#voQw7I0gm@}gYrWYZ>BQJCxv*~7deIKEXD@UF!_Amo%gws zImWQTV9?RsSddihM%1u%yc{A%tk6;8sBrF@HGX z<4#0;(Rd&b=OP}i!WEF5)1ZzkTxFXZugP^rK{JSF0h;OssKiaAfl|u6T053#O}#Q# zsU3?@lgp4`7^ks+G`eCU)8lNbV@nRz!G}7Tc9V?tmud3@xe|*BA)K;bWg6dXUY{=( zZyubH3+WkYvgUwwMHRh;{=_G!^>yY_j1 zCex;jya?ak)1G^F_fq_je|_mp{XC!j+ti}f7uT-5V?n&{*Ynpq!kZ6(^}ZO%Zh)qx t;L_gXa$)Xep>BCs{o{^%9V=%G)J_Vw?_2-5u`=u2-9&6aSdNTb{0&AOSqcCE literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png new file mode 100755 index 0000000000000000000000000000000000000000..0e4d1b76e004475947e7123c548b65e9f42b1f0d GIT binary patch literal 1485 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?+0o3=!rai@*#sEqhOQ<~M$S&ohUTWO1_n+R z#zqz}y)OC5rManjB{01y2)!0K^@5T@ZUN9{m(-%nveXo}qWoM1u$Qeeal6G7r+HAl zDY)HYhEuOT&@uX;h((HMm=G}afSB-P3*^8Perg^twHE=C^__&^UknUPj-D=#Ar-gI z%&_)mb`&_SFJ80AOtDO>tF_-NT37hWEv+bz4WIUP3+1@DaPM!qAuYP`>XHwQw^mNQ zC86@XK85d?;`BTBj#{(VZFrOX%zsn0wYBE;Qe9_hR_+8jpC-Wz=ab(*U<^6HX~Fj0 z?Ve`&Jgs)-**C0=|Ji?Viur*Yxd5(^Ipqj}c*p-~O;Xy>jHMy};v*>yn;sQIL-5=3Hto@;ESP ze#;h-5P|0Pg611ex=mlcUV-&wew%Q!1i$-{rTV*E?{n^&o#)tL|bn0jMDdF z%#THC0y{L1Ya9~}6niA*abeDk4arCIjh@MH&JvRi=j7NW_EuBKM8#^JkiZv(TgqEj z+FyL}q)#uPJ5u22zb9p9xBZ)Wb52>+wfPNgb{GF`xVlf$%i+R?4EtME)72GTT-V(G zv-H8t$qfs5FX~;^ly-jn%sy7O{J|CX!a4iT-Rz&n_VT#5&rA1hk-sK}<*z?0!IEq0 zePNPc;^#Wge~wI^|MtB!&RE-uco7R_!N~`>2t51|zed@A^>ja&Mxl&?lV&XOnZAqBQ z6?rN8(WHAU%lVmYzPV|#toXFFHYMuPZ?Oc1^V^^5%kRDs2`XScUHx3vIVCg!0GLK6 At^fc4 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_radial_active.png b/TMessagesProj/src/main/res/drawable-hdpi/blur_radial_active.png new file mode 100755 index 0000000000000000000000000000000000000000..73725eea927cd311ecaadf45f08d8bdb4bc3bb3f GIT binary patch literal 1707 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?+1$z8%+b}-*#sEqhOQ=-#?H>JrfyEghUVsu zE-q#;y)OC5rManjB{01y2)&Lt^@5T@ZUN9{m(-%nveXo}qWoM1u$Qeeal6GFr+HAl zDY)HYfm5$O&@uX;h((HMm=G}afSB-P3*^8Perg^twHE=C^(wcklYzNK-qXb~q~g|@ z8NMDNfg;E6+jKi^>GiXotdNlvCaPq5Rf%m)YqwFCmw*nB{X(;g%Q7C@xpS);Gx4h2 z-oY_5E714Rp|IMWCpMJTyr(LC=bUZ){y=pG!+ayl>XIcnXMeWIxK3#ZUcmf@z0u^a)`_?R zzBNsr7r5OHdTnzk<4aoffLDT%-KfJemGPdjll;XRmRz>K3Vcq-wz6cf{B}^i;i7f( z+6lW`PG7G2-(SbVda(GyqFZ8)*6%0&H0FtGR{hYdvoUu@ZO*;TEB#poOo%7n>__oB|5pO>9tcf5V&WBTnmPwhCOK2N*7 zhEFE@vtz(&zuw$wTIXKL6wW*%{^+t`;OcKJ9J5&0U()ziRH7ER_^j3X+WET*m~*~5 z_)OR+^ZM$`c9BB)3Z12AMEO}_Q+2vGx^GojsbL-Z{Pcqw!J{4Ty+tImvwUtWt?4alTj=_vaO)f4^4n8*dr~3t?73{{V-pX+|B+L`u z(Y{Y+vcy-3xlePZzGkxESr!_tUc7W$>6+lRd&2vVm?Y~wiMs90RL8+1@qbgl<%Tuy z(htbx?axsW&6%A2{h|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?+07UXoy{$c3=LgPoXkxPT`e6Q4UNqWjGT>( zVR~KilS^|`^GaZPQ{Z|{3~=fNC57Aqpv^9+MVV!(DQ-pixe8z}TV>*QiwjQkpn6kq zy2aQPr(S)aWAs50ixkl?AzEaktaqG>D zk9=(M&sv-QfzxQ~yp>m~m}=X?-iylK-fEa8SNEe``$nEd^W)=<-wn4Kx~*NA zl9j5;sJh@ki&R^p_p*zg898aSI!rEoS*zZqq_dnl6mT_4{!5J4->)G_PeLPS@OwCy zo%(#|OpE4@lYO@@{$Q6{s2=%z&+Uv@CnZy+#XtUX=1aOiI?-phbkc%-2UuLgZJhZ+ zo;#W*2N)V0jF+@tWxL{1dsnL<|JM_*O#LegX04Yol;t*-_Gq}Y(LmtBk!vd=BqFRb z7K!Iy&h?yeUobrJbXG{3!h%l!-H}XM(Hzf?TvIY)X7u#rpDOvqPGm~s^HV%k^0QRg z7Xn2W-g@E?Yr7(>X_C?w#oNlB{l7!xLJrzJ{C%PMe2b&e2H};`zgMit{nWH<%{0$z y-~UeYY5(%q$ZoTp)2~-wHY);yp`N*l+khc5%sSxv5>ru7VdLrQ=d#Wzp$P!6Ij&Uz literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/forward_blue.png b/TMessagesProj/src/main/res/drawable-hdpi/forward_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..36d5c85d6809b56fdc981b97db63a6b31a7c8947 GIT binary patch literal 1220 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFso#SM3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcp$o0y!L2NKW( z>+top^2{qPNz6-5^>ndS0-B+hnVDkcZ0u&@Y-r$WX>MR)Xy|HUVeD#PX>4p{VPfj) zWa4N9)9aF-T$-DjR|38Iua(|ZvxVdw1dD`Q|_H1l+E45_%4 z^ymM7`@;!LK0M7lJysbfEIV3*n7PDakEvc|I}+OR#lPe7(rAuQrb2xIW4>h?+DwmD zF0ts6%hV9=c+P0}Il=1+r^B9>87AK6W5gJbtZtZ*YmoZeK_QO+$eiYtGM|_popm^4 zJA=zDUEv<%k(w7mJqvEhMeN`WnOe`)VcXF9`1iq}(iw~&;}RM=_?GQDBhbOmAggLA zv4}_V4pY+fgCVz9Gk!dD@X3PN4l?JBJY5nV)$h{{_SOY|d9ViibEce_VbrV0tcdD~~|EG|$x6RvE%ijwfW)=`cSk zQ21vmA(gSftW-weza)?Ejh7B{n2yx5J1fgy(Lb%Wh+{!_b5!Gw7LnrtOA};d|4Mx1 cW8yGixO>+p^t#;%B~ZEI>FVdQ&MBb@0OVDcdjJ3c literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_fwd_forward.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_fwd_forward.png index cfa12ce2580039c6c5114fecc5595e355564a8ca..bbe96ec85f3d9adaee41e05fbbb4a070b8fa10e8 100755 GIT binary patch delta 540 zcmey)b%1k&8&iydnSqIcfrX*7xuubzp{t3bnT3V3xq*wDtFgJOv6-ooLPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|2$$Z;iAAD(6&9xL{Z7Y<#RG-=XB4P~}1yk_j7OojRa z#(c{(w3!~QTw>8Bm#HD#@to1{bAs0uPKP}$Gh%$t$A~c=S=}%r*C6$`gF+ntkvYvP zWj--II_q$zck7a6OG1`1STKL&Q~1XA$p41Z3;TLr1H}a9BfA?T3JgMJ(;W7Qcet_# z$EI-{VQ+{iG6-E472tl7Z`rLl-VSj-HTJtKk1D1)KAMqzVbO!52^eok{Sx zqP|e^GuvL@vmVT+IYj%~8*i}hU6QuMbw5v(>_cOT5Q$%mAGaS2*qPVdb_Ph_Uf*oy zSjW@$?0Aro0w4RM_~wO;Y+1p_89&ZHc%fx3-w{oRKjj7{pB(>g%2B%QZc-kgy@EyI qsNt5f0A9;k67KA4+GaH~F!3;m%=GDXYnE_h00K`}KbLh*2~7YE!oYa| delta 725 zcmX@W`JHQn8&iz4iMg?%g{iTbg^Qt~p{t3dlbfNXi-D`9i>b4tk&~;ELPc(YudkI$ zesXDUYF>$_i>(q+L@y;X#R{s|1ee~)i5|o-|m4e#>BV2kX>oGgk zcO{hZGcYi|_H=O!skrrKhQ9_&pv>{|vd-S_CAv@j`GPDoP9^fsStH_Qsc~ zj*dq=*b8qJEf72TF1C8&gePt?X6%Ip1%(&Hl4|OI^_o>0@7|n$-23-x|J=7{_METY zfB*O1Oq1B_v0AOSmqv)Ru5sdSb*k4A=yZ{Zu3xBjHE0`iTd2^dCJT;LAy?!CSh-id z-Q+6vdBv8u&2yaAd)0Py*>J9M5uf5AwL)r3W7-9VEXTbMqU1_=c@-{hLw zEOFy(vTFUN%mthttZTDYFuf`66|veUrLjcsu9~=t%%p`C?8X*9{av+9_@>*kxsqsPVZ z)lKs+sPFQAbZt#=cEUNAM>F}4OKkra&izuaQNTB)K|QIee%jX}@Bg`Gs}m+K{lsY% z;eKY`WKENwkL^#rHOl|b&uO}uciEb-YjYLT_WZxsSa^Z)o65;GA9kiseU`6ys$4RH zN!LbNQpxK2Q=R|Yc$8C3Dy(-*+_Col0h1dio~k*&SmUsMjivvF3A`7sWn~{dZ|J)4 gzuFhg0}OmIsiB(~moH@CW?*3OboFyt=akR{0HpdN%m4rY diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_ab_reply.png new file mode 100755 index 0000000000000000000000000000000000000000..2d78652e7376d2be9c8bdb5abb6d807bd4f692b6 GIT binary patch literal 1458 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?!pzmc$lTe$*~QV)(9qSy!ot+m+1bFv(Z#~q zz{1S{rq?AuximL5uLPzy1)eUB2MjsThND&Pa0;V1i6P|2=9C*S{%>$W*NSGPM+zKCM{M>pr%$*refkqseZis!k570P{n+vR-eRK2-O@7OWV)cPbJ~P2!d#d2TF!`H z5_z($lwVPaX|lnLZ@#@fTb^0}xLkK?f~LA|x4@GsMb#^xtx}BbwBt<-xA$Cfp1UzN~wxnMfM3|T#L9AFVA?@_+6zck+;jY^~THF zOB5>#UX=XaBE55&uCtd~q4^z4m8*Qp(~3L3?N!!wn#mlLn2}^ywusMdN!)9hs+SE{ z!P+T))48ml!fOB9F~S zdky7hl?IeKb)NkG&&l>H&-SC$ZpZ3o^PP54VtM_mYvMQl*9|>9k!P>X(97`fw6@w} zTjuo2$D!Bn&EJmmzmxVEDv4f7mG{4Na#p*!m5Tq@o%6p{C+$1rRsT@9zK%`VGilSS zs~<$;PQ>;8p45LuBGbWt>e~hPbbC%M6Z0%@a!s35yMNg;`x~XH|9?*uJ;k-uLXK5} Y;ncL{+*&-_u7OHXPgg&ebxsLQ0Id=kX#fBK literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/reply.png b/TMessagesProj/src/main/res/drawable-hdpi/reply.png new file mode 100755 index 0000000000000000000000000000000000000000..98db79e65019a248c801667e109db836bfccf751 GIT binary patch literal 1419 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k1|%Oc%$NbBBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?!qmdR($Uh$+1%2|(9qSy(b&Mq&Ctxq)YQz$ z*vZKfrq?AuximL5uLPzy1)QekGK4Y&18 zPS3I|Lopty>~0)mw$g}`~Ba)=a1{p^)9>o(qn>` zi3nHgz37aJrxE2Vnd+jp&hI_`@7LU?i5u=OJe;Yl-}*^`F}_)8iI>@#!xaH7ai>~3 zQrTTKl$@teSjf{7;G*_ZOypIbK}=PkV2HEo6lcvTneTENWHVatuj80l-L>-8!^wLd zEI#ZWa!_u|ftRy|l!fG1SS2z@z4Zx@ej3HKW;(Lw=r)=0VcaoI0Ka z={l`HKKU;r+r+2~T#A$Zw`vw2Ss#?2k#glv#P>kAuNMStx2%s&O}_AE@)_MPijz-R zw7-~Z6*;L+<*dC{q|)ZOg;Nz5tMDy2#y-<~YWoCBBkvwtv(&r?0)7v?ltTZnj0t5> z{j^5N_qXv(q5WHC&brqb)H};VCAByvbmjaL?{xfnwn{0Addy}?+BMzO)9bv*Ss5MW ziGR)~21&n8=R8+b-21=SxA*OosDB+cyA0B=Es%eACeLWe?cVU`_ql(t*~bV~+MPbk z5%Dhg*y@kx8a-#YsXU$J5!Ez%aY=Wp+;n}Lz0T9^=+6^mAjr852NJ9@(O`H-`Yzd@{Rb38f z?20F~t`1GmsTIq~8c)OmCO|6bnOiJZ^upAru88;kHA9i35Y!Q-emm8yG>{T>0Ljsn z0WHX~B+t`q702`JGBOloLrf44KEPIq9505d$+3^Z)*QV}Ovv?Pw(u!Tr4X`3hRI|y zbf%JqPCLU2g5Ya}LII2jxSbYKy@2JG=M`k&YK~ze16ri7sJ6m13RBqA-yxWGLDq7| z(u5Pnc&g2?bkGke4^))@Lrt@Qc2NTS@%Nv?ZnDz`Oaizt?P$1gZRNfxTa+B2BIqO` z+>*~?Lkc43rl3tqjXYV=WLP@PxJyUziXz4=7pay8Vseu4ZmQg z?F!B=ee-Q^@27)ZFIl@)G@9=PYc5OD>{WM$OJNNF9;~Q?wDqHh@(c+Po z)jjF>@ByQC%FEaHY8O_V{laaH7~@Z$nY_OzdwbL8?#L5mBDs?&DNH}6zuW#@tJ_>F zmOOksft$HAPJf)?tsW{nb^6i+rnh3?`ht`9wNUs7m+Rm7sQYs6!}_C#c8`=yAx`{c T9uDfMsQ>h1(YSoAu4UIRcQ1bv delta 214 zcmaFP@riMQO8rhx7srr_TW@c8^EEjLuw3A~=jv?3#KT?qIBI8$@e%C;#+*HE(_O3{ zCNnX{o=Fd!du3N#nz`$iy0uIH6oiT{-E~j<@2Sv}=ISqZO>!@u@NPZ3f>zgeJ>!}p zw#bIgL>ARwm0#LkDz|Z_{CFgLMbd48(b=o!9z4P)%$J>K$YS(o;!tQ{fD>z)G;9Jg zik&8CEix)%~OxQeD{9kduHa+REHV+BDooW Nz|+;wWt~$(696kjTps`c diff --git a/TMessagesProj/src/main/res/drawable-hdpi/tool_blur.png b/TMessagesProj/src/main/res/drawable-hdpi/tool_blur.png new file mode 100755 index 0000000000000000000000000000000000000000..c8614ecb936f19dbf3e522621b382d84cbe1bb13 GIT binary patch literal 1218 zcmeAS@N?(olHy`uVBq!ia0vp^av;pX1|+Qw)-3{3k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDkc>SAteSSPMW@Kn) zWMp9h)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GS>L*^_mzQx(ah7uF{I+w zo9Vs0O%6P*PYXCA7*ix<9U6D~9N561^O$EB%X8Uj7aoXKKm4F?R_U})VX3}UHB?f zr*HewW2Ve2hYunj?@THeYU@;eyl3t~&(+n{TeaBU=jP1(v-hFUwCl&cq?!FW{H80$ z$gya)ex5g7Lx=T|=s{K%9qGHvC;#J^nzb}R>FUOsH6EIZ7E`nCuD-aJg{xtX#}0Q% zv(#mZSDp0_W&LgWJ<*kQ)`JrduGCuHTxQkuc;?Bq|BRNOQh)Px{*7~9rc;k)b%vO0 zTwP|Ow%!BCt6!DA^w(lDf!n=@Zn90XzGae@tMHa-&X!wci+{Z3RcU!T_w?Mqb5?{; feP7wSlhc5Kv2~lEnf=18pi;%t)z4*}Q$iB}F3qWh literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png new file mode 100755 index 0000000000000000000000000000000000000000..06d029c462f0c8766d4825b6cb4415d6826b4884 GIT binary patch literal 958 zcmaJ=J#W)c6m^J-P^(HvEPxPwa+ZSX&%`FS;zo&`&`5O@(n!r%$9_qy)PBZ(!A>T` z#?b%4#2;WljQj)`5Cbbh>VO!K!gCs@3-{9T{CR z-c7$-H_88Nto2Ny6EwuJ6+)`!paBFe&lvZRD|5 zieVEkAZ&`NRFlB6ClG@H9J#(m|9JPF2Ck#gr;^E=fey#+(L97F^LEdkPi)1ZtB0VH zs6@bn*aC@n?ni2((Mw&G%+qa-21^K@X!KQ5eX|2}6ha`eMaJd@0mw2dlq6Xe4uHrD zBFB?gW`vR|$*TAStR9*~3!S0bHJYnfWTnw#j02V9;y7mGB8$QiCn$=NYKS635KJ`l zv6V1>RLB$z7}=p4U>EryRkQ|ZiZz;KdUXUZSj+m+s!XI{Tw(>B!1C#lGN5VxAL@B) zbcDO`I^TZ^N4;49xh{;*G_*pLip z9xd^vskZzGTfPljhDH+w)^#0KPj$OFqGtM2Apl#O~TuCqCp+D0x%lHt+qu2iyF5I5aPjTg lPBXe3w;!5~!j~H_sXUcC*peQ9-``7bRIAZ8-qz1v{QCkZ74s?f^){_BoD;t(qpWn>M1ZN*bvd>)6-EO6@cD6+4*_ zEObEp4Tz;;KrkawF|q(+%+vuf!iE@-$~jF^27+b#e(1gTefNFu4mQ?TW@oO=Fbp$W zTQ%x*oJ+q8=js1A)_&1po-8-XCf*^j6(XkW;1&Wk&)P+GWI5gYAJ8JhOtEgGNt))G zYGaSHQVf@P0cA7H;!+Y=b_WsALc6Z7u|M7(vA}gScB^0tW}u_CyV?uUW^cV=_d2%X zuuFHqVxm$34-pF_-ku++iN+3eRXR_%c@_*Hq@%H?Nj1$4pyLpM0+-L(0)#-8IVcrm z8Qub-07YJ)ubhLDT98%oHW)rEjTSmPYTc*~W6_nywh0MTo{!_0i}M@~cX_BNN~$4> zIf}?dU7uJ<&W{#G3I>Yo&<%)-eUK_zExb=OmS%c-1TPrN`q8jVv|xN<1w7=0^hhJ1 zY5pJTd1G`$>gX)re+oy9Zh-hYitv7D)5h&Aq@e;;50OQ1*uZ#iRK<-pCOB&20O*@C zxUuE>4vwRn1H5UfH9sPjZ=;%_u~dO`T}OqL0<1`4S(gM6!eyzb=ktmz8Re>87Nnv$ z;u_fA_mEFUT<45inaEA8-~}|YfkO8Ia;hQrz~IQLJ2{u)M7<%`nVgF zmHF2n52lZ@rL}t^`?b`czH~AFMSL>1lJ6g8UnpJa`m=A3pKoVM4>L^f_$stt{w$@p NthT&vysB(J`UAZgFHQge literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-mdpi/blur_off.png new file mode 100755 index 0000000000000000000000000000000000000000..424aaa5b46999390fbba6f74aacc12b18916e662 GIT binary patch literal 994 zcmaJ=&ui0A91n_P3@dsWRS+JTpn}b>wb>FDYn!yLVrprND}vB8d0k_dyqLV1v>*&` zf(J$a07Va;1ig9~b6&g&-aJhNuL@oU3iG9FI}g^7jt3s0BgEF;-y}8dmT22e?F0hiSXszzzMX zY$As-Vhj^G9${0|Qa17ovkNh3!ByK;=BCU$(x(qI6=U4`Bcs-ahaihKw%%zVn^cpiu%!>2Q% z$X@^g#|tb+UNOa|<%}o`3t;%r#G7xm<*HU3`XW1p?qKZ6EE|R)6V5ZpUuAhol41=( zND)LT=(*U4Qf@FeQqW*v`nHE{juLzk%F<2;jui!#VL(| zy8eHtO%t~zmCw_sEU;i!YJq<52!T} zoLjM73x&b?0bbYTk{e*dHDO6pXrjQ_wk1nNHM5Y>G&N0%&KJ^>uqfmNA*U6k^kQK# zKjLc0Tz8<0M_lWGTbRg=N5S!kXAS!H9cUGOHk^M5ZS;$74%2@p?z9p1z_VJ;Yv`eX)^Dd%tU- bJT=WxXDS;vzx;gkHNJJFLRov2Z{GU@K~FlH literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_off_active.png b/TMessagesProj/src/main/res/drawable-mdpi/blur_off_active.png new file mode 100755 index 0000000000000000000000000000000000000000..5dfc12a2bd3162c73f3892ae15f2d550c1000584 GIT binary patch literal 1011 zcmaJ=O=#0l9FNF0Q3rZZx1Amt$ON0Ow%HOI$Ck7%Xh!J@D?6DcuWhy^FD7p`n-@2| zOm@P^{UzI1Kp!5Wgh|9kv?zyIf3%}-wJJvwld zqNrYdLMxE9FaC~nlmCah@{26}I9tL~sDkTe0I4w>l_AhwvkD8)v=^_wg&B%EOgqIA zE*Y0)3%QILW0=VG37euaqmge~a}a|vtU8`Te}B0_1IJeA>9oNaz6xv3#8LpKmL`kV z(wrsP^ymeUiDV++LTrM_o%cdHQs{=ROzilWr9lIN=M;KBsFINfDheP-Gs%R-@jMVk zhEJtMkv|Uvju%*tykde+$!Sp*hC%b8iMPP6$OSFe^hI_GUBlRyS+-uUGxa2cf-1{P zk`!wQLV_R?;i8AlDB*>JEd>pRR^a&9K^}+|%`#fR3QZ#2Pr>!uvR>FM6Db%QnLf)i zT%1x1Xc+&8x^5dC;sQK~_n*RHanXlt0fuNHut?)7gRv`LRs(2a6ciDfZ&fj0Ll}iM zS#~(S|k@#Fc8u9@AN xU%%|_^ifZ*|I|0A-=OQw`ts+8EB6!Bp>8T#Klxzj6tf*)Lp?jGJsZEW@(2AtLl*!5 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png new file mode 100755 index 0000000000000000000000000000000000000000..a30d6619bb8865eda892c5e354a9a08e9d9d863f GIT binary patch literal 1265 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gjk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDkcVr1lG;N)iJYyu2)Lst_=M`t5PBXcu13lmdU zQv+9+UYGpj(%jU%5}4i;gkE!;dO=Acw*Y9fOKMSOS!#+~QGTuh*vnR#xZPrc(>$o& z6x?nx#i>^x=oo!a#3DsBObD2IKumbD1#;jCKQ#}S+KYh6x@6(x7zPGLVCXr9RNUG# z&DQU*gFx$bJr0qTKQeRjFENR_d-S?wPxe+glIY~ElKeoR#o2+IX(y9bhSI-j<{4p9 zk#RYbc$I4l_eAZTE?HeBB$0eYf8jv^o&#bL?C%$_e1E_-r`dWrljM~J2Q_~foc(yR zx^!;X+#hlkf=re-SUDruVmF-3PTu%l^o_Zs%m@8VhdPy=Jr7lD?mMvXw8B$fk>k28 zt9x2Jqf9T%S@f_s%gt?3OqA4c_F5J9)uv{ic|U)za=&Z3 z&u-#D-urJVOg2PaPboNQzS5m}wdq3jd*Z!f)p=X?#p;MvhWt65=$<0i|9Z{a1D(;= zV)*7Pj&xVs`d>)+<1NqB6u#SMQhxhzP4vBdK|jX5_Cx!A-P;Mx*X4IQsy|@5vx{XP bs|3TAe>=^VpPAhTDug^;{an^LB{Ts5=UBR+ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_radial_active.png b/TMessagesProj/src/main/res/drawable-mdpi/blur_radial_active.png new file mode 100755 index 0000000000000000000000000000000000000000..a385ca60a2ed27012703e8592fe18538c1abae49 GIT binary patch literal 1387 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gjk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDkc>}KI?VQFFNYyu2)Lst_=OJie8b3;P|6GJC+ zQxjvDUYGpj(%jU%5}4i;gkCe8dO=Acw*Y9fOKMSOS!#+~QGTuh*vnR#xZPrm(>$o& z6x?nx!Kqgt=oo!a#3DsBObD2IKumbD1#;jCKQ#}S+KYh6I^xtu#LF0#u=nKjvuF68pYi#2uRHnex8Sdw{5M$Y4ESRnNShqs-oZRQ z{Pel!aZG)3Y)UmOObI?;`=`xlsFk>C6)zQAw}I=Fg3Cvlh=ng%W<1JFc{fLD)3!}< zIc;lr$_|*$ShArbuTeUHJ>H@3&xxG|*H1*LpE#7VeY&H-oT7It5kmQ zJP?U%e)Q=~)2$V+EL@wTa&wzKRVIdiYrXcVyRpByTAFvuG=H8niys>$xj}nN*vW*IQzz}_y|Y+LdFP!gS!VRVAjn2+zyTUB_1lUc8&TM|tn_1DqY3 zUaH)vU;EDHs$0^|`-1xgt`l zyX8F>MPDxG`LI2e@l4Ubshm-du7A4X{UE%7kwN!V=PuWyT-l)F&(qbc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDkc;%Z@F;OOM+Y;I{}Xy|HUVQAs#Y~W;IVQFFD z=;&wy)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GSv!WwxdXGrOHUWakcwMx zrat6tG7xBue#~XmGF9;a?=ScEfb_uS55nCW6sM?`a8&rdb5Fi?FVSfcr*E9XmOcHu z_p#aXG|wttbLC7jKAjg3wJuXXTP;hZ`jJJ$6IpjR$SCU-c<|5*rbo`Y1VpS zx73yW1?StK2?uJpZELnBF>E~=enEH%x1!+Z+Er7n$}gO_A}!f;)kM`Oo$=uHZHzA7 zXI&dSyr*3GW6l?q;#|ASOYe}9gO2W&i#IvC8CGf(35qf9m~*+-Rls>dk{2tl_|bkZ zp1sO!F&e*bY9zgL6^MWP@^$fsKNtT=8*mvgT#srHx9KFna2iOu>J}Z0+g1(CCWz)1+YqH8h{yprsAwVT+vBGcsmLMftWRJBBMehYSH^_B zneMoh8IpoB)pCk#wgDDUAreVj9o8&hhp2)sz zJ#O6`q}gCF=xA`93nN_CsD?z_rCE(d1s+uSX2zxrbVV32BO-z7g zBi?`~!UR1YF5vY=+P!UDk<07Shzd1SjqOH2P4(^KRn7o_l_~6JLs4ly8gM9|wM~ zueVgXD(WjIpRGR3^}qiN`hMl6t{u+TP*1WwCw8`G^UGj*|5(=h4(wj3bSeCv{_W74 zBj>Gi%a;S6GJRhzftfRj)Xb~aEb{>zS-&+`wQA>XR88LRO3uzMyqx;kFgCGx{rG(2 zqXQ|s{w~)rv6g>8+*!-l-UPX|Hw*R0ndzk$KX%Y7yJCxhzOVJ$h>B|BVB});_}iZ)h839KIy&n#IMHYB#ObzT8%wqsiscyh;0W@>erZI@GYUk)oHPtU zLSRN=3NqYe?km`ZAU2dwXS7W6D9K8Kn=vtNU62hnf^>y+nPJDE28Q7%F9y-IPnS@@ zb3t^#pY$ZEKnlZJo*H3sOyxTunP5Z%-zjk&pvp8C4*oNlIFh#;d2;mz6Y0%}O$e_7mX1055V^i&9Zu^%4&S_eJ7jZN?z5e=u(=!_+p)2+QCex3rdE!A4ZgLN zo7>ylThGtG*a$9L&eO*iULW6GY?xVyf9GwUDg1h%)Z{$e(Pu5&fmm1mh3eXweD;yK z*AUnH;0voC{9a#vftud?oc!=bG}>|Pr5PP7HMK?d%vmcb@Y%h^81-Jf@YE;A^BsauUMPGWoOZGe{tvXr2uv0*at(ozq-M~nMhHpFMoJ7?0fU@EQXY+A^Z>L4+R8V ze{`|(SmRPdc~HNoS#wRL_0ZK^--%dd;_TRUTcsJ?dUgM(qxkNr8;i=4J-c4Fv5Z(A zdWZXS_uPQ3k_O%LU!Dn_`X02kTb+Zmu8+c?=~}^0T|$bhar+uZweIpw?>+Z(o%J;J zoBd#ae12thQMa`mYZ;uXpYecO(YLRxQQ>=hH}|}?>jE`<1+2eu_Mo~v@VD<{1bmJ- Wp2@Ub_$IJw-a(02FMTdDRQLx?B&m-8 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_ab_reply.png new file mode 100755 index 0000000000000000000000000000000000000000..a8d82941166308afadc56f6228ab20086a261e58 GIT binary patch literal 1272 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gjk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`X<}hyY-r->?BZx?Xy|I<=w|9>;bd-XVqs`x z>SSaJ)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GS?kVXbz@*)%<*(_45_$v z4wOj~>}C(DbWb9#|9>vtd%q1QAv9cP=0K zHM~A)OTJ$|PuJG=_Zj1}XAv;- zzT;5x4NHkbGoKxIeSM6j=*Gcjo`^)zZ8urYJYsk$aCLh^T!_mFu~*%!XA#o;5k-B=@oXph`N4LBwTv)4hzUG0{>6|iInco|`?;qNZ>gTe~DWM4f#`w** literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/reply.png b/TMessagesProj/src/main/res/drawable-mdpi/reply.png new file mode 100755 index 0000000000000000000000000000000000000000..7d71990f785dd986dfda4e95be436e1dd24b52dc GIT binary patch literal 1250 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gjk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`Zee6-Vqj|IY;I{}Xy|HU;bLg&Y+~x>WN2V% zWaerC)9aF-T$-DjR|3Q!gkfv4~Pj*wm=R%;iu*SQ+p9GSvwmhYBMk}hIzU;hE&{2 z`t$$4J+m&OFmvz02U`~;Tuil7NL#j)|4Ty!>jfdcD7HWjf%gniN)D$jHn2ZxcJN-3 zDS2|i11qjAF3hn_6K~WoTv@}iJi6KMd#DWq9 zK9(d`rP|ND9fupI}z{lvu3f*1bp9i1(z`CG#su%>x!4wlbU@RuV`*D&}UjTvmu9pJ7gno(5!##M^-mhXa#&s zw9)(9c!cezhTw`i$z4h__>~swMKB-Xb!ffr!SP<-L5AnbX71T4XP7({%2>3lJd#rO zu^p8TxSturl_1t~P^p#W17AmO!>_!D!AC5j)cJR?GBC0+=$|imH9^gXA5`jiy85}S Ib4q9e0DmT$>;M1& literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/system_blue.9.png b/TMessagesProj/src/main/res/drawable-mdpi/system_blue.9.png old mode 100644 new mode 100755 index 40f8cc60781563c253426153dc570437fab62728..c1ce3b4f6da3293aae2f89e95887d730687259dc GIT binary patch literal 1052 zcmaJ=&rj1(94{de2btnQ4aCHzyFfzQbwA2hHny>Dut<@NB`j(TUHf1Sw6C@gH%N?N z(13{vF_9RJ;=y=Q0|z`Pi5D&&)I_;x`~&pFK}j@Td>tEja5nAh`@VcWpYPANG(6Pr zZf`9=5Fv<0 zO3UR@UK$h>s57#IVamFR*#r@Zl}%Zh1c)qv3C)O7JFi|-q^3rx(V*m&%p@pk1G5$w znH|b0vy)0#rDDBgq%2?o9Uz%3>r;j;l%rHdSHOGcn5D=H1WiV%y`b{aFqwoFAcKsb zR=gZX@;t)@f;`W4kv=cyW4-w0X)YiHdBN9BRv!v`v(#}RE2gWyuob0>2$=%QmP#e2 z+ORz}1rgYarI|>B2I(lu1vrhO6pnN+1>M}2HSB7c zaKYHJY_c5VbyBJUCF%cAUEfFBC<_ka{im>B8_&I(?Vgp6S$*-$`6j8a&E(KJ=)=KY~?G7(62hy5Iv z3WSo0U|%ZTmk9eqA)Xg&ToEeMIxtX;s~&KJb-B(c=qC0o0!zCL)U*Y4vXZi()sMwj zSFg%d>&N1+%Vlvetkc-P8eKcW)8lOS#}*s=gAWWm?G_&Ei#zMP_)08i#6+(AxzPDw z^Jc@zukYNy-^U|kTb&IX3$8_aE`NOSQ(H$kCvufJ-52#{uc{R=6Y9_?+!MtpH0(k8|wD$M8UQ8p>WF0Wa(cS&-bg;dFy_9 yH22(|%`B!7KLL_t(|+GAkA5B`&Y34n$MChP1zZQI;_Zy*k#0`>-(2QnA# z0EfJZI#efkpKVy diff --git a/TMessagesProj/src/main/res/drawable-mdpi/tool_blur.png b/TMessagesProj/src/main/res/drawable-mdpi/tool_blur.png new file mode 100755 index 0000000000000000000000000000000000000000..9c05923319139933f63dbd675a6f6db387e59aa4 GIT binary patch literal 1083 zcmaJ=T}TvB7#%Z9Y^5*@6w2FJsL}4sth}KnZTZ^v9x}Xmwjx$$x(3v~VT-#MD z(&!J0=&6FBf*$gvh#n#`BnV2RAHyhwA|mWjsUD1s?T)(IL)$Pj_lI-N_ucP1_gr(+ zfx?2)0*ayvBL~G88H?>Ne;xT>IJd2k3?;a}4Y!~!oRmyR1r^i@K}3_fVGK&jK;Jm@ zQ&cXk#@ldPv{8_e=8|lTE2SBPO;P^Zlp)DI5Q9$Gt?B`K_R$y(R3$*SdZTRA2*HGU zaL|M;gH3UHut)YObnQOiPYFaogIEG7tyi~%RDfR870BG)W@xYo!94+bDXF$-GYBCQ z0GhAhr%V*`a2RpTqS!ho~&GkB*WN^{j1TLE#e+~x?)?hSTR1-iQ7$L>-M48J8~uNM#Nw| zHQl+8PS@sc?{GW?d0&k=j@q1ioO-jcabsC7TV(7Qr#_sj7@DssN;@`P2SXR7PqiNA zch2XropU3zaO;{Um+~*1{Rt)}=hJ;9XRj5%-2Yh0dFx+aRe5D{e#7gjlP{#YhJxqP zw=(C$8{hAZq|Y#pVEg$qyAQ415}HX@cpW7-KQ3H6`HC$){bPLM*39AIfvZ!a4ZlVk mZ=cB9l~?XRI(_*)m9viWK0Eg1{)4fQeVrrqP2!!pj^RI-NMvCE literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png new file mode 100755 index 0000000000000000000000000000000000000000..94ab2c803679f290b61eb3a5466cb001167102c4 GIT binary patch literal 990 zcmaJ=J8#rL5H>{N5l96MDPZML5W(4A$LEW!n9H4=hb0`Hd?)3~IQHhwTme33heYS{wReCxh=&n&_gKWtosI3Yc_6sA*cEAu0XozD_D0(}1pBg-ibdW-njAi3=cunlW#N10nC`d(0BcS8_9~wnt zbV^-x9`8Se)7C+PL>HxapZKhByYq#sL^lcYC?+k8_eQta=wgb~E>3{iRKdNiFb;5* zF7)w^quX&xz1T;#W$;Wv2*W^^R8v~3n2V+&$q=q8wThxx+R~D#s+LrS^%2*?{(gjF zI^qWBTxBA+XoVI0F5Y^>A`5aH8Ij8%&Nxp2!thFk(^IzY0AvvF<6h ztJccD{`hiwl>^tOR_^~iA@th9$Cb-V^*gWbzD|EV zzTJO2+|di|?B#`{@72cKz);NZj?3Kkjo#3(ee>Il#C;B?(c2H}r-jj8-L&4+x1aq1 DC^9LR literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear_active.png b/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear_active.png new file mode 100755 index 0000000000000000000000000000000000000000..a7d39b91cbf29e17944e6dee5ec8a32e51bf0502 GIT binary patch literal 1002 zcmaJ=&ui2`6do;Tt*yNXqNj0+sNm*TchhdzSa*}HT`)`8E_P39Hko!qH<_4BP1=(P zBK;dG)~gp0yeNfQy(x$%5d{4U1VvBk#hLBy)`M$E=EuwTeeb<_Z#L$um&Zm7nl#) zMKc#+A=Q|GkEsn)za7L{s-ups#@5^{BG`e@6&>vb)v)HFK_U!u!eqvgWErZeAZK%` zDqnz#BrBrCUNs|UwVbLcQ?UCW<}GrUw3<2F^~H8NYEc?$qL?I!kW30BS{CJeKF>82 zCBqPzcrBoInhD~Go`Q*EC-Oq-kpOZhCfcCiVK6iE?m$!l+GS4QCyj$3vjff9BDQn)~Sd4*sU9LMg7IPq1WWk8M zuzwZ0XJXyMm;JV7n||ZtfOUJs+WPm~ZGI)LRm@^N{rKg>%Okte=+N#n`fBw4qhHC> z(gSq%8#w&kc>if4|897kgTW>G`T0(JcjxNq+nZbI^)o|n9v+ag2ZFuv(`2BwW&o>#5b=FiL zsU`@bCejs3;FWd$1N-sZyKiR#FZC##LOrk_WhE03?F#GzWJHq&Kmth0$mK=gBZx{$ zO{P#P+AYdZqa_DJ+nRyd1mSD54N1-bMD~FJRrgchpT3|-Rq<23%~3XL1VLKu8Z|-B zXe=p@W@JI3+FD7UEn)!;Ac?fKLEREWQYut&1UIr z6AjG)h7$zA(Qvz67~!%;bR^j>-D)T*gn%WRs)1Cfla8X)2ZxZK!k+Gipcy4u-72IB zCycQrgW+h_38@H-M*k1hv=Z7v39#qyKZUL2hyj=cu;7p>Y(q#|{`6;YGtEwWl1la)B!M6uJIO$y2 z(-QQ$g>VP&4zeCL+%6QkAt(=NKu1Ncvd0aSTYM-rKG1Quo4Boyc>-tglbDNy+LQL$*4oRe z`FP#<`lNmEcAe|Q6X{N*;`7BbUG)oJo-YOH$He0N3wHhH@|CS^e|UWQ*0LZEjxF5J z44>b4ec{b3VRrRdj<3kodf!gBR@|$dxO-Ko*#0s1-rhX-F?YQ-|NP2Nzq7xVI=|ld z*0?gZRO72=KFxT49y&fVyYp^i>geI=)y>?4)7$FiRBqxCQAt#VKdf}O*2NsXNH`XH I7`Sxp54N3Oi2wiq literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_off_active.png b/TMessagesProj/src/main/res/drawable-xhdpi/blur_off_active.png new file mode 100755 index 0000000000000000000000000000000000000000..c37ef8d8e03e74ec83afce44e45e053c48da948a GIT binary patch literal 1103 zcmaJ=O-K|`93PWJ1kqDk5e_4fmAf;u?vA^IqpZ7YuC`+9f_rqFd9I_*ym97jJF9(R zMTDL@)FC{IK~QwDAgJgI67o_Y`4OUrNGmG{5)bxfb+tp=@aBE-`~Ci(?|OUNsp6tT zMFc?gKt0`LF7|P zERN!l)4T*#r)XoGma1bmLDV%^x+wJnM0SIOq6yUc*_ zwZ){Ne#s|O4fSN5#bW^#Ad$4x0nOwsfy(IecyC|R6q$jbeu3I{DjsPk1JD4Z$64c$ z7?veD&dItx9LH9ZE{1i{3?7_=b@LvMch!t?tbn*!j| z{gRRWYv2^FCI+w|S{Myv@`oEtm8blZro-kC_o>MPb3UjLf2##=X5X37rJLSpko z!KeJpbId($9T`40b+P28V_TW+JYNxFi4z&gEHFk~s0j}+74FCWD literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png new file mode 100755 index 0000000000000000000000000000000000000000..10caa4fa4a10ff20847df5387144ceb84a368c2e GIT binary patch literal 1717 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)yMv>2~2MaT(7eMPQ9R{kXrz>*(J3ovn(~mttdZN0qkX~Ox$h(+Ke=Sg-dD3UnZ0`L>Q{w*rKXZ0&^|_rJ zv$no+x$r1KW)53&f&@>4-o1Fn`;MGBP2vf>HQd#YBRH7Z59;jT@Vl^;X`a9Nxn|K1 z9Di~=SS2}5Bo;{Lgf7k&Ef7~}dc|4vL2d)bsjJVn8r@G`A0Jz{J3z>W{dktlWaia( zj(gvEuDxe{_kZETf8=K}rDw&g=2&*{wZ^UsmLG0E?i6(pJ0ks}tI*Co{&B8P+gqpU z2l^g9l0SHr&86D#{Piih?WQIv3FjW4)M?(waa8-oEPk7Jmf}|qv>cy&-o$Z7%E8CJ zK0iz+81KD8|?&7@JRn#$6U02HQ)HcUGO4%2R51)28 z^x@XDTN-g2Q(ky+PHwDjTe#^w6Z75&%@@kzrCzY#ezc&H`^fA2oO^ROKZ|9)euVM0 zSZDYe?%pLg3oG3WmD427%lw{o#boUxMlQE~9Y6mlezA9UWRJm|z6bh&Gu^xGd3Ed{>v$BzZ3t;}%;k#{D&@ z+vQTgg$;^3f3wT*&W?-EX#DXy@$&0BE*V>2fqSy4jf>+tSF)^g(fDUnAz#|*X&AZu z#B|QUC#SDyewv%_KC{$Wd-Jrd9$r%;gY8bOSzp2GppqJP)UM#N!PAaS7q{kr+^e+y zigsUvwQoe0!`IG*3#tz3e0#y3c}_?^zhEP~Z|D4`;}6_dhp#^2a=_wwWbmz`*?IT& oFV)?C^MOWzZr6gB^BI^Kw*KGvJ!8euB2Y!*>FVdQ&MBb@0B-Z6Gynhq literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial_active.png b/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial_active.png new file mode 100755 index 0000000000000000000000000000000000000000..86585c39a2f3bd644271560d17af0c356109acd8 GIT binary patch literal 1990 zcmaJ?Yg7|w8lHp@T@pZVR$KyG@WN`X(#k@m*xHE|yFZqlGc(`iJkRsK z-}^r2e8owLTRc7dJOBXjjE@t`iIL^{mQsm-DtYb=Vt5&sq~XbE25wQCVIWqEro&*o zL7fT9VYN2b)B{HYfE!J(NW;@)+jtt(z)-s|46DINumK=C#%fe+vS1uchcopEpEmVj zCk@nV`LxtX8B1mq!8(0ho*7QgOH^p`vNT*REk*!FTX}?l0mjv!)vyo2cve2`nJ$l* zySAA$@EHWp;?sUkDovIIicm8QMl#rR4GV%m4u=6nL~=OLCNP`@g)>>i%b`ONyhsi& z{1x!|LnES@wHZ9QSo%B`vEtKoIBw)InHGzMVPP{+b0!nwa=9*z@NhbTpkuiRuC~$< zENDSN3}YIz-iYf_1av8?)6s04Pa`t@`3MH%3t0qvUM8YoOsm?+gcvN>krse5+5d+c z3@^|aE{A`~_kRjwid-Yil*1UBZPpNt%LsCXGV(-bSdF7*1&Z!lsA7^1#ZgR$8bMJq z2MkTsBU;pgg+0T|WW0C;!_|leju-Q3gaSja*YZSc4kTf-V?_}}(IH6$H!6ZHl}b5W z36~>@kct+#VpNlDfDwFwtNn$$c~P#*3I-z)Sqz)?Ij~l0Mh)PzBlGl&=MuH3-gB;Y z@m#oza+yRjOjl$7tI-QvgnL}m7q%r9FN_Z(gxk%8t*_cP_y7Qf7cY)gSVunJxhqbw z-J8$$Rofkxiv!CFGk)~0NE)v!m{ArAm#^>`- zy=RUcEeusS_LSLGag76C@5*fZu9ST%d$Lsxjbc+=OJhg=RQ@%=aLYqer@4E-kkssz zM$wY*2|a4oQ3P)5Y&qlHZ@lmNPnCp}oSE8I>wRPSrX|tprfPCOV77fRI_tj_kO}$U zMEZLDYwh>_B!=6%gL^@A`J=?iiAxcmgw#^2UOh&>t5=e$g@+~sksAutN=Ns1RbRI) zgWXoz&Z(PnsjbaN52$L^-NwQKR-X(AIwZU_u(qztJ*O{y{6W=Gs1V%KC$MK=4=W}w z7eExj$4RT2`zN0O<4XcdK0VYn-MO*H;x<3`No9I}aKUJ$SC=3#Sy1vu|N3Cks|R<2 z@vUFF`MM47{?kFfz?PKO5R>zo&b?tG_MDRJw4uEPXCMo(o%6G&|h4 z_hzGgDiVB09E2_Vt!*%sJzs--XrubXWR2(dR_RWJrFcXEn^qZ=rr`IE{Kd;~rExSK z_{jZt#VagP$s2kZ(2}vluh4z3bwLxn^6RA+t~giKCcHmr3RC$uEAi-<*nbA^oWF)< zj^G)iTq^cU$8>@j-SNd1jg(YxxrkYUF7{7?AScjqwJKd}hyI)N9YTms2#_9gZ9{NA}rm?XRPhZFSQY=n*Lbo4nwpq;YO2`?`$M(A5 zj)7p(koeZh*WKfgp}&9i^kUdeYZc|H#ANR#pKbq7{(~pID$>xM=$@>%vM(<8Eu*&_ z9}b>khNlTj_cP0EYfk^wp&}jMWuqijJZ`^Uh3W#%);snFn*NaP{%wNERD6)U^<&8N z@LS$C<&ovyAUE>fGCwcYhRKn9Pg-XscZYQM{cO_jZM@I!HG3ditIFnA7Ps*x1LPG^ z^_%O})3zhjrQnL`zuh8D@-8$Cx}EZ^u9I&+DSVVdPibfOXO{yP>o=xNS3b4HkZ%9L z2^5Yt-Sw1rF;!;s7g9jFPsIY>)QZ4)^ln5ViZPzt5-=@5`C4f=?F| zIT3DlK$b*WF)_n|j=fuWN03)NRC<_69TYrF_|4_}8{dDuPW-`Wtu*z#sDJgudFp5T zTH5LkI2(Q#+1fjjF`&HWY&h{zN_XRRsC`G!SjeBd_Vnb=6?xDp_gii}F?}%jQs>#w zf)!f^*V`q0Pitun_0G-MHJb4dqg&cl@*jg9tW8j!etSqyeM-HON0YY*W@{l|qx|mS zoR^L!)HogFHwEoGx&=r9^410Svojqs|M$o>8`m7x9iXfQj1kVl!|bP3uA4Ppk|=K4 HtSbBoJlhpV literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/delete_reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/delete_reply.png new file mode 100755 index 0000000000000000000000000000000000000000..ce9fd147b0b7afdb5d4c474fd3ad8d5802a7e257 GIT binary patch literal 1356 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFhHdsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6qEIL(9V zO~LIJQ=EGBfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tQ8}ZYZw?94|uvbhE&{o zGcz~4*+8J-s@S*l*WMqJ__{Rpck*g&KC5o|ZGZQOl}m;Tct%a$y;*nnfke@Z&kYUB zHx^zmy=c2#W!L9rOj-*-=zny=yW*nT+n)X5dZg`pSyoP&@j$8H^>c}v8!8%;-M`5> z{NV54S=9D7eckeo5AOw3kBEIs7jn+v{@AiVJw~XYm+7Iuj(10I%K?6u{n`Ij6f}fb z`A*uk?>uh4o1w>>d3V~Bf`jP=>-{H2b_6ckazMW3Ve_&;woakrKLqT)xALE3X5kF0 z2vXvn5MlXXb3jFr+P4V?AM*Krq;2wflVO^t-SXah#7Wq#t+*L>3r8Yb3;W)?ZiHV)B^tm8MvdCr;u+Z(zC@o_(y>{!98|t} My85}Sb4q9e099M!;Q#;t literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/forward_blue.png b/TMessagesProj/src/main/res/drawable-xhdpi/forward_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..40af0d3dcfcf07b4297b8ca43822d057883f42eb GIT binary patch literal 1299 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y-fM)1rW~Nv<8@rh}8yYxTnj2Uc8oHWT7`qx+8XFr~n3%dc znK&B3^t$9Hm*%GCmB93-AoM!n)C)=sxdlL*T~doO%TiO^it=+6z@E0s#O4+QBWDA1 zS2v(}=Gff=(VK$JEnvNF1~~QV10ACeidv+oh6w@F4~Pj*xIhj(>8Iua(|ZvxVSoC4 z44AhVTRmMILn>~)nd$G%6ew~uy@;dm;q)x!AQ!O9=a;gH_b99zdIEw=Lx7Etz^I7eE-wl%Jh4Cs?UX9|6bc(dB*a|VXh5KX|WB{ z*Vp^}p4t6CcuSUL*%*S8Yb_9Q4_Le=&#Qx|^=~-LUZn6}+tL;6~{YC7I?$Yx$OzRa`t$LW`4hsE9 zvT2-FR$$)~x`NSY!SNT&rW=@lIr`nXu)#!kn^WFDrj+I)fy100bL@U-&&*+3vd~g$ zTcx_jUCAqF=JfrV+?M%HD}S%iE0*&c&c1KXn&G*OLn348PA=<>!qmyd+04M%+|tm{(AC7z(8STw$;r~p$<@Wp(#SE(uCavr55ffvFoVy_5Br zo$4d_CckH3V4Ugc;uunK>&+}{Z)Qi4)^t-3pNICFHcec>;`*VrX@Tp8%UdsoZ49*D z8suWQqSY)=B7zqIf7iraeEY;CLjBKb*>Ma0&t z@?V6^@rNum0tRetGg)~W-3<=?;RtmQ4w-qs(P&3K^W-!79~pMA6`u+9@cL;Pk)*fy z?*o=AGk-g<@Ex=&Ru&elPUzk%oZl>4roEB#+t-jw+6U?-*6jX0B!XNa^H1Va3F{L3qfcgAhy^xlM xZB;*~>xgMPIT)Wly6D47M*#trg8qC)HU_;`w>z#pG0qG?;OXk;vd$@?2>>^V`EURL delta 863 zcmZ3=)xfjCjVZ>-)zQ)1*x1y}!o|?g(AC7r+0n$p(%8|}+`z@n+{j2tp(3}y*VoD= zKe;qFHLt|e#a0O@qL-4HVg=P}hD-0{MN9@T3yg6oQc@@`2}(_~O2KV`2`;^p^_ZRN z|FimhVPIeay38@8;?|p){vIKLBFFAar#mP+UYfuqqNx;hBT73*@Y;$DOGoX=8R{H@ z`HCKnAp(kyJerE@nz9Z}m5$ZOxZ&p0nc*PdsI0~D z{_wcYvvYGl->p9X^W5x@W zcaWXIc2!ILqvZ$5E30B!{TekdEGUxHWlnxD?UY>rk6nY_)ZR55d)WLN*KHF1-sC7Y zC*VN5p`R=Do%=T8^{$sJ< zJaf7n2irf^J*@8!=1Vudlv2@omeXvV6R~X``-;cblT-iM$4%+U)${*udvfmEmJ?5W z7-b{NavAn8tgiG4i>lu}(?5K(cEhCArjP&Xeqgg<-~TBlbJ_vZcSWY^OzURNn^Si4 z$O@)EQv%eUJ5HYLYsAg*`L#;=|8P&!x~BIvmrk}fORi=9YA3HM71Fc%?6%9SXP8dB z{O84EcS?QksZ_zu3^Nb*Hl3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)ycG;}p_GBY-JF?BX|G%+zX zH8-(@>2=9ZF3nBND}m`vLFjeFsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6saIL(9V zO~LIJ3!HlOfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tpA9MYBDe|9r1K=45_&F zW~Oh3u%krVWVdb+*4#jWi%s?#qO67-{}h`nt?7%xzl5V%TQwp!ZuNTf`JlSU!k6dr%w{&qR{WTjVr=~W&6(e4 za~`!iDLyM&*<~50#5l3Rqv3I?+Xb#mFTd**)emRzJ3rf zv)ax!!!Db1?}k%5U45Q!7o2xM>3K}YIdfsTgE7x@rkq>Ou{~j0u$kBK$1TPMhj!XH zJQr>`ec@S*(&EpP78Gqb?p*6@z~7c2aPN@yiEtN&x$9MJ3_kpDOD+1z$vkUe_0;K0 zg#_lma&de9`fBE(4;7V8-yiCI*)aD<-NP zwe04W(@KoR4;DRtYoc_FFg!9Kyoys%PML-OcPM%NS1HZ(HI zeOF1CBv9D=S&q*kv-V1IaE-n2v;$clhxl$J%%~3H*pZ^*;3}gK)BZ|nyKK|!w#B;~ zV%VY*_qP9zKj`K1q_=NMR`Twvf?i=Oz8j|~u4GD?P$&BHWYLY6uYG)!@3y=(kU6Hc z^xyM>i2J5gTe~DWM4fxP)QI literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/reply.png new file mode 100755 index 0000000000000000000000000000000000000000..ee23fc6b69b2e0ad4d2931557c80f02bad7f21bc GIT binary patch literal 1567 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)yCH+OV#Hn%h~G;}qwaCNkFG&FKHHZ*W? zakVgj>2=9ZF3nBND}m`vLFjeGsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6qsIL(9V zO~LIJXPkQVfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tgSap5n*6pn(XP~7*cWT z%}jp}(Lj;*`_*bGA|j$ej)JZ(0c*7vizP(`E^A!f(_!YQxRymzNYqJ101Dh9T=gu_${OnN7j~T7y>zC(Kvs+s!=fXUyvrQuA!~x2Z0W;XA}>u})HN+r!TAD~EnB;#|N! z>2U$0-{D&wJnQ+6F>@+>Ftxe$a88=N*WqfeuUR$sRtp?7|1{%DRBT++t1st2NZGz+ zX!Q2o#}%HGRN-78$Y#`b@cU7fiscVW4_HlBzOr<>sb8|xx5GKdRDUNatu^GXbFxia z^gvbZhi=yMmlCY{@(!W9nAe47FoYe^_|YD~d_QKk<)--clOG%9IWzw$C{1dbZdAIL zqWLCZ3*P{I>O6#`6rTe+Rg8cf}o&{=u;SpYeXD-VMi7V+HRq z{XO>9h;S1h(5lK1rG?+qn2(cEYLuk8Nz)$F}Y=*6RU z?<3#lwEL<(=e7t{$TnX%`+$9GMP%w*8QEM`?WNSZIJZTQot1p&H(oPT7E3f)^xa!&Fy0|i~3D*{O z9*}p*2yl+d75k(2K;(kMhx^Jr`{G~!Nt)n#$+14|YouHF)9)s#!U3-){&Abe0ZA2& d$Kn~;7 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/system_blue.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/system_blue.9.png old mode 100644 new mode 100755 index 0ff46944a67e9470c647f468ce98e5d9dc05060e..68c398416ad76632f9e470b0a2685627f7badaee GIT binary patch literal 1204 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y2=9ZF3nBND}m`vLFjeDsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6p}IL(9V zO~LIJOPqT3fsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8ti{d#$}uo7YIwRhhE&{o zbIVrfV1NkggYR-$Qxn%H@Op1xTH6#Fu&HB7il~TJSOTZX&Bpy+PrvV}sL2vsL6UMw!@u|qv@O9odOS5;ZJ1Oyg_IhR4ssA?0zJ4)hC-a?D<%N6t zSNv#jI63ZLxfo_*yw!=v*Ij4T2U*oXu6O!t0jPfmZp-7xvU zyK4CjLL4`KHAE;Vd}HKJ(OvQ9Sm{2dLuH>kOhubE$f~dV{5YIL{>_GCCwL;2+C`?? y?eN=n`$nm+T6X-KVEIXU|5g;={U%o?n83hmYJZrUB{UvXj(EEIxvX+nF~2 delta 262 zcmdnOxrk|kO8rYu7srr_TW@dqavd@dV14l5T=fgZmSZ6o_I514u(_V3(`B!^3<+9|`ebx`%O+T2NU1GCi=C*S>Ywu^i{%$FfUf8xN@Yr_#)9Hmp zmk<3a)m!+x%P8ntxWj6rO(A2zx%b1>ir4fkLFXP;n^bZP2+wT6}FwKEw`{n^p@%Szn*Nw#r+`UTl=UKIt6 w$In+Cyu68h`($HFzHPg=y^Q?E;pBan;rvR!C-bK}?f@C@>FVdQ&MBb@09i_@% diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/tool_blur.png b/TMessagesProj/src/main/res/drawable-xhdpi/tool_blur.png new file mode 100755 index 0000000000000000000000000000000000000000..81511a35ac6b712fc373a0180bf3c8e125d94edd GIT binary patch literal 1203 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^SBuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFe_z-M3hAM`dB6B=jtVb)aX^@765fKFxc2v6eK2Rr0UTq__OB&@Hb09I0xZL0)vRD^GUf^&XRs)DJWv2L<~p`n7AnVzAE zshOFfj)IYap^?4;5Si&3npl~dSs9rtK!Fm_wxX0Ys~{IQs9ivwtx`rwNr9EVetCJh zUb(Seeo?xx^|#0uTKVr7^KE~&-IMVSR9nfZANAQKal@=Hr> zm4GgVcpgi&u1T;Y}Gc(1?#mUjt%+big$v`6q{}ZyY~#JgU=JYDWyPWjfzzt^H5mxWLCvy|fNj4yf{RaY=PT@Z0dIDl2lw(!`7 z<0@J|jLU@Lu2wv3)YeYBC3vS`y>@t*j@VSEv!XKhP1tp93O05B_siip<)D5+a7xo6 zu|1I*v+M<yp=iFg{mdK II;Vst0IPbQod5s; literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png new file mode 100755 index 0000000000000000000000000000000000000000..7a9a7d59d0f8fc824a58a0424292ddab2916cf3f GIT binary patch literal 1045 zcmaJ=&1=*^6i;iFZKY5>_=Vz_idg98V?VMcY^>YOZg;_yWxLV^LChx8Zrmo5CQ~=v zlXxri;6?N(-n@A6W1OM}H6$}{UVgvddvE5=R&8-%a^l4hz$@rYi^)~DjVr4#HMbZ1rY>yRQ4dLrd|U@ zn8`|#I15sOnBoQUN=Y%JWF;k)1O103(R^z~scYqaEV5GBHpZU9^WAQj>!vy6ukxZS z%TyzkN)kje*mSWGCf#5{02g6@h;Zd2&15l zJWyPcz}02jwNN*hiSW9vRNVj@t_iD}$`S?6wk<^v(#4!y&K5I5N)$_(f>yXz7UlVz zEM^K)NshT1GB+IP;+Sh4a;2eM+6ss zB*W8#{p+A(7wH~q4%(J128|D0((OKJ>yx$h7vxH8RkcDR-21*)m|#GHdAI%RH~jW_ z=F7d^`HN@9E^Y6gf1NwQjE*Iyz>NpYcr=cTj#WM?AD%oPr~YSeZqEu&>0jbcJc>pN x>r+O4=09Dy6484|j7@^N+-FRIkzVJxz}z`~^zqE8uRHXjR!fW8%lW$x{{TqiI2`~0 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear_active.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear_active.png new file mode 100755 index 0000000000000000000000000000000000000000..d6802f74b8993c896275fed003ba193a68fc5e76 GIT binary patch literal 1079 zcmaJ=O=uHA6yDY-wNR`ctO~_pb5StaY?|F9Yh!=1NfR-(Cea22>2`P8EbZ>ByHm3* z9-=7XK~S(a&r%hIB1%=%LlN=NUg{|ay@&-{713T4!P)%PgK?RC^TYRj@6CH}t_}?j zw6*SQr6{T`nGn-tPB?$dHeyeHemFp;y*QS`88n6qk_o9k1&u?s~D>)ditr>((QQbYZA;}XEgHbrH>Jj?uvzIhbl?Xk|rFR9PqT)lmGlC9udt~;!7Lblli+#}##+axyk3KIk90_y<4q BRha+) literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png new file mode 100755 index 0000000000000000000000000000000000000000..954cd8ac5678444ccaf5e31af4d8b4843745d294 GIT binary patch literal 1221 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`Ze(QX=Im$o& z6x?nx$EjBz=oo!a#3DsBObD2IKumbD1#;jCKQ#}S+KYh6`dV$u69xuGOHUWakcwMx z?i}v`n#Jve^ygu%92asF?2 zuJo`h*IM=@pOJ+_K*6DbfssiCM1Xlrm_iLKP*p4*FjX+2U*~UbuUyDzopr0DLZ*q5uE@ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off_active.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off_active.png new file mode 100755 index 0000000000000000000000000000000000000000..539299f2d683ccfbf0ec187027bbd18ad029a7d1 GIT binary patch literal 1231 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDi`ZtCJ>rDBLi1c7ZVc; zQ$r(|UYGpj(%jU%5}4i;xL#KSoO(e?A-4c%vrB4GW?5>ATTy$#(fTl(+wn1P1fyo7(ic6?Sr=LvIaD7{;Jg#)$SLd+*tDlfy+hN3(Q^I{ z5f16=557gOwx;Qicm1|)iVr#s7EQk=v**8`8!9vq~^ztxEs!r=|5asEF}&^>bP0l+XkK_=lDG literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png new file mode 100755 index 0000000000000000000000000000000000000000..d7d8bc1b87f05411d05e28dc6819306968942412 GIT binary patch literal 2285 zcmaJ@d00~E9wwJ^H#JSInC017B11&WFq#3+_EW+EJgltnlSCNAiVX{J`@k~u+( z)r>Y~X1B%bP_}4kmNn*RJ(*UHmZjCS+?#a|O*Z$B+da=Y=lj0j^SM(WhQo^k6dDJ`h?5~XM+zdSJaG~TLS{QS0yw z3_}tE@&)uQQZQxV5U~^l@V@>&TnrWq5D30l9G*bHdINqKtRET!zXTsFj)W(W`~rZ_4+{1s z zxKe=x5{N~BPLY!&&Va}$IMTmT5K6wtie#V51Q!gg;7HI|UyLrLIUs}a|Di(R7qkqD z2LF!te+tXkSrQN(4a&qBQZC%MWM`c#2`NMhav-skEf%NERguLPLt+_UECE7d2!Q)K zfruxT%RD~e84OZ{NCt64Trh%0M!^cc0s)T{92`c#gy8~1aB$JFp}1g7C^pca5F8xn zkH=yC1LwFjF*id9il8|z?{6;gt6beE2qmy*8YmTHg1j)PSO|PdnI!mnEQGJ>edhAM z9!tPixo9{Tw63xL)#y1BJUzPYm$8KpUj`o(!P72<$GXI1|8fMvkP|_pvK2#5>o=w? zid}TY(rcl|u|*#3_D73FHfe1@NyNQ6dRdrqrZg!=D~>En3|731EwSu4x)5)r&tLs; z%qr(*od!R1e#3WBD8Mre=}lj?P__Ba$BFu%hB?=jPp>?Ec9-0ZUM@T0|K|Of74m0i zWY?P@62oc;uW`6*;YhK*Yi6g~%yJ$tD>NNh8feJOM{4C7qDb;#^s>Az_jO0iR;yp7|cKK5yhR44@(6&k|nx1d( zgI7H+5RSMU-?1$u^Rom zULP%zLPo6KSsJH!v*^$CohK4cS)K&bD>Ns&$pwQ)Uy*N23=1omcJ1wqJIvIDT8UCzS=(HH=_2Q*#k4(_h zSwWq_pQL0fi})!H#oSvHW7qZ_*K1HFH}!(wl=mj9_xRYdHNPindYrnb6ECJyDatpt z{H=X#CRl#QOKUOy?s}X36&bVe$;P!V2dzD4f4Dk4=>nb8HcSP@?Q>WY8OR(wT--UZ zOh28j{A2BqU8J@zqlIK?<`wdsWtO{vY2ndfQEC@64wh>&Sx4OeO}f;FQ%}-L8*`KT z-18&|r9+5n@W^cBa4S<)t=cVpk-M#V8LRxhOWkVIS39f;Q-)-$-O+GmyJx>=cGfLD z@*h~UF;QK`lc%+>()PS*jAx!TH@h6Kadlx{r+(PrL~XQ9|CiaqtrxGX1n(rtr%dh zGdN-3_^o5Axi!CqaIS^&t4CRY{WmwFAH8iht_XN+JKq?pl)i^9aC?8_@1QV-9Lo$R z*Ev4N(1G4Nxw+rgJ6ldhYSRug7WBB%EmveZVz%Ir>nn{{xaP2l9$-GDt^&E{7?tO7 zd3lApJ13>E6&gL;+EU%rwERemdq9EzYok#Gy;-`GfpsD;sT%v|f$r@;{wA-gRBxYH zQ-91JzeytIc!V*?(bu@jlceN?f zyms4cf`Q;ccF3V0?jv72{cdMB;%O8gH!_ev{wC7srT*2~Yxr}=5j7X%Y^KGhk82O| zVzZ6FOYV%DZl#xc`WG!tvOoCoTKIHZv-6YT2H4OZm#}O!A=HcU!0bDzTV%`W?t%Eu zOC>?jp>TqOd{;*wvZ0K=$?>ICRG(bsvf}<^mM2ry@Q<#mqeOLcsoe?MoiQHRdy>V8 zg3@y|Ic!&#vnP$5+=_xIYssxy#Dt2@{qdW}ZAuQ-fI9Gct_KVwp1bgp$V0i!o*~ONQ1njVx10BwB@} zk|h_#t&2D%Tix~|LfAqW_x-%@`&&NG^L(G*_xt_hm*(f=sjIzA8v=po z(!FQ_s?lry(^{nZuYYyXQ#F`K+(RURf+$G>Qv^cDY(XRl(0R;gFaTt-6XS1yE)a-1 zf)f-X31N5>Sppu4IgdffctRB$0&!U*6Eay`Py$4P(HuSrG1+hx0dUwP#0EUWo*|@y zF&wWX5g3@{6U0j5vYgn6HLie*jHnXeff6PlUS3RhOum&u^mznI6Q%Xu?4X97%bXe^%CqbI3k`v#5w}s9)v2Ih#f@? zpm}_YrCN~?F%pT8h(;$QB%l%;Py$gj8sp^TG_Qfh+NltB;zYiLDYN5?O}{J9Kru_i z5lT1$J}|Gyj1)*EB!tT8Uq|2xf5`I1-_oQ?7+S^@qA@7@`6GP?G8q3K%H#b&izNZz z-+uq6usA4D2%-Z(u|O(fsR|cmIv+|%q>4bML?8+h2;#nH(Jw|I5r|_1LVy}b04z6f z_-sLf*y<~u!64H4VhNMa0_ijoLZyJ>aM(nOlcR?R)x({NQzaeajw5@J@lM#)RJ?=Z zYAn{>;X9WmU`cr(U-F&H{+sLZQ|^2#@Pw+!G*HCZ3bH*!0v_=7$VAT1y-EMLo8!W(t!s=HCyb;-Hm*pAM3W)ao-+oGQz z6-u%O3tHF*TN&#A<3 zoAkF@7iVa32l5W=5NrbOeKFn_E_7&G<$uq2W^WHU#`N=XuVF*?p7#n1Ev}Xl8mi}d z1iI5mrkuhv*9>S42ugKdJAG~}Q*T~aDJ=8Q z+AAH+4c%^ePbBb>%@p(iqgj%hl&=<^RJgHyyPvC3BC?GyNuOGA>NbZ~rc4dngR}_W zJwnjGl~L5!t9Z=2679PD&eS{ z3vHf_O}UYlqu0p7^pzd_N8#*Q+TwS(FvW$t;YeFk7auM2TbPuoF0hAupS87Ri6?aM z^h2Xo6G01XaErF-1M*0vU3x_9g2D_~(0*E6`e{AS>b$J;C1G9UJgL7y$6O_kq7h#c zd*3YFbZT9v_1uv9$cIeiC0>QDUT)huKUd17p)AdTDZMlAjPI4-%83Zo-Jb!Ye|!yl z=aJ)LkrlbiP#K{e(>_;;N6OEha>?1~qikQ!Ni*nEzmtA;+~8WFuoM|tMeQra`hFlM zSXI9=%dUO}tNG3EG<3MrT3ix(a6wMf2X4Odu;^I&OSuWfpdMgQKGKS5CV_RqO)m_X zKHH>CVA(>FMV8^#_Iw|o)xO!E$KG8JW+N>#EB))M?5K!f+XLkc%g1h4EW6VIpMNP8 zNBV*%3~!u9ytTjP-E(l+7pVk~+aUjlansXYLM51Ng32Z-n@)BhLy%I5UUbrJe-zh8i=roL+UEb>2 zIW;Ix(fSlv?|KlLeJDgXG4a4gi-6s_zpn&V9Q z<>Y2(l@&JE(eT>X-1*?$!7+!W`|m7DY2U&vwzv2_AK3iNl;Mn;b{jho_sc&wEZwJg zQJkrrd)CD*i~a1yfOo;LLvy`*$y$(=AGT;6K5n1U^T9v|vdgO5<}U1HB{UXxA;Eu| zC_ttTQw!h3=558-mib%GUUv!6)u}k1hrB_!oOM#SS^B&`%b47vNJu_%$eOiFu~ES* zGi>iGn!v}o!*nWS^=415D=XG*a`S=4RT*=f0PesnZ56gRi= zkF&6d5_qS>aPQhL>T=$>l6zwFmGY2JZrShd`(bWOvvDf>4m@r)IECoBTS^F|9>kc?yT4@B3y z)L9QNUS4P79OZ$Ru2$nNEL3KDbs!oqu7BycJTr3l<(m_GSiSE%b`&h#u171|kn-|i zW^R?#*}q!DbQ0D1z}oiwTT|;cu=DkDM$>H9B;sg|f8Nz4C%O#e5yHU}2Cm-yQgD3F zi|C4~_-^{hXYf2)IX#r@+SoI3%P1EzyO%X(_`Jvp)vuG%VuwCCv}2-i>y7QWg_DG{ zspRhX+*3tX&55@!wm&dxUfWTZ7~#Ipqs?Z`z%xb+ywR}qs>UtpjLrK}^5Mx8)Xw35 zqtr^f^aqQ%4cITuy_6Z#h1aH>>nJI&3Wf;g8u=DSYZ0Mbn#9Bxuwn`C=*nI!G54Km zHBTe9?CUmotX?_Th#4Y-%PHB8P0{+S+5w#*SCho+M?z&fLwbNF^HIeG60%au-{z?i sWD%^l<9CfW6rC^Uwwr~{eTYz71nKqUqXEN}dGq%@y1NhU0%eQ*PqKwsT>t<8 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/delete_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/delete_reply.png new file mode 100755 index 0000000000000000000000000000000000000000..3cfc6883e5aa604f2d58743ecab60707a2b905b3 GIT binary patch literal 1495 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+n3Xa^B1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDkcWMb@M;bLmyY;I{}Xy|IgZv4~Pj*wm=R%;iu*SQ+p9GSsR{qpTWSub?t32S@9S^Z{lPfclCZsKV zZ_D>m;}Xj+gSreI$+GQweX?i&$3?tdYLszzvZmB}zd4?@7P)F`Rm(S;OV!>#SL~!B z?l=3WwxNR8-D5gu?s)98@HTe8=sHWflUMy&;yza^iwXOfCPow{{hxGAILcx|8l%S> z3r(-y5Dz7bm025acqCb9c3+L~SY)ws^-r;vFC1>&br3rKFr)lM=YFdR%fcsYI`Hrn zJFn}fV-GV{7nq)DQ%G$-%$c&@Q=L7?%;JuN)j74ve&u_n$+|PWh*J@i(Oj?)Xyhb^ zqb(v6&M(}<`%P}U$przKLX}X4K8;DIc--|*RI>-2?ObAX_@cXZr`&dp3m0y!I?3so z+LkZ13;jG7ZemRa0ox_)z}PwNt+V<(wBQ~Q+rmT(;qbPZ~KP%?3j zI#ZJ3%BF%GmG$3pd6pY2&6{nqw+NwF%+f*#jj30_TY(#zR3x%|!?{&R1^73GC&yIa4=a=Raw wsMk@r&ku^;76wopL*m?tfy2S@ad-nGgP5;)b?U^~pkkZB)78&qol`;+0MXJA_y7O^ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/forward_blue.png b/TMessagesProj/src/main/res/drawable-xxhdpi/forward_blue.png new file mode 100644 index 0000000000000000000000000000000000000000..075a4f7f75db1182ad5df5b24c1575e6feaa3c8e GIT binary patch literal 1542 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m{l@EB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvO-#2=9ZF3nBND}m`vLFjeGsTY(OatnYqyQCInmZhe+73JqDfIV%MiQ6qsIL(9V zO~LIJXPkQVfsWA!MJ-ZP!-Rn82gHOYTp$OY^i%VI>AeV;u&?ji@`HhaslwC6F{I+w zn>p4QB91cc&qG{TRhyi+SaU_Dh-7XNG_?!h;ppm!l2KanA&^DBbtCV}MN2+h{LvsR z5~Si9Fh$_w)r{nc3K5zaiW(YRT8rk~zoUC-((ib^>1Pj~{bToI)f>Kt$@zKdWjkXw zMwA>%>l4zLz@!O50ZY!ze#vmR^`qOr{k1nHKW$+CxoyF^1)nPfi+^?8oO4XOx9iH9 z;tPd)I*Ub5Jkz*$E=i8}XY?BbzDG5zn{Kur-VxB4^X&nLUXa4c`w1}aGJ-yW-Q$&huG+)Jy8ei{>c>!*~=^hg(3QMIH_DK=oiE0O>AJ-a;<&+$FE zt*06A)Iz_8%Dv-$k<@ zk$J)XPW4>G*5)MMFK4HkpPA=hnxH8l`noQ9^}+WVX&XQPWG#PuI*PCFE!VG>-5)~N zsvi+~u~>UQtABA2-XUs#CS^hZ z^UwU1eJM$0TvML88a=N$m$cym(@*!4)*rLOnA=1$Om;f|oA-3VLY7_6#pj)5x}q5{ zOYuv8U;Wu*56;TH;FBwP>Z`xpAu})G-qi1t<}xka*%iB4c6lW8*T}&D_k`#K_#)+|tm{(AC7z)zZS*)Xc@)#M0T)$i+-ap(3}y*VoD= zKe;qFHLt|e#a0O@qL-4HVg=P}flKe?MN9@T3ruk-Qc@@`2}(_~O2KV`87{q(^_ZRN zxe8)dFfcFyUFH~4aqG<-M~@IknPcv;hs35dvG8-21zwmu-EZcywj==!rE88(9}=oo zy%o6RYn8cti?^nRM#%+dl`f5}*e{PQ_?*GEC*X}-j=C|FC zyJcx|_V;F+f1ZCl?P!wW(Gw>ZDR4nhy^)z>u%3xfXG+SQoO{Y;oK?P#A3qE6SQM+X zo~&eJyR3ThiscG!o@N=YNuODImj3e1`4#;}@CV1bfC+Qd3|Q9%O_<~MfwM)^!%uex z>rWAt=X^7muWNdo%QfKV((v$OjbLdNQCZHT)2PHXDVS;6L0urVMs+Gs+w3Yot>yI! zmaS1iu1dX5GqqCFG|Ue$WiV)W-f=W^{-AvQOVXxE{WIp+7%;yA8WoXWAP=-O#(;B{ zrbl0JPH|UWKZtQ#j#XAfB>qzMhbc`@EZjZw4;FKE>93Uk5)|-9M&HNzOTjXU^#5Pm zn$AtT%zJNcPT0#QDuEX`-E4MOR$11clfS^H_D{R~Lhmo$TT`m7R%@J?9lwCp$J?G` z(*oxY0Xx$(x|;U{KQOwvA1OR3Y?{$y9x!qlyr_dQ?Vs@x>LoBP$l zTdvY9F9mN0z7toF?lj>#6_>*uqN=5?QGP*f1>=4F%QwDRzmVQh9cj6ZJBs~kg7r+l zoO;nGdzQX?*%=u)!CbrQ+|AF6jc>EmGJZd}FJAVRN`~M13H*QFToH4e|Ml4C3-9}K z1-`t0@k2v&?rgmbnJrq|Un~VWm;aRRWVc|;j+ISqQ=$|4msKeUvsx~nXM1YD{<$?m zSJ>m0c=vTS#VxIN`1hHKHBbPGSWW9$B}5s78aFQZxOvM*1|aZs^>bP0l+XkKT;f-($vJnz|q9a!o|?g(AC7k)Wyuj&C$fw(9pud$;3%Xp(3}y*VoD= zKe;qFHLt|e#a0O@qL-4HVg=P}ic9b0MN9@T3yg3nQc@@`2}(_~O2KV`F)qE6^_ZRN z8>WWEGcYhe@pN$vskrrKPHl#7p~Ug}@asx#D`)<6zR~4$C1{d}p>Tag=FIC+lk7## zuA5rFXR7@&@2pSL>^GAffB(~V|7O-j7gtO&=(k(sz|vW-AgI#hGJ!+Laj!{}pT7WCtBtOL z44*gK*KN@`!V-E-XBKnZVQE!5VRNj(&A^pqrn}q@wl3ERl{_rs2fYMSkG+3R}5=;>~eK2)`Zqu1$vyKlw>P?SCruh1Cd+lF;bQjktB|(w> z3-;t~U+|@=Ug4LddxPf!mY$M;fOQ+H5(1P3oe#A9m*95WC}6%U*UDYDoax&Oy^gM( z9}}dEWkr^3T(G2PiC=t(y5rx2G8+VR71!6jk%qDXfG!`pQm@-|@vDv}2yZ$EIC)=O^GpC@$Rjg~7 z&MxR$9;)xE=&j||xCBi9yuQOiDlefQ5YMJ(JZ_+YdjS z+-KBr`Qx_pPfA3ml>Ydum3!UMV#cX|Z1dLE$WF^QlzThdWMyiQ;Qj+rcapYFGv+8_ z3od+`YyB#exclJvf2&^IsPmcd-qnw5Pu(yq{kncivhfOwXVqKcRyNHL z>pePQLcQ*(8~w$$Nvvm|TwlI`DM`vCKDhK#(yxeBdIH)RMmKz3a#_xub^0gYG_A#~ zYc8p-;7Ph=vq9?rk{)%JyrsXK?y^+6@U1=iqH3KPNH%yf1rAJChTZ mwUj(qIu$@XnPc&cYz&9H@0lK-5ZcH91RS2OelF{r5}E+#QV(wc diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_ab_reply.png new file mode 100755 index 0000000000000000000000000000000000000000..2af3db4e545694f9e45fb6a8378daeba45a68dc6 GIT binary patch literal 1936 zcmaJ?eOME996yC2f`bWUT2qe$6%@7|vcaYc#|AQT!p4wEYL4x26SmuK2YV?Kp$VuY zh)xUy6;tNBpy3P3Pzlm}DIp9Ju~2$Z3>6>KtZpRQAJIK`_xpW+&*$^`zTR_%i3{hG zJ>K#F0Dvrv6G(_P&iS~z5%1*tb@Pd35*{PNlhAbBD8~?hr$o~bP^giwKqQDXr%$rTw04yGY1)LJg|;B+Gds+C+Qg(+f) zbbLgmj;9L`j5YQmF95iV%wFZuf3k~UVh`sZe4uL}uJcA4U z6O>Gp2=Y-30hzSfp$Y~JgDe&e4rj7ha0nR2fWznv;%0@y;T$H56BYr!ydc6GrcCEZ z1hFrD5f&Fx;kb@NryGq%nsGJ_#a7T^Hk<9#2n!1(5TORM7MGhswT6IU1p#7EU}_z% zMzx?*QJ#io;arG_^q&+ox>vGV!^<)e1*4nfIyy{aI8z!1ibVep)o5O!4Y&k(9q)e% z8>D6(LYE*0Gz(J@jY|)3y3%p@7$V0}Op2nJ!&OXFp*U(#p*oPC!~%m-)LJEKGz1Uf zMIw$+Yry4N1tJu1Awq$sRx3HINM0l?h~@DGJT?r+gtKA(?8w>7m}o&PKa9tNhq(e& zk)=Vj_%K)bnj1YL*EtFr9pPDkVCrl{8H=GBa42PtdgNFlN7Q@CRgN4Bdqggs2!`%# z?7td4d_+u-bNgy+3FFn^BU)nGF=DJe-Cd*r;OZ(A@T8{Bd*vUfiu4m(ZY>Rh6~|BR z*DtxqteybX-}aW*FzbUZ#21xBEn$_|j6QcZzTmsxnc{P?IKyW(xKinP5d6!JV4dGftLt7Wu6Z9 zHQpjvaga2I*L7l9^QU&#L^ls)Tf~H$q0i01Td8fkC5~Xm;@n+FRn}8I$2a_F13hxK zHk9e9?>8U0-1=}OfG?r+CISt2+ku~Iz}9W3Kk&rux`T0T>EI{PwPV?SfD!A4lN3$O z1s#p^m?lzXUd#A4ODyF=G36KX0X;Z}RJLdQZPHbJ{k9okO$FFmm<-&z6mqv?YLi*# zwq#TmT$KmTu+rnLc!ifOr!M4I*H)4y4RXg+)_p*dUqw_`9=j*7W^^-nnaL~m?HPDr z#lI(K%Eh1UsIJb1MlW|Lj#|@NEWeEl!3C5t4v&pv=AEjpc{7WOe=ef*_8Nc%142sW zr2+7IE$Ee#&)jGP%I#}<4t;kreAyIgdd{VWGw_VKj=?Z5W#g)u!A0j0$K%Pa!hBuX z*pHq{C7k?j>2?0NO{xI)*bkrBcaQ3k9V@?|-Ur5=YB}9Mvnqa9_PaaPypY0k-%ixd zd3rQE$KSRHj~`$abYbGhH9k~U7p}*}Z5{SPlStH%om$gUdc~jqrCd0TBF$V6+KzeTbEnh) z2)eP)YPmKjrUg!FnCtyR;g&@=nphsYx{cEV+dFI99dCb~c*%u4{m(P&y2cNREB_kP z;L>3(III+MkFCBLv;XHt-=HH|bT?sJe}&iCFI4>|Pp_QCJ7&npQ)H&b(fwz->K9uB ze|fv8FCo%4IO-lLpvgV-an8=;#)!e<^f^b%S6^6DD=A6-*iStDwQk9lu>#Y$s? zYjx8qs|`(^T(91lK8f7eA^s!5YwhB-zPab#3@>?3o0&Y>JIZqQ^Jq_Qv&O#3JfIg) z+Kmhss+d9fCZHd?Ru!?YDm4!^E4*8Q7PHpeDMq!rBE0&b1yP5Aw)@Ap2t^<~u`4kX=~ zJS)&z{_IzWE`lT$Pc1v!`7lN=EVBI67iHFZ?mAU%-d*H5zulJoXh8aKJ^x=HULhDf fWIZ2D$r%N7nfjNzc$Wk?|B=F&g@QxT%X9w*x%2TJ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/reply.png new file mode 100755 index 0000000000000000000000000000000000000000..d08e72b8254c9f531bd2116db009bc20ac3dc5e0 GIT binary patch literal 1904 zcmaJ?eNGRdx2Jc7c;9ot~j1!Es>90qd?m{G*oy|9Vfy=)gYC=CZ5 zgGwMi)z)b3EUKcai?z3<2Q{eI8$ywCHT zw_KUD&X-IllSm|AxlF7gMw#pL_9FhN_YSWkh9F#`!Bfy2+^RJrBq5AuBY@nf%|%p* z7B0&F4p~bgy#yN68eF4D1az^6`W6iPsZnh}7*h>FlfLJ+{^G9WgG%Z0)LRwTq?MiMVK0%G$yTs|urc=mvV zH8Y&USBa(1Y!NE~sK;@P&tzJyR)#f-ftquf5Rb=mX|Pxk1R}yxWWu$!2$N;`tb!P^ z=*$KTH=riKrKrtD3vdBQc=|L1BlcX@WO;T>#DOtwT8s%XB3&WP0u_q?hZ>E~(H2~V zyzuuwg)QnL3}LDe3tC{-5sAxL?lOh(MP@{cqh>XVZkjzsr5?pmiyp-QQ3@9bO*fce z)M^Qv!7CJexygcSO*%v_7J!5T!(f2<9FBw=&w|*ZXdVlKBy6EHo+X8(k?}E5Bs-ET zoaKs9U4aoX;j>)$1(!1?*HsEejIb<5%!Wb)mYPu`FcUK0Ft;zPIrW}#;kkW@nv=^U zoME~W`>#aLZV}bvnm#XEV)4B25ff4EW}>Vu>&g!k-Evbd7OHI{cbhY0wDpSzDm&%t z)4X#2^skE-%C~w@zoH>h0WR!p2B-p$TYJkgdxaF~wk(>2vKN#{C23BPv|&Y{XCYJ- zxBvE1T3!8@k7CE($MXwYuT3=m^3XX@G10i;-Kp<+H+Z?+uwcK{^QUA1LQv*W4p2kv z;wtX|VE`CPwI^&G8GY1vCQe`*?LYN-g?aa5!SMD)oJBu*4Nt~w=uD1!ca`4FBCaZe zOO^o19*qN`nCB*c;aIi%#<-*26)bwG$m#tg+@83bb~!(-9H`OEYqzVZ@Y46=qAGDP zG(k9gr^~UR)A867Y4@(kR9^4OP(Bd)Z|*P8S~xhbCYV+`{snh|AtXDzVYt$e#q!D5 zUHw#d**@RdF=79#q1kN=ni8f3`y>nvz5=w>IH*~W#;v||+9M|~C|3pj)j0T?ezC@r ze)4UsF;?B{)x!>~{cr{6-u`lbw%=XPH=XVpU+Kmel2RHiQb~__eCSmdoT*`Eid z2j058W(Y_c=yR)?I_PNo=1ID#&o5rL>S433i;QcIpFYxq{k+sirauFtwK#XA?YzB58+;5iS6u*luGlzT#*v*)Am;S)%B1|tu~gF= z9jER%zFypFjlSyMsf1JWLbrRBZZjcMSs*#_`a`#1(!jD$(|>TUdT_F#d26@lWO4G% zE<3C2<3|U|8V=Ia2U3TwLIr>H1y%>uE}C4^bWk0axUWB3HpoEk4jf%tZC`kQJVi-{ z6iw&%Kd`Yjj~sYeOm6ZmRQ1Lu?HV&5FXcEco~aR&SCuuGUOn3%8#X$>dQIjoeF?B@ z@ROs91l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|81#=KlDb#X~hD#E>34K5C;EJ)Q4 zN-fSWElLJPT$(b-ssbzLqSVBa{GyQj{2W*)24v)y=Hn%i3G;}qwG%+-DayGLxa58hW zur#xP>2=9ZF3nBND}m`vLFjeHsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6rfIL(9V zO~LIJN1S@~fsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tW!HqoM2#JoapJ|7*cWT z&7FmQhaF^&f6QiH(WN;lSL2sd$Ih3XA4QxGIrDJ(GbU{=7T$AolIF1li6aIMVRh`X zJF~eDD!izzKY8B7^uK@A-fJ->RfVZ_vp-LMeCE&RjC(5#E^q(tX8&Nzm5|)kol>)Z zr7T`|wbe?V?^m~wk4S2$1@BjlnYte=CQ@g9c_k2*Dy#aDb5=N)RP+}C0WEqyOjz2Th7gSn^A*%tCk zXw|XkT@7sTK6B1m=**?PJAw-rPnBNH{%YY*n=gy<(#!Tfz5R8s)%N!@-UfY|H2>z* fi$Q01GcYrJ+t>H1b^qIBP=V#?>gTe~DWM4f``g@w delta 362 zcmbQs)xtbMxt`J6)5S5Q;?~ocwA zlPzV%7uGI%oV&)zR$ivfxJs|sx^U6oN}**xZ|To)PsyA4U$w9P#80lvOsnz(dLQ2p z-ekW~?A-TQDncw0%VsuSs)$?a-YP8fm1~OCql-H%)!3F+7W>3JWVm!zcsT>J zOu+$0b_l`5XYrtc8A>$3Sq~bV;Yxst+mR%Iifb*Bb6!~%3hiY)vgxs8S`}wksr8J# zMX%#5ds+J2n0D#N#EOOH_q~^YR`hSWuEv+=C+=MDzxQmZg6YKY`sGFU?mbh@PQR`& j|HALNv8*q*9lFan`)lFXvfahT3_#%N>gTe~DWM4foQc-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxSU1_g&``n5OwZ87 z)XdCKN5ROz&`93^h|F{iO{`4Ktc=VRpg;*|TTx1yRgjAt)Gi>;Rw<*Tq`*pFzr4I$ zuiRKKzbIYb(9+TpWQLKEE>MMTab;dfVufyAu`f(~1RD^r68eAMwS&*t9 zlvv ztM~P_^2{qPNz6-5^>ndS0-B(gnVDkc?CfanYH4QbWN2tv4~Pj*wm=R%;iu*SQ+p9GSx1RH2xVYk+~Mis7*cWT zP4sQA!wv$z(=P4H{AGFdU-$O%`A5zRFxBRNR6g=(byL0YXXbUnk{d7jTFriQqt}wT zz3u6SGoIgzB-B=JH4Ef$-k}gOdHqjwmHYNu3%Pb|x?i~N!1p%Kl0#-T?T@P6S8XW? zJ|wALtM74dx_s}27l%}oIXPq(UyxK(7ipO^e|hx}?Ptdhh~Hnl^RH|rcfF|Of8j~N z+kdHVmQT)asbt_pIyGpJ7|WMtgtxWy|oG-XUo;xugThVCSGJ2pNMI!@VCzQ)~%Y; zx9<_F@ILAJ^G@^o+5WNN3F~*~Mz--Y{+PQr@5O7?$Cocn{Za_DFk|K~)`unOKlidd zTfB~YJyy6-;8%Xjv1^kTTstff?cWr|@0?@HnPtnf_~zo-Z1R>O`zrbuwKIO#XmNUx r@Osw|FQ#};4e=LlpQj#aXJBSvS*`NkDEP@oP`T#m>gTe~DWM4f3jgXH literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/layout/messages_list.xml b/TMessagesProj/src/main/res/layout/messages_list.xml index 7e685fb8a..6f6381a86 100644 --- a/TMessagesProj/src/main/res/layout/messages_list.xml +++ b/TMessagesProj/src/main/res/layout/messages_list.xml @@ -61,6 +61,8 @@ android:gravity="center" android:textSize="15dp" android:paddingTop="6dp" + android:paddingLeft="8dp" + android:paddingRight="8dp" android:lineSpacingExtra="2dp" android:id="@+id/list_empty_view_text2"/> diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 685e5fb17..8531c127f 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -16,7 +16,7 @@ رمز التفعيل تم إرسال رسالة قصيرة تحتوي على رمز التفعيل الخاص بك %1$d:%2$02d سنتصل بك خلال - جارٍ الاتصال بك ... + جاري الاتصال بك ... رمز التفعيل الرقم خاطئ؟ هل استقبلت الرمز؟ @@ -36,12 +36,12 @@ ...لا توجد محادثات بعد إبدأ المراسلة بالضغط على\nأيقونة النقاط في أعلى يمين الشاشة\nأو اذهب لقسم جهات الاتصال. في إنتظار الشبكة... - جارٍ الاتصال... - جارٍ التحديث... + جاري الاتصال... + جاري التحديث... محادثة سرية جديدة في إنتظار اتصال %s … تم إلغاء المحادثة السرية - جارٍ إرسال المفاتيح المشفرة... + جاري إرسال المفاتيح المشفرة... %s قام بالدخول للمحادثة السرية. لقد قمت بالدخول للمحادثة السرية. مسح سجل المحادثات @@ -81,7 +81,7 @@ أرسل الصورة بدون ضغطها مخفي - جارٍ الكتابة… + جاري الكتابة… يكتب… يكتبون… هل يوجد لديك سؤال\nحول تيليجرام؟ @@ -108,7 +108,7 @@ لقد تم إخراجك من هذه المجموعة لقد قمت بمغادرة المجموعة حذف هذه المجموعة - حذف هذه المحادثة + حذف هذه الدردشة قم بالسحب للإلغاء حفظ في الجهاز مشاركة @@ -244,7 +244,7 @@ لا يوجد صوت افتراضي الدعم - خلفية المحادثة + خلفية الدردشة الرسائل أرسل بزر الإدخال سجل الخروج من كافة الأجهزة الأخرى @@ -300,6 +300,8 @@ آخر تعطيل تعطيل + تعطيل + إيقاف رمز المرور غيًر رمز المرور @@ -358,6 +360,9 @@ الحبوب زيادة الحدة الطمس + إيقاف + طولي + قطري هل أنت متأكد من رغبتك في حذف هذه الصورة؟ هل أنت متأكد من رغبتك في حذف هذا المقطع المرئي؟ تجاهل التغييرات؟ @@ -479,14 +484,14 @@ الرمز غير صحيح الاسم الأول غير صحيح اسم العائلة غير صحيح - جارٍ التحميل ... + جاري التحميل ... ليس لديك أي مشغل مقاطع مرئية، يرجى تنزيل أية مشغل يرجى إرسال رسالة بواسطة البريد الإلكتروني إلى sms@telegram.org لتخبرنا عن مشكلتك. لا يوجد لديك تطبيق يمكنه فتح \'%1$s\'، يرجى تنزيل تطبيق مناسب للإستمرار هذا المستخدم ليس لديه تيليجرام بعد ، هل ترغب في دعوته الآن؟ هل أنت متأكد؟ هل ترغب في إضافة %1$s للمجموعة؟\n\nعدد الرسائل الحديثة المراد إعادة تحويلها: - هل تريد إعادة توجيه الرسائل إلى %1$s؟ + ؟%1$s هل تريد إعادة توجيه الرسائل إلى هل ترغب في إرسال رسالة إلى %1$s؟ نرجو الأخذ بالعلم أنه يمكنك استخدام تيليجرام على أجهزتك المتعددة بسهولة تامة وفي وقت واحد.\n\nوتذكر، تسجيل الخروج يحذف كافة محادثاتك السرية. هل أنت متأكد من تسجيل الخروج من جميع الأجهزة الأخرى باستثناء هذا الجهاز؟ @@ -501,7 +506,7 @@ هل أنت متأكد من رغبتك في حذف سجل المحادثات؟ هل أنت متأكد من رغبتك في حذف %1$s؟ هل ترغب في إرسال رسالة إلى %1$s؟ - هل تريد إعادة توجيه الرسائل إلى %1$s؟ + ؟%1$s هل تريد إعادة توجيه الرسائل إلى .Sorry, this feature is currently not available in your country تيليجرام @@ -556,12 +561,6 @@ %1$d ملفات %1$d ملف %1$d ملف - ليس من جهة اتصال - من %1$d جهة اتصال - من %1$d جهتان اتصال - من %1$d جهات اتصال - من %1$d جهة اتصال - من %1$d جهة اتصال من ولا محادثة من %1$d محادثة من %1$d محادثة @@ -616,6 +615,61 @@ %1$d مستخدمون %1$d مستخدم %1$d مستخدم + + %1$d رسالة معاد توجيهها + الرسالة المعاد توجيهها + %1$d رسالة معاد توجيهها + %1$d رسالة معاد توجيهها + %1$d رسالة معاد توجيهها + %1$d رسالة معاد توجيهها + %1$d ملف معاد توجيهه + ملف معاد توجيهه + %1$d ملف معاد توجيهه + %1$d ملف معاد توجيهه + %1$d ملف معاد توجيهه + %1$d ملف معاد توجيهه + %1$d صورة معاد توجيهها + صورة معاد توجيهها + %1$d صورة معاد توجيهها + %1$d صورة معاد توجيهها + %1$d صورة معاد توجيهها + %1$d صورة معاد توجيهها + %1$d مقطع مرئي معاد توجيهه + مقطع مرئي معاد توجيهه + %1$d مقطع مرئي معاد توجيهه + %1$d مقطع مرئي معاد توجيهه + %1$d مقطع مرئي معاد توجيهه + %1$d مقطع مرئي معاد توجيهه + %1$d مقطع صوتي معاد توجيهه + مقطع صوتي معاد توجيهه + %1$d مقطع صوتي معاد توجيهه + %1$d مقطع صوتي معاد توجيهه + %1$d مقطع صوتي معاد توجيهه + %1$d مقطع صوتي معاد توجيهه + %1$d موقع معاد توجيهه + موقع معاد توجيهه + %1$d موقع معاد توجيهه + %1$d موقع معاد توجيهه + %1$d موقع معاد توجيهه + %1$d موقع معاد توجيهه + %1$d جهة اتصال معاد توجيهها + جهة اتصال معاد توجيهها + %1$d جهة اتصال معاد توجيهها + %1$d جهة اتصال معاد توجيهها + %1$d جهة اتصال معاد توجيهها + %1$d جهة اتصال معاد توجيهها + %1$d ملصق معاد توجيهها + ملصق معاد توجيهه + %1$d ملصق معاد توجيهه + %1$d ملصق معاد توجيهه + %1$d ملصق معاد توجيهه + %1$d ملصق معاد توجيهه + and %1$d others + and %1$d other + and %1$d others + and %1$d others + and %1$d others + and %1$d others MMMM yyyy MMM dd diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index 6a00c0f6d..b43db3eb5 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -151,7 +151,7 @@ %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,\nDein Telegram Team %1$s hat das Profilbild geändert - Beantworten + Antworten %1$s antworten %1$s antworten %1$s %2$s @@ -300,6 +300,8 @@ Sonstige Deaktiviert Deaktiviert + Deaktiviert + Aus Pincode Pincode ändern @@ -358,6 +360,9 @@ Körnung Schärfe Unschärfe + Aus + Linear + Radial Möchtest du wirklich dieses Bild löschen? Möchtest du wirklich dieses Video löschen? Änderungen verwerfen? @@ -556,12 +561,6 @@ %1$d Objekte %1$d Objekte %1$d Objekte - von keinem Kontakt - von %1$d Kontakt - von %1$d Kontakten - von %1$d Kontakten - von %1$d Kontakten - von %1$d Kontakten von keinen Chats von %1$d Chat von %1$d Chats @@ -616,6 +615,61 @@ %1$d Nutzer %1$d Nutzer %1$d Nutzer + + %1$d angehängten Nachrichten + Angehängte Nachricht + %1$d angehängte Nachrichten + %1$d angehängte Nachrichten + %1$d angehängte Nachrichten + %1$d angehängte Nachrichten + %1$d angehängten Dateien + Angehängte Datei + %1$d angehängte Dateien + %1$d angehängte Dateien + %1$d angehängte Dateien + %1$d angehängte Dateien + %1$d angehängten Bilder + Angehängtes Bild + %1$d angehängte Bilder + %1$d angehängte Bilder + %1$d angehängte Bilder + %1$d angehängte Bilder + %1$d angehängten Videos + Angehängtes Video + %1$d angehängte Videos + %1$d angehängte Videos + %1$d angehängte Videos + %1$d angehängte Videos + %1$d angehängten Audios + Angehängtes Audio + %1$d angehängte Audios + %1$d angehängte Audios + %1$d angehängte Audios + %1$d angehängte Audios + %1$d weitergeleiteten Standorte + Angehängter Standort + %1$d angehängte Standorte + %1$d angehängte Standorte + %1$d angehängte Standorte + %1$d angehängte Standorte + %1$d weitergeleiteten Kontakt + Angehängter Kontakt + %1$d angehängte Kontakte + %1$d angehängte Kontakte + %1$d angehängte Kontakte + %1$d angehängte Kontakte + %1$d angehängten Sticker + Angehängter Sticker + %1$d angehängte Sticker + %1$d angehängte Sticker + %1$d angehängte Sticker + %1$d angehängte Sticker + und %1$d andere + und %1$d anderer + und %1$d andere + und %1$d andere + und %1$d andere + und %1$d andere MMMM yyyy dd MMM diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 0d576537c..b5977896b 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -149,7 +149,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 - Privacidad y seguirdad - 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 seguridad - Cerrar todas las otras sesiones.\n\nAtentamente,\nEl equipo de Telegram %1$s actualizó su foto de perfil Responder Responder a %1$s @@ -300,6 +300,8 @@ Otras Desactivadas Desactivadas + Desactivado + Apagado Código de acceso Cambiar código de acceso @@ -345,7 +347,7 @@ BUSCA GIF Buscar foto Buscar GIF - Cortar imagen + Recortar imagen Editar imagen Realzar Iluminación @@ -358,6 +360,9 @@ Grano Nitidez Desenfoque + Apagado + Lineal + Radial ¿Quieres eliminar esta foto? ¿Quieres eliminar este vídeo? ¿Descartar cambios? @@ -442,7 +447,7 @@ Eliminar foto Establecer OK - CORTAR + RECORTAR un1 expulsó a un2 un1 dejó el grupo @@ -550,18 +555,12 @@ %1$d mensajes %1$d mensajes %1$d mensajes - Sin ítemes + Sin ítems %1$d ítem - %1$d ítemes - %1$d ítemes - %1$d ítemes - %1$d ítemes - unused - de %1$d contacto - de %1$d contactos - de %1$d contactos - de %1$d contactos - de %1$d contactos + %1$d ítems + %1$d ítems + %1$d ítems + %1$d ítems desde ningún chat desde %1$d chat desde %1$d chats @@ -616,6 +615,61 @@ %1$d usuarios %1$d usuarios %1$d usuarios + + %1$d mensajes adjuntos + Mensaje adjunto + %1$d mensajes adjuntos + %1$d mensajes adjuntos + %1$d mensajes adjuntos + %1$d mensajes adjuntos + %1$d archivos adjuntos + Archivo adjunto + %1$d archivos adjuntos + %1$d archivos adjuntos + %1$d archivos adjuntos + %1$d archivos adjuntos + %1$d fotos adjuntas + Foto adjunta + %1$d fotos adjuntas + %1$d fotos adjuntas + %1$d fotos adjuntas + %1$d fotos adjuntas + %1$d vídeos adjuntos + Vídeo adjunto + %1$d vídeos adjuntos + %1$d vídeos adjuntos + %1$d vídeos adjuntos + %1$d vídeos adjuntos + %1$d audios adjuntos + Audio adjunto + %1$d audios adjuntos + %1$d audios adjuntos + %1$d audios adjuntos + %1$d audios adjuntos + %1$d ubicaciones adjuntas + Ubicación adjunta + %1$d ubicaciones adjuntas + %1$d ubicaciones adjuntas + %1$d ubicaciones adjuntas + %1$d ubicaciones adjuntas + %1$d contactos adjuntos + Contacto adjunto + %1$d contactos adjuntos + %1$d contactos adjuntos + %1$d contactos adjuntos + %1$d contactos adjuntos + %1$d stickers adjuntos + Sticker adjunto + %1$d stickers adjuntos + %1$d stickers adjuntos + %1$d stickers adjuntos + %1$d stickers adjuntos + y %1$d otros + and %1$d más + y otros %1$d + y otros %1$d + y otros %1$d + y otros %1$d MMMM \'de\' yyyy dd \'de\' MMM diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 5362a26a2..35540a276 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -36,7 +36,7 @@ Ancora nessuna chat… Inizia a scrivere premendo il tasto\nnuovo messaggio nell\'angolo in basso a destra\no apri il menu per avere più opzioni. Attendo la rete... - Connessione in corso… + Connessione… Aggiornamento… Nuova chat segreta In attesa che %s si colleghi… @@ -149,7 +149,7 @@ %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 - Privacy e Sicurezza - Termina tutte le sessioni.\n\nGrazie,\nil team di Telegram + %1$s,\nAbbiamo rilevato un accesso al tuo account da un nuovo dispositivo il %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 @@ -259,7 +259,7 @@ Eliminare la localizzazione? File della localizzazione non valido Abilitate - Disabilitate + Disabilitata Servizio notifiche Se i servizi di Google Play sono sufficienti per ricevere le notifiche, è possibile disabilitare il Servizio notifiche. Ti raccomandiamo comunque di lasciarlo abilitato per lasciare l\'app attiva in background e ricevere le notifiche istantanee. Ordina per @@ -274,7 +274,7 @@ Mostra sempre i popup Contatore Badge Breve - Lungo + Lunga Predefinito di sistema Impostazioni predefinite Download automatico media @@ -300,6 +300,8 @@ Altro Disabilitate Disabilitata + Disabilitato + No Codice Cambia codice @@ -358,6 +360,9 @@ Grana Nitidezza Sfocatura + No + Lineare + Radiale Sei sicuro di voler eliminare questa foto? Sei sicuro di voler eliminare questo video? Annullare le modifiche? @@ -556,12 +561,6 @@ %1$d oggetti %1$d oggetti %1$d oggetti - da nessun contatto - da %1$d contatto - da %1$d contatti - da %1$d contatti - da %1$d contatti - da %1$d contatti in nessuna chat in %1$d chat in %1$d chat @@ -616,6 +615,61 @@ %1$d utenti %1$d utenti %1$d utenti + + %1$d messaggi inoltrati + Messaggio inoltrato + %1$d messaggi inoltrati + %1$d messaggi inoltrati + %1$d messaggi inoltrati + %1$d messaggi inoltrati + %1$d file inoltrati + FIle inoltrato + %1$d file inoltrati + %1$d file inoltrati + %1$d file inoltrati + %1$d file inoltrati + %1$d foto inoltrate + Foto inoltrata + %1$d foto inoltrate + %1$d foto inoltrate + %1$d foto inoltrate + %1$d foto inoltrate + %1$d video inoltrati + Video inoltrato + %1$d video inoltrati + %1$d video inoltrati + %1$d video inoltrati + %1$d video inoltrati + %1$d audio inoltrati + Audio inoltrato + %1$d audio inoltrati + %1$d audio inoltrati + %1$d audio inoltrati + %1$d audio inoltrati + %1$d posizioni inoltrate + Posizione inoltrata + %1$d posizione inoltrate + %1$d posizione inoltrate + %1$d posizione inoltrate + %1$d posizione inoltrate + %1$d contatti inoltrati + Contatto inoltrato + %1$d contatti inoltrati + %1$d contatti inoltrati + %1$d contatti inoltrati + %1$d contatti inoltrati + %1$d sticker inoltrati + Sticker inoltrato + %1$d sticker inoltrati + %1$d sticker inoltrati + %1$d sticker inoltrati + %1$d sticker inoltrati + e altri %1$d + e %1$d altro + e altri %1$d + e altri %1$d + e altri %1$d + e altri %1$d MMMM yyyy dd MMM diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 2f89c7e8c..913229857 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -300,6 +300,8 @@ 기타 끄기 끄기 + 끄기 + 끄기 잠금번호 잠금번호 변경 @@ -358,6 +360,9 @@ 그레인 선명 흐림 + Off + Linear + Radial 이 사진을 삭제하시겠습니까? 이 동영상을 삭제하시겠습니까? 변경을 취소하시겠습니까? @@ -556,12 +561,6 @@ %1$d개 아이템 %1$d개 아이템 %1$d개 아이템 - 보낸곳 없음 - - 채팅방 %1$d개에서 - 채팅방 %1$d개에서 - 채팅방 %1$d개에서 - 채팅방 %1$d개에서 - 채팅방 %1$d개에서 받은 대화 없음 %1$d개의 대화로부터 받음 %1$d개의 대화로부터 받음 @@ -616,6 +615,61 @@ %1$d명의 대화상대 %1$d명의 대화상대 %1$d명의 대화상대 + + %1$d forwarded messages + Forwarded message + %1$d forwarded messages + %1$d forwarded messages + %1$d forwarded messages + %1$d forwarded messages + %1$d forwarded files + Forwarded file + %1$d forwarded files + %1$d forwarded files + %1$d forwarded files + %1$d forwarded files + %1$d forwarded photos + Forwarded photo + %1$d forwarded photos + %1$d forwarded photos + %1$d forwarded photos + %1$d forwarded photos + %1$d forwarded videos + Forwarded video + %1$d forwarded videos + %1$d forwarded videos + %1$d forwarded videos + %1$d forwarded videos + %1$d forwarded audios + Forwarded audio + %1$d forwarded audios + %1$d forwarded audios + %1$d forwarded audios + %1$d forwarded audios + %1$d forwarded locations + Forwarded location + %1$d forwarded locations + %1$d forwarded locations + %1$d forwarded locations + %1$d forwarded locations + %1$d forwarded contacts + Forwarded contact + %1$d forwarded contacts + %1$d forwarded contacts + %1$d forwarded contacts + %1$d forwarded contacts + %1$d forwarded stickers + Forwarded sticker + %1$d forwarded stickers + %1$d forwarded stickers + %1$d forwarded stickers + %1$d forwarded stickers + and %1$d others + and %1$d other + and %1$d others + and %1$d others + and %1$d others + and %1$d others MMMM yyyy M\'월\' d\'일\' diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index 162cfbf94..673f17b9e 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -300,6 +300,8 @@ Overig Uitgeschakeld Uitgeschakeld + Uitgeschakeld + Uit Toegangscode Toegangscode wijzigen @@ -310,7 +312,7 @@ Huidige toegangscode invoeren Nieuwe toegangscode invoeren Toegangscode invoeren - Nieuwe toegangscode opnieuw invoeren + Toegangscode opnieuw invoeren Ongeldige toegangscode Toegangscodes komen niet overeen Automatisch vergrendelen @@ -358,6 +360,9 @@ Korrel Scherper Vager + Uit + Lineair + Radiaal Foto echt verwijderen? Video echt verwijderen? Wijzigingen negeren? @@ -556,12 +561,6 @@ %1$d items %1$d items %1$d items - van geen enkel contact - van %1$d contacten - van %1$d contacten - van %1$d contacten - van %1$d contacten - van %1$d contacten van geen chats van %1$d chat van %1$d chats @@ -616,6 +615,61 @@ %1$d gebruikers %1$d gebruikers %1$d gebruikers + + +%1$d berichten + +1 bericht + +%1$d berichten + +%1$d berichten + +%1$d berichten + +%1$d berichten + +%1$d bestanden + +1 bestand + +%1$d bestanden + +%1$d bestanden + +%1$d bestanden + +%1$d bestanden + +%1$d foto\'s + +1 foto + +%1$d foto\'s + +%1$d foto\'s + +%1$d foto\'s + +%1$d foto\'s + +%1$d foto\'s + +1 video + +%1$d video\'s + +%1$d video\'s + +%1$d video\'s + +%1$d video\'s + +%1$d geluidsbestanden + +1 geluidsbestand + +%1$d geluidsbestanden + +%1$d geluidsbestanden + +%1$d geluidsbestanden + +%1$d geluidsbestanden + +%1$d locaties + +1 locatie + +%1$d locaties + +%1$d locaties + +%1$d locaties + +%1$d locaties + +%1$d contacten + +1 contact + +%1$d contacten + +%1$d contacten + +%1$d contacten + +%1$d contacten + +%1$d stickers + +1 sticker + +%1$d stickers + +%1$d stickers + +%1$d stickers + +%1$d stickers + en %1$d anderen + en %1$d andere + en %1$d anderen + en %1$d anderen + en %1$d anderen + en %1$d anderen MMMM yyyy dd MMM diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index c4eddf668..4e697f7cb 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -57,7 +57,7 @@ Silenciar por %1$s Restaurar Som Em %1$s - Desativar + Desativado Nova Lista de Transmissão Digite o nome da lista @@ -299,7 +299,9 @@ O número %1$s já possui uma conta do Telegram. Por favor, exclua esta conta antes de migrar para o novo número. Outro Desativado - Desativado + Desativar + Desativado + Desativado Senha Alterar Senha @@ -347,8 +349,8 @@ Procurar GIFs Recortar imagem Editar imagem - Aumentar - Realce + Realçar + Luzes Contraste Exposição Calor @@ -358,6 +360,9 @@ Granulado Nitidez Desfoque + Desativado + Linear + Radial Você tem certeza que deseja apagar esta foto? Você tem certeza que deseja apagar este vídeo? Descartar mudanças? @@ -556,12 +561,6 @@ %1$d itens %1$d itens %1$d itens - de nenhum contato - de %1$d contato - de %1$d contatos - de %1$d contatos - de %1$d contatos - de %1$d contatos de nenhum chat de %1$d chat de %1$d chats @@ -616,6 +615,61 @@ %1$d usuários %1$d usuários %1$d usuários + + %1$d mensagens encaminhadas + Mensagem encaminhada + %1$d mensagens encaminhadas + %1$d mensagens encaminhadas + %1$d mensagens encaminhadas + %1$d mensagens encaminhadas + %1$d arquivos encaminhados + Arquivo encaminhado + %1$d arquivos encaminhados + %1$d arquivos encaminhados + %1$d arquivos encaminhados + %1$d arquivos encaminhados + %1$d fotos encaminhadas + Foto encaminhada + %1$d fotos encaminhadas + %1$d fotos encaminhadas + %1$d fotos encaminhadas + %1$d fotos encaminhadas + %1$d vídeos encaminhados + Vídeo encaminhado + %1$d vídeos encaminhados + %1$d vídeos encaminhados + %1$d vídeos encaminhados + %1$d vídeos encaminhados + %1$d áudios encaminhados + Áudio encaminhado + %1$d áudios encaminhados + %1$d áudios encaminhados + %1$d áudios encaminhados + %1$d áudios encaminhados + %1$d localizações encaminhadas + Localização encaminhada + %1$d localizações encaminhadas + %1$d localizações encaminhadas + %1$d localizações encaminhadas + %1$d localizações encaminhadas + %1$d contatos encaminhados + Contato encaminhado + %1$d contatos encaminhados + %1$d contatos encaminhados + %1$d contatos encaminhados + %1$d contatos encaminhados + %1$d stickers encaminhados + Sticker encaminhado + %1$d stickers encaminhados + %1$d stickers encaminhados + %1$d stickers encaminhados + %1$d stickers encaminhados + e %1$d outros + e %1$d outro + e %1$d outros + e %1$d outros + e %1$d outros + e %1$d outros MMMM yyyy dd MMM diff --git a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml index 6deb25e57..6e74903b1 100644 --- a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml @@ -57,7 +57,7 @@ Silenciar por %1$s Restaurar Som Em %1$s - Desativar + Desativado Nova Lista de Transmissão Digite o nome da lista @@ -299,7 +299,9 @@ O número %1$s já possui uma conta do Telegram. Por favor, exclua esta conta antes de migrar para o novo número. Outro Desativado - Desativado + Desativar + Desativado + Desativado Senha Alterar Senha @@ -347,8 +349,8 @@ Procurar GIFs Recortar imagem Editar imagem - Aumentar - Realce + Realçar + Luzes Contraste Exposição Calor @@ -358,6 +360,9 @@ Granulado Nitidez Desfoque + Desativado + Linear + Radial Você tem certeza que deseja apagar esta foto? Você tem certeza que deseja apagar este vídeo? Descartar mudanças? @@ -556,12 +561,6 @@ %1$d itens %1$d itens %1$d itens - de nenhum contato - de %1$d contato - de %1$d contatos - de %1$d contatos - de %1$d contatos - de %1$d contatos de nenhum chat de %1$d chat de %1$d chats @@ -616,6 +615,61 @@ %1$d usuários %1$d usuários %1$d usuários + + %1$d mensagens encaminhadas + Mensagem encaminhada + %1$d mensagens encaminhadas + %1$d mensagens encaminhadas + %1$d mensagens encaminhadas + %1$d mensagens encaminhadas + %1$d arquivos encaminhados + Arquivo encaminhado + %1$d arquivos encaminhados + %1$d arquivos encaminhados + %1$d arquivos encaminhados + %1$d arquivos encaminhados + %1$d fotos encaminhadas + Foto encaminhada + %1$d fotos encaminhadas + %1$d fotos encaminhadas + %1$d fotos encaminhadas + %1$d fotos encaminhadas + %1$d vídeos encaminhados + Vídeo encaminhado + %1$d vídeos encaminhados + %1$d vídeos encaminhados + %1$d vídeos encaminhados + %1$d vídeos encaminhados + %1$d áudios encaminhados + Áudio encaminhado + %1$d áudios encaminhados + %1$d áudios encaminhados + %1$d áudios encaminhados + %1$d áudios encaminhados + %1$d localizações encaminhadas + Localização encaminhada + %1$d localizações encaminhadas + %1$d localizações encaminhadas + %1$d localizações encaminhadas + %1$d localizações encaminhadas + %1$d contatos encaminhados + Contato encaminhado + %1$d contatos encaminhados + %1$d contatos encaminhados + %1$d contatos encaminhados + %1$d contatos encaminhados + %1$d stickers encaminhados + Sticker encaminhado + %1$d stickers encaminhados + %1$d stickers encaminhados + %1$d stickers encaminhados + %1$d stickers encaminhados + e %1$d outros + e %1$d outro + e %1$d outros + e %1$d outros + e %1$d outros + e %1$d outros MMMM yyyy dd MMM diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 81181db86..10d21bff7 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -300,6 +300,8 @@ Other Disabled Disabled + Disabled + Off Passcode Change Passcode @@ -358,6 +360,9 @@ Grain Sharpen Blur + Off + Linear + Radial Are you sure you want to delete this photo? Are you sure you want to delete this video? Discard changes? @@ -556,12 +561,6 @@ %1$d items %1$d items %1$d items - from no contacts - from %1$d contact - from %1$d contacts - from %1$d contacts - from %1$d contacts - from %1$d contacts from no chats from %1$d chat from %1$d chats @@ -616,6 +615,61 @@ %1$d users %1$d users %1$d users + + %1$d forwarded messages + Forwarded message + %1$d forwarded messages + %1$d forwarded messages + %1$d forwarded messages + %1$d forwarded messages + %1$d forwarded files + Forwarded file + %1$d forwarded files + %1$d forwarded files + %1$d forwarded files + %1$d forwarded files + %1$d forwarded photos + Forwarded photo + %1$d forwarded photos + %1$d forwarded photos + %1$d forwarded photos + %1$d forwarded photos + %1$d forwarded videos + Forwarded video + %1$d forwarded videos + %1$d forwarded videos + %1$d forwarded videos + %1$d forwarded videos + %1$d forwarded audios + Forwarded audio + %1$d forwarded audios + %1$d forwarded audios + %1$d forwarded audios + %1$d forwarded audios + %1$d forwarded locations + Forwarded location + %1$d forwarded locations + %1$d forwarded locations + %1$d forwarded locations + %1$d forwarded locations + %1$d forwarded contacts + Forwarded contact + %1$d forwarded contacts + %1$d forwarded contacts + %1$d forwarded contacts + %1$d forwarded contacts + %1$d forwarded stickers + Forwarded sticker + %1$d forwarded stickers + %1$d forwarded stickers + %1$d forwarded stickers + %1$d forwarded stickers + and %1$d others + and %1$d other + and %1$d others + and %1$d others + and %1$d others + and %1$d others MMMM yyyy MMM dd