From 82f9be238d6a7bfb961f3b4a77e811d3f81e3556 Mon Sep 17 00:00:00 2001 From: DrKLO Date: Wed, 22 Jul 2015 21:56:37 +0300 Subject: [PATCH] Update to 3.1.1 --- TMessagesProj/build.gradle | 4 +- TMessagesProj/src/main/AndroidManifest.xml | 14 +- .../SQLite/SQLitePreparedStatement.java | 9 +- .../telegram/android/AndroidUtilities.java | 10 - .../AnimationCompat/AnimatorSetProxy.java | 4 +- .../telegram/android/ContactsController.java | 80 +- .../main/java/org/telegram/android/Emoji.java | 439 ++-- .../org/telegram/android/ImageLoader.java | 3 + .../org/telegram/android/MediaController.java | 450 +++- .../org/telegram/android/MessageObject.java | 57 +- .../telegram/android/MessagesController.java | 2 +- .../org/telegram/android/MessagesStorage.java | 23 +- .../telegram/android/MusicPlayerReceiver.java | 69 + .../telegram/android/MusicPlayerService.java | 295 +++ .../telegram/android/NotificationCenter.java | 2 + .../android/NotificationsController.java | 33 +- .../telegram/android/SendMessagesHelper.java | 83 +- .../java/org/telegram/android/UserObject.java | 6 +- .../telegram/android/audioinfo/AudioInfo.java | 154 ++ .../android/audioinfo/m4a/M4AInfo.java | 325 +++ .../android/audioinfo/m4a/MP4Atom.java | 151 ++ .../android/audioinfo/m4a/MP4Box.java | 87 + .../android/audioinfo/m4a/MP4Input.java | 41 + .../android/audioinfo/mp3/ID3v1Genre.java | 171 ++ .../android/audioinfo/mp3/ID3v1Info.java | 86 + .../android/audioinfo/mp3/ID3v2DataInput.java | 74 + .../android/audioinfo/mp3/ID3v2Encoding.java | 41 + .../android/audioinfo/mp3/ID3v2Exception.java | 24 + .../android/audioinfo/mp3/ID3v2FrameBody.java | 155 ++ .../audioinfo/mp3/ID3v2FrameHeader.java | 165 ++ .../android/audioinfo/mp3/ID3v2Info.java | 376 +++ .../android/audioinfo/mp3/ID3v2TagBody.java | 81 + .../android/audioinfo/mp3/ID3v2TagHeader.java | 191 ++ .../android/audioinfo/mp3/MP3Exception.java | 24 + .../android/audioinfo/mp3/MP3Frame.java | 315 +++ .../android/audioinfo/mp3/MP3Info.java | 270 ++ .../android/audioinfo/mp3/MP3Input.java | 60 + .../audioinfo/util/PositionInputStream.java | 79 + .../audioinfo/util/RangeInputStream.java | 63 + .../android/query/SharedMediaQuery.java | 34 + .../android/support/util/SortedList.java | 16 +- .../android/support/widget/AdapterHelper.java | 3 + .../support/widget/DefaultItemAnimator.java | 1 + .../support/widget/GridLayoutManager.java | 2 + .../android/support/widget/LayoutState.java | 23 +- .../support/widget/LinearLayoutManager.java | 75 +- .../android/support/widget/OpReorderer.java | 14 +- .../android/support/widget/PositionMap.java | 1 - .../android/support/widget/RecyclerView.java | 564 +++- .../widget/StaggeredGridLayoutManager.java | 186 +- .../widget/helper/ItemTouchHelper.java | 2331 +++++++++++++++++ .../widget/helper/ItemTouchUIUtil.java | 65 + .../widget/helper/ItemTouchUIUtilImpl.java | 138 + .../util/SortedListAdapterCallback.java | 2 +- .../telegram/messenger/ApplicationLoader.java | 1 - .../messenger/ConnectionsManager.java | 4 +- .../telegram/messenger/FileLoadOperation.java | 18 +- .../org/telegram/messenger/FileLoader.java | 9 + .../telegram/messenger/HandshakeAction.java | 2 +- .../java/org/telegram/messenger/TLRPC.java | 12 + .../org/telegram/messenger/TcpConnection.java | 2 +- .../org/telegram/ui/ActionBar/ActionBar.java | 366 +-- .../ui/ActionBar/ActionBarLayout.java | 10 +- .../telegram/ui/ActionBar/ActionBarMenu.java | 26 +- .../ui/ActionBar/ActionBarMenuItem.java | 42 +- .../ui/ActionBar/ActionBarPopupWindow.java | 50 +- .../telegram/ui/ActionBar/BaseFragment.java | 3 +- .../telegram/ui/ActionBar/BottomSheet.java | 465 +++- .../ui/ActionBar/DrawerLayoutContainer.java | 3 - .../ui/Adapters/CountrySearchAdapter.java | 1 - .../ui/Adapters/PhotoAttachAdapter.java | 17 +- .../telegram/ui/Adapters/StickersAdapter.java | 2 +- .../org/telegram/ui/AudioPlayerActivity.java | 464 ++++ .../org/telegram/ui/AudioSelectActivity.java | 344 +++ .../org/telegram/ui/BlockedUsersActivity.java | 3 +- .../java/org/telegram/ui/Cells/AudioCell.java | 169 ++ .../org/telegram/ui/Cells/BotHelpCell.java | 6 +- .../org/telegram/ui/Cells/ChatActionCell.java | 5 +- .../org/telegram/ui/Cells/ChatAudioCell.java | 79 +- .../org/telegram/ui/Cells/ChatBaseCell.java | 2 +- .../telegram/ui/Cells/ChatContactCell.java | 1 - .../org/telegram/ui/Cells/ChatMediaCell.java | 1 - .../telegram/ui/Cells/ChatMessageCell.java | 4 +- .../org/telegram/ui/Cells/ChatMusicCell.java | 428 +++ .../org/telegram/ui/Cells/DialogCell.java | 18 +- .../ui/Cells/PhotoAttachCameraCell.java | 3 +- .../ui/Cells/PhotoAttachPhotoCell.java | 1 + .../telegram/ui/Cells/SharedDocumentCell.java | 5 +- .../ui/Cells/SharedMediaSectionCell.java | 2 +- .../telegram/ui/Cells/StickerEmojiCell.java | 4 +- .../org/telegram/ui/Cells/TextDetailCell.java | 4 +- .../telegram/ui/ChangeChatNameActivity.java | 3 +- .../org/telegram/ui/ChangeNameActivity.java | 3 +- .../org/telegram/ui/ChangePhoneActivity.java | 3 +- .../telegram/ui/ChangePhoneHelpActivity.java | 3 +- .../telegram/ui/ChangeUsernameActivity.java | 3 +- .../java/org/telegram/ui/ChatActivity.java | 291 +- .../ui/Components/BotKeyboardView.java | 6 +- .../ui/Components/ChatActivityEnterView.java | 104 +- .../ui/Components/ChatAttachView.java | 203 +- .../ui/Components/DrawerPlayerView.java | 130 + .../org/telegram/ui/Components/EmojiView.java | 10 +- .../ui/Components/EmptyTextProgressView.java | 3 +- .../ui/Components/LetterSectionsListView.java | 2 +- .../ui/Components/LineProgressView.java | 18 +- .../telegram/ui/Components/NumberPicker.java | 1 - .../ui/Components/PagerSlidingTabStrip.java | 3 - .../telegram/ui/Components/PasscodeView.java | 2 - .../ui/Components/PhotoFilterView.java | 29 +- .../PhotoViewerCaptionEnterView.java | 35 +- ...tomLayout.java => PickerBottomLayout.java} | 30 +- .../ui/Components/PopupAudioView.java | 7 +- .../ui/Components/RadialProgress.java | 5 +- .../ui/Components/RecyclerListView.java | 5 + .../ui/Components/ScrollSlidingTabStrip.java | 3 - .../org/telegram/ui/Components/SeekBar.java | 54 +- .../ui/Components/SpannableStringLight.java | 88 + .../org/telegram/ui/Components/Switch.java | 2 - .../telegram/ui/Components/TimerDrawable.java | 4 +- .../ui/Components/TypingDotsDrawable.java | 2 +- .../ui/Components/VideoTimelineView.java | 1 - .../ui/Components/WebFrameLayout.java | 8 +- .../org/telegram/ui/ContactAddActivity.java | 3 +- .../org/telegram/ui/ContactsActivity.java | 3 +- .../telegram/ui/CountrySelectActivity.java | 5 +- ...agesActivity.java => DialogsActivity.java} | 11 +- .../telegram/ui/DocumentSelectActivity.java | 5 +- .../org/telegram/ui/GroupCreateActivity.java | 2 +- .../telegram/ui/GroupCreateFinalActivity.java | 3 +- .../org/telegram/ui/GroupInviteActivity.java | 3 +- .../org/telegram/ui/IdenticonActivity.java | 5 +- .../telegram/ui/LanguageSelectActivity.java | 3 +- .../org/telegram/ui/LastSeenActivity.java | 3 +- .../telegram/ui/LastSeenUsersActivity.java | 3 +- .../java/org/telegram/ui/LaunchActivity.java | 90 +- .../org/telegram/ui/LocationActivity.java | 9 +- .../java/org/telegram/ui/LoginActivity.java | 7 +- .../java/org/telegram/ui/MediaActivity.java | 80 +- .../ui/NotificationsSettingsActivity.java | 19 +- .../org/telegram/ui/PasscodeActivity.java | 3 +- .../telegram/ui/PhotoAlbumPickerActivity.java | 25 +- .../org/telegram/ui/PhotoCropActivity.java | 5 +- .../org/telegram/ui/PhotoPickerActivity.java | 28 +- .../java/org/telegram/ui/PhotoViewer.java | 23 +- .../ui/PopupNotificationActivity.java | 10 +- .../telegram/ui/PrivacySettingsActivity.java | 3 +- .../java/org/telegram/ui/ProfileActivity.java | 23 +- .../ui/ProfileNotificationsActivity.java | 3 +- .../org/telegram/ui/SessionsActivity.java | 7 +- .../org/telegram/ui/SettingsActivity.java | 9 +- .../org/telegram/ui/StickersActivity.java | 3 +- .../ui/TwoStepVerificationActivity.java | 3 +- .../org/telegram/ui/VideoEditorActivity.java | 7 +- .../org/telegram/ui/WallpapersActivity.java | 3 +- .../src/main/res/anim/no_animation.xml | 3 + ..._attach_music_big.png => attach_audio.png} | Bin .../drawable-hdpi/attach_audio_pressed.png | Bin 0 -> 3041 bytes ...attach_photo_big.png => attach_camera.png} | Bin .../drawable-hdpi/attach_camera_pressed.png | Bin 0 -> 5560 bytes ...ach_contact_big.png => attach_contact.png} | Bin .../drawable-hdpi/attach_contact_pressed.png | Bin 0 -> 2859 bytes ...ic_attach_file_big.png => attach_file.png} | Bin .../res/drawable-hdpi/attach_file_pressed.png | Bin 0 -> 2687 bytes ...ach_gallery_big.png => attach_gallery.png} | Bin .../drawable-hdpi/attach_gallery_pressed.png | Bin 0 -> 2718 bytes ...c_attach_hide_big.png => attach_hide1.png} | Bin .../drawable-hdpi/attach_hide1_pressed.png | Bin 0 -> 2275 bytes ...ach_hide_big_icon.png => attach_hide2.png} | Bin ...h_location_big.png => attach_location.png} | Bin .../drawable-hdpi/attach_location_pressed.png | Bin 0 -> 3117 bytes ...c_attach_send_big.png => attach_send1.png} | Bin .../drawable-hdpi/attach_send1_pressed.png | Bin 0 -> 2261 bytes ...ach_send_big_icon.png => attach_send2.png} | Bin ..._attach_video_big.png => attach_video.png} | Bin .../drawable-hdpi/attach_video_pressed.png | Bin 0 -> 2369 bytes .../res/drawable-hdpi/audiosend_pause.png | Bin 0 -> 2055 bytes .../main/res/drawable-hdpi/audiosend_play.png | Bin 0 -> 2604 bytes .../main/res/drawable-hdpi/bluecounter.9.png | Bin 0 -> 489 bytes .../main/res/drawable-hdpi/ic_action_next.png | Bin 0 -> 291 bytes .../res/drawable-hdpi/ic_action_pause.png | Bin 0 -> 234 bytes .../main/res/drawable-hdpi/ic_action_play.png | Bin 0 -> 348 bytes .../res/drawable-hdpi/ic_action_previous.png | Bin 0 -> 306 bytes .../res/drawable-hdpi/ic_attach_contact.png | Bin 1255 -> 0 bytes .../res/drawable-hdpi/ic_attach_gallery.png | Bin 1248 -> 0 bytes .../res/drawable-hdpi/ic_attach_location.png | Bin 1490 -> 0 bytes .../res/drawable-hdpi/ic_attach_music.png | Bin 1206 -> 0 bytes .../res/drawable-hdpi/ic_attach_photo.png | Bin 1442 -> 0 bytes .../res/drawable-hdpi/ic_attach_photobig.png | Bin 1696 -> 0 bytes .../res/drawable-hdpi/ic_attach_video.png | Bin 1045 -> 0 bytes .../src/main/res/drawable-hdpi/menu_pause.png | Bin 0 -> 1069 bytes .../src/main/res/drawable-hdpi/menu_play.png | Bin 0 -> 1215 bytes .../src/main/res/drawable-hdpi/nocover.png | Bin 0 -> 2148 bytes .../main/res/drawable-hdpi/nocover_big.9.png | Bin 0 -> 2163 bytes .../res/drawable-hdpi/nocover_small.9.png | Bin 0 -> 1051 bytes .../src/main/res/drawable-hdpi/pl_back.png | Bin 0 -> 1166 bytes .../src/main/res/drawable-hdpi/pl_next.png | Bin 0 -> 1302 bytes .../res/drawable-hdpi/pl_next_pressed.png | Bin 0 -> 1319 bytes .../src/main/res/drawable-hdpi/pl_pause.png | Bin 0 -> 996 bytes .../res/drawable-hdpi/pl_pause_pressed.png | Bin 0 -> 1001 bytes .../src/main/res/drawable-hdpi/pl_play.png | Bin 0 -> 1342 bytes .../res/drawable-hdpi/pl_play_pressed.png | Bin 0 -> 1342 bytes .../main/res/drawable-hdpi/pl_previous.png | Bin 0 -> 1313 bytes .../res/drawable-hdpi/pl_previous_pressed.png | Bin 0 -> 1328 bytes .../src/main/res/drawable-hdpi/pl_repeat.png | Bin 0 -> 1187 bytes .../res/drawable-hdpi/pl_repeat1_active.png | Bin 0 -> 1230 bytes .../res/drawable-hdpi/pl_repeat_active.png | Bin 0 -> 1195 bytes .../src/main/res/drawable-hdpi/pl_shuffle.png | Bin 0 -> 1366 bytes .../res/drawable-hdpi/pl_shuffle_active.png | Bin 0 -> 1369 bytes .../src/main/res/drawable-hdpi/player.png | Bin 0 -> 1415 bytes .../src/main/res/drawable-hdpi/player1.png | Bin 687 -> 0 bytes .../res/drawable-hdpi/player1_pressed.png | Bin 1210 -> 0 bytes .../src/main/res/drawable-hdpi/player2.png | Bin 676 -> 0 bytes .../res/drawable-hdpi/player2_pressed.png | Bin 1250 -> 0 bytes .../main/res/drawable-hdpi/sheet_shadow.9.png | Bin 0 -> 325 bytes ..._attach_music_big.png => attach_audio.png} | Bin .../drawable-mdpi/attach_audio_pressed.png | Bin 0 -> 2284 bytes ...attach_photo_big.png => attach_camera.png} | Bin .../drawable-mdpi/attach_camera_pressed.png | Bin 0 -> 3929 bytes ...ach_contact_big.png => attach_contact.png} | Bin .../drawable-mdpi/attach_contact_pressed.png | Bin 0 -> 2189 bytes ...ic_attach_file_big.png => attach_file.png} | Bin .../res/drawable-mdpi/attach_file_pressed.png | Bin 0 -> 2057 bytes ...ach_gallery_big.png => attach_gallery.png} | Bin .../drawable-mdpi/attach_gallery_pressed.png | Bin 0 -> 2172 bytes ...c_attach_hide_big.png => attach_hide1.png} | Bin .../drawable-mdpi/attach_hide1_pressed.png | Bin 0 -> 1841 bytes ...ach_hide_big_icon.png => attach_hide2.png} | Bin ...h_location_big.png => attach_location.png} | Bin .../drawable-mdpi/attach_location_pressed.png | Bin 0 -> 2333 bytes ...c_attach_send_big.png => attach_send1.png} | Bin .../drawable-mdpi/attach_send1_pressed.png | Bin 0 -> 1840 bytes ...ach_send_big_icon.png => attach_send2.png} | Bin ..._attach_video_big.png => attach_video.png} | Bin .../drawable-mdpi/attach_video_pressed.png | Bin 0 -> 1899 bytes .../res/drawable-mdpi/audiosend_pause.png | Bin 0 -> 1552 bytes .../main/res/drawable-mdpi/audiosend_play.png | Bin 0 -> 2002 bytes .../main/res/drawable-mdpi/bluecounter.9.png | Bin 0 -> 336 bytes .../main/res/drawable-mdpi/ic_action_next.png | Bin 0 -> 229 bytes .../res/drawable-mdpi/ic_action_pause.png | Bin 0 -> 188 bytes .../main/res/drawable-mdpi/ic_action_play.png | Bin 0 -> 282 bytes .../res/drawable-mdpi/ic_action_previous.png | Bin 0 -> 249 bytes .../res/drawable-mdpi/ic_attach_contact.png | Bin 1162 -> 0 bytes .../res/drawable-mdpi/ic_attach_gallery.png | Bin 1131 -> 0 bytes .../res/drawable-mdpi/ic_attach_location.png | Bin 1261 -> 0 bytes .../res/drawable-mdpi/ic_attach_music.png | Bin 1102 -> 0 bytes .../res/drawable-mdpi/ic_attach_photo.png | Bin 1227 -> 0 bytes .../res/drawable-mdpi/ic_attach_photobig.png | Bin 1376 -> 0 bytes .../res/drawable-mdpi/ic_attach_video.png | Bin 990 -> 0 bytes .../src/main/res/drawable-mdpi/menu_pause.png | Bin 0 -> 1063 bytes .../src/main/res/drawable-mdpi/menu_play.png | Bin 0 -> 1131 bytes .../src/main/res/drawable-mdpi/nocover.png | Bin 0 -> 1705 bytes .../main/res/drawable-mdpi/nocover_big.9.png | Bin 0 -> 1550 bytes .../res/drawable-mdpi/nocover_small.9.png | Bin 0 -> 844 bytes .../src/main/res/drawable-mdpi/pl_back.png | Bin 0 -> 1084 bytes .../src/main/res/drawable-mdpi/pl_next.png | Bin 0 -> 1166 bytes .../res/drawable-mdpi/pl_next_pressed.png | Bin 0 -> 1162 bytes .../src/main/res/drawable-mdpi/pl_pause.png | Bin 0 -> 975 bytes .../res/drawable-mdpi/pl_pause_pressed.png | Bin 0 -> 977 bytes .../src/main/res/drawable-mdpi/pl_play.png | Bin 0 -> 1148 bytes .../res/drawable-mdpi/pl_play_pressed.png | Bin 0 -> 1156 bytes .../main/res/drawable-mdpi/pl_previous.png | Bin 0 -> 1182 bytes .../res/drawable-mdpi/pl_previous_pressed.png | Bin 0 -> 1183 bytes .../src/main/res/drawable-mdpi/pl_repeat.png | Bin 0 -> 1058 bytes .../res/drawable-mdpi/pl_repeat1_active.png | Bin 0 -> 1090 bytes .../res/drawable-mdpi/pl_repeat_active.png | Bin 0 -> 1063 bytes .../src/main/res/drawable-mdpi/pl_shuffle.png | Bin 0 -> 1210 bytes .../res/drawable-mdpi/pl_shuffle_active.png | Bin 0 -> 1220 bytes .../src/main/res/drawable-mdpi/player.png | Bin 0 -> 1249 bytes .../src/main/res/drawable-mdpi/player1.png | Bin 516 -> 0 bytes .../res/drawable-mdpi/player1_pressed.png | Bin 828 -> 0 bytes .../src/main/res/drawable-mdpi/player2.png | Bin 503 -> 0 bytes .../res/drawable-mdpi/player2_pressed.png | Bin 845 -> 0 bytes .../main/res/drawable-mdpi/sheet_shadow.9.png | Bin 0 -> 207 bytes .../res/drawable-v21/bar_selector_audio.xml | 4 + ..._attach_music_big.png => attach_audio.png} | Bin .../drawable-xhdpi/attach_audio_pressed.png | Bin 0 -> 3825 bytes ...attach_photo_big.png => attach_camera.png} | Bin .../drawable-xhdpi/attach_camera_pressed.png | Bin 0 -> 4972 bytes ...ach_contact_big.png => attach_contact.png} | Bin .../drawable-xhdpi/attach_contact_pressed.png | Bin 0 -> 3519 bytes ...ic_attach_file_big.png => attach_file.png} | Bin .../drawable-xhdpi/attach_file_pressed.png | Bin 0 -> 3070 bytes ...ach_gallery_big.png => attach_gallery.png} | Bin .../drawable-xhdpi/attach_gallery_pressed.png | Bin 0 -> 3424 bytes ...c_attach_hide_big.png => attach_hide1.png} | Bin .../drawable-xhdpi/attach_hide1_pressed.png | Bin 0 -> 2806 bytes ...ach_hide_big_icon.png => attach_hide2.png} | Bin ...h_location_big.png => attach_location.png} | Bin .../attach_location_pressed.png | Bin 0 -> 3959 bytes ...c_attach_send_big.png => attach_send1.png} | Bin .../drawable-xhdpi/attach_send1_pressed.png | Bin 0 -> 2825 bytes ...ach_send_big_icon.png => attach_send2.png} | Bin ..._attach_video_big.png => attach_video.png} | Bin .../drawable-xhdpi/attach_video_pressed.png | Bin 0 -> 2866 bytes .../res/drawable-xhdpi/audiosend_pause.png | Bin 0 -> 2442 bytes .../res/drawable-xhdpi/audiosend_play.png | Bin 0 -> 3266 bytes .../main/res/drawable-xhdpi/bluecounter.9.png | Bin 0 -> 663 bytes .../res/drawable-xhdpi/ic_action_next.png | Bin 0 -> 326 bytes .../res/drawable-xhdpi/ic_action_pause.png | Bin 0 -> 215 bytes .../res/drawable-xhdpi/ic_action_play.png | Bin 0 -> 399 bytes .../res/drawable-xhdpi/ic_action_previous.png | Bin 0 -> 354 bytes .../res/drawable-xhdpi/ic_attach_contact.png | Bin 1399 -> 0 bytes .../res/drawable-xhdpi/ic_attach_gallery.png | Bin 1335 -> 0 bytes .../res/drawable-xhdpi/ic_attach_location.png | Bin 1607 -> 0 bytes .../res/drawable-xhdpi/ic_attach_music.png | Bin 1272 -> 0 bytes .../res/drawable-xhdpi/ic_attach_photo.png | Bin 1588 -> 0 bytes .../res/drawable-xhdpi/ic_attach_photobig.png | Bin 1921 -> 0 bytes .../res/drawable-xhdpi/ic_attach_video.png | Bin 1032 -> 0 bytes .../main/res/drawable-xhdpi/menu_pause.png | Bin 0 -> 1119 bytes .../src/main/res/drawable-xhdpi/menu_play.png | Bin 0 -> 1266 bytes .../src/main/res/drawable-xhdpi/nocover.png | Bin 0 -> 2563 bytes .../main/res/drawable-xhdpi/nocover_big.9.png | Bin 0 -> 2822 bytes .../res/drawable-xhdpi/nocover_small.9.png | Bin 0 -> 1307 bytes .../src/main/res/drawable-xhdpi/pl_back.png | Bin 0 -> 1199 bytes .../src/main/res/drawable-xhdpi/pl_next.png | Bin 0 -> 1390 bytes .../res/drawable-xhdpi/pl_next_pressed.png | Bin 0 -> 1394 bytes .../src/main/res/drawable-xhdpi/pl_pause.png | Bin 0 -> 1012 bytes .../res/drawable-xhdpi/pl_pause_pressed.png | Bin 0 -> 1004 bytes .../src/main/res/drawable-xhdpi/pl_play.png | Bin 0 -> 1437 bytes .../res/drawable-xhdpi/pl_play_pressed.png | Bin 0 -> 1449 bytes .../main/res/drawable-xhdpi/pl_previous.png | Bin 0 -> 1380 bytes .../drawable-xhdpi/pl_previous_pressed.png | Bin 0 -> 1384 bytes .../src/main/res/drawable-xhdpi/pl_repeat.png | Bin 0 -> 1161 bytes .../res/drawable-xhdpi/pl_repeat1_active.png | Bin 0 -> 1207 bytes .../res/drawable-xhdpi/pl_repeat_active.png | Bin 0 -> 1170 bytes .../main/res/drawable-xhdpi/pl_shuffle.png | Bin 0 -> 1392 bytes .../res/drawable-xhdpi/pl_shuffle_active.png | Bin 0 -> 1395 bytes .../src/main/res/drawable-xhdpi/player.png | Bin 0 -> 1573 bytes .../src/main/res/drawable-xhdpi/player1.png | Bin 858 -> 0 bytes .../res/drawable-xhdpi/player1_pressed.png | Bin 1470 -> 0 bytes .../src/main/res/drawable-xhdpi/player2.png | Bin 844 -> 0 bytes .../res/drawable-xhdpi/player2_pressed.png | Bin 1482 -> 0 bytes .../res/drawable-xhdpi/sheet_shadow.9.png | Bin 0 -> 419 bytes ..._attach_music_big.png => attach_audio.png} | Bin .../drawable-xxhdpi/attach_audio_pressed.png | Bin 0 -> 5237 bytes ...attach_photo_big.png => attach_camera.png} | Bin .../drawable-xxhdpi/attach_camera_pressed.png | Bin 0 -> 6375 bytes ...ach_contact_big.png => attach_contact.png} | Bin .../attach_contact_pressed.png | Bin 0 -> 4959 bytes ...ic_attach_file_big.png => attach_file.png} | Bin .../drawable-xxhdpi/attach_file_pressed.png | Bin 0 -> 4269 bytes ...ach_gallery_big.png => attach_gallery.png} | Bin .../attach_gallery_pressed.png | Bin 0 -> 4444 bytes ...c_attach_hide_big.png => attach_hide1.png} | Bin .../drawable-xxhdpi/attach_hide1_pressed.png | Bin 0 -> 3648 bytes ...ach_hide_big_icon.png => attach_hide2.png} | Bin ...h_location_big.png => attach_location.png} | Bin .../attach_location_pressed.png | Bin 0 -> 5429 bytes ...c_attach_send_big.png => attach_send1.png} | Bin .../drawable-xxhdpi/attach_send1_pressed.png | Bin 0 -> 3650 bytes ...ach_send_big_icon.png => attach_send2.png} | Bin ..._attach_video_big.png => attach_video.png} | Bin .../drawable-xxhdpi/attach_video_pressed.png | Bin 0 -> 3903 bytes .../res/drawable-xxhdpi/audiosend_pause.png | Bin 0 -> 3224 bytes .../res/drawable-xxhdpi/audiosend_play.png | Bin 0 -> 4247 bytes .../res/drawable-xxhdpi/bluecounter.9.png | Bin 0 -> 961 bytes .../res/drawable-xxhdpi/ic_action_next.png | Bin 0 -> 408 bytes .../res/drawable-xxhdpi/ic_action_pause.png | Bin 0 -> 293 bytes .../res/drawable-xxhdpi/ic_action_play.png | Bin 0 -> 543 bytes .../drawable-xxhdpi/ic_action_previous.png | Bin 0 -> 447 bytes .../res/drawable-xxhdpi/ic_attach_contact.png | Bin 1648 -> 0 bytes .../res/drawable-xxhdpi/ic_attach_gallery.png | Bin 1552 -> 0 bytes .../drawable-xxhdpi/ic_attach_location.png | Bin 1993 -> 0 bytes .../res/drawable-xxhdpi/ic_attach_music.png | Bin 1496 -> 0 bytes .../res/drawable-xxhdpi/ic_attach_photo.png | Bin 1949 -> 0 bytes .../drawable-xxhdpi/ic_attach_photobig.png | Bin 2487 -> 0 bytes .../res/drawable-xxhdpi/ic_attach_video.png | Bin 1092 -> 0 bytes .../main/res/drawable-xxhdpi/menu_pause.png | Bin 0 -> 1073 bytes .../main/res/drawable-xxhdpi/menu_play.png | Bin 0 -> 1318 bytes .../src/main/res/drawable-xxhdpi/nocover.png | Bin 0 -> 3273 bytes .../res/drawable-xxhdpi/nocover_big.9.png | Bin 0 -> 2944 bytes .../res/drawable-xxhdpi/nocover_small.9.png | Bin 0 -> 1772 bytes .../src/main/res/drawable-xxhdpi/pl_back.png | Bin 0 -> 1317 bytes .../src/main/res/drawable-xxhdpi/pl_next.png | Bin 0 -> 1542 bytes .../res/drawable-xxhdpi/pl_next_pressed.png | Bin 0 -> 1546 bytes .../src/main/res/drawable-xxhdpi/pl_pause.png | Bin 0 -> 1040 bytes .../res/drawable-xxhdpi/pl_pause_pressed.png | Bin 0 -> 1037 bytes .../src/main/res/drawable-xxhdpi/pl_play.png | Bin 0 -> 1759 bytes .../res/drawable-xxhdpi/pl_play_pressed.png | Bin 0 -> 1759 bytes .../main/res/drawable-xxhdpi/pl_previous.png | Bin 0 -> 1505 bytes .../drawable-xxhdpi/pl_previous_pressed.png | Bin 0 -> 1509 bytes .../main/res/drawable-xxhdpi/pl_repeat.png | Bin 0 -> 1263 bytes .../res/drawable-xxhdpi/pl_repeat1_active.png | Bin 0 -> 1320 bytes .../res/drawable-xxhdpi/pl_repeat_active.png | Bin 0 -> 1273 bytes .../main/res/drawable-xxhdpi/pl_shuffle.png | Bin 0 -> 1718 bytes .../res/drawable-xxhdpi/pl_shuffle_active.png | Bin 0 -> 1712 bytes .../src/main/res/drawable-xxhdpi/player.png | Bin 0 -> 2047 bytes .../src/main/res/drawable-xxhdpi/player1.png | Bin 1312 -> 0 bytes .../res/drawable-xxhdpi/player1_pressed.png | Bin 2355 -> 0 bytes .../src/main/res/drawable-xxhdpi/player2.png | Bin 1290 -> 0 bytes .../res/drawable-xxhdpi/player2_pressed.png | Bin 2436 -> 0 bytes .../res/drawable-xxhdpi/sheet_shadow.9.png | Bin 0 -> 703 bytes .../main/res/drawable/attach_audio_states.xml | 6 + .../res/drawable/attach_camera_states.xml | 6 + .../res/drawable/attach_contact_states.xml | 6 + .../main/res/drawable/attach_file_states.xml | 6 + .../res/drawable/attach_gallery_states.xml | 6 + .../main/res/drawable/attach_hide_states.xml | 6 + .../res/drawable/attach_location_states.xml | 6 + .../main/res/drawable/attach_send_states.xml | 6 + .../main/res/drawable/attach_video_states.xml | 6 + .../main/res/drawable/bar_selector_audio.xml | 19 + .../src/main/res/drawable/floating_states.xml | 9 - .../main/res/drawable/player_next_states.xml | 6 + .../main/res/drawable/player_pause_states.xml | 6 + .../main/res/drawable/player_play_states.xml | 6 + .../main/res/drawable/player_prev_states.xml | 6 + .../main/res/drawable/search_dark_states.xml | 7 - .../main/res/drawable/search_light_states.xml | 7 - .../res/layout/player_big_notification.xml | 122 + .../res/layout/player_small_notification.xml | 116 + .../src/main/res/values-ar/strings.xml | 11 +- .../src/main/res/values-de/strings.xml | 13 +- .../src/main/res/values-es/strings.xml | 11 +- .../src/main/res/values-it/strings.xml | 45 +- .../src/main/res/values-ko/strings.xml | 11 +- .../src/main/res/values-nl/strings.xml | 11 +- .../src/main/res/values-pt-rBR/strings.xml | 11 +- .../src/main/res/values-pt-rPT/strings.xml | 11 +- TMessagesProj/src/main/res/values/strings.xml | 12 +- TMessagesProj/src/main/res/values/styles.xml | 4 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 422 files changed, 10937 insertions(+), 1587 deletions(-) create mode 100644 TMessagesProj/src/main/java/org/telegram/android/MusicPlayerReceiver.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/MusicPlayerService.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/AudioInfo.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/M4AInfo.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Atom.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Box.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Input.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v1Genre.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v1Info.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2DataInput.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Encoding.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Exception.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2FrameBody.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2FrameHeader.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Info.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2TagBody.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2TagHeader.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Exception.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Frame.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Info.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Input.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/util/PositionInputStream.java create mode 100755 TMessagesProj/src/main/java/org/telegram/android/audioinfo/util/RangeInputStream.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchHelper.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtil.java create mode 100644 TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtilImpl.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java rename TMessagesProj/src/main/java/org/telegram/ui/Components/{PhotoPickerBottomLayout.java => PickerBottomLayout.java} (81%) create mode 100644 TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java rename TMessagesProj/src/main/java/org/telegram/ui/{MessagesActivity.java => DialogsActivity.java} (98%) create mode 100644 TMessagesProj/src/main/res/anim/no_animation.xml rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_music_big.png => attach_audio.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_audio_pressed.png rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_photo_big.png => attach_camera.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_camera_pressed.png rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_contact_big.png => attach_contact.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_contact_pressed.png rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_file_big.png => attach_file.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_file_pressed.png rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_gallery_big.png => attach_gallery.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_gallery_pressed.png rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_hide_big.png => attach_hide1.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_hide1_pressed.png rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_hide_big_icon.png => attach_hide2.png} (100%) rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_location_big.png => attach_location.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_location_pressed.png rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_send_big.png => attach_send1.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_send1_pressed.png rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_send_big_icon.png => attach_send2.png} (100%) rename TMessagesProj/src/main/res/drawable-hdpi/{ic_attach_video_big.png => attach_video.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/attach_video_pressed.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/audiosend_pause.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_action_next.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_action_pause.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_action_play.png create mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_action_previous.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photo.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photobig.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/ic_attach_video.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_pause.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/menu_play.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/nocover.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/nocover_small.9.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_back.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_next.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_next_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_pause.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_pause_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_play.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_play_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_previous_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1_active.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_repeat_active.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle_active.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/player.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/player1.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/player1_pressed.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/player2.png delete mode 100755 TMessagesProj/src/main/res/drawable-hdpi/player2_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow.9.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_music_big.png => attach_audio.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_audio_pressed.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_photo_big.png => attach_camera.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_camera_pressed.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_contact_big.png => attach_contact.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_contact_pressed.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_file_big.png => attach_file.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_file_pressed.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_gallery_big.png => attach_gallery.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_gallery_pressed.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_hide_big.png => attach_hide1.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_hide1_pressed.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_hide_big_icon.png => attach_hide2.png} (100%) rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_location_big.png => attach_location.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_location_pressed.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_send_big.png => attach_send1.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_send1_pressed.png rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_send_big_icon.png => attach_send2.png} (100%) rename TMessagesProj/src/main/res/drawable-mdpi/{ic_attach_video_big.png => attach_video.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/attach_video_pressed.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/bluecounter.9.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_action_next.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_action_pause.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_action_play.png create mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_action_previous.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_attach_contact.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photobig.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/ic_attach_video.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/menu_play.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/nocover.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/nocover_small.9.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_back.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_next.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_next_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_pause_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_play.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_play_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_previous_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1_active.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_repeat_active.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle_active.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/player.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/player1.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/player1_pressed.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/player2.png delete mode 100755 TMessagesProj/src/main/res/drawable-mdpi/player2_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow.9.png create mode 100644 TMessagesProj/src/main/res/drawable-v21/bar_selector_audio.xml rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_music_big.png => attach_audio.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_audio_pressed.png rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_photo_big.png => attach_camera.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_camera_pressed.png rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_contact_big.png => attach_contact.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_contact_pressed.png rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_file_big.png => attach_file.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_file_pressed.png rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_gallery_big.png => attach_gallery.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery_pressed.png rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_hide_big.png => attach_hide1.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1_pressed.png rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_hide_big_icon.png => attach_hide2.png} (100%) rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_location_big.png => attach_location.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_location_pressed.png rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_send_big.png => attach_send1.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_send1_pressed.png rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_send_big_icon.png => attach_send2.png} (100%) rename TMessagesProj/src/main/res/drawable-xhdpi/{ic_attach_video_big.png => attach_video.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/attach_video_pressed.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/audiosend_pause.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/audiosend_play.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/bluecounter.9.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_action_next.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_action_pause.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_action_play.png create mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_action_previous.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_contact.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_location.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photo.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photobig.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_video.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/nocover.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/nocover_small.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_back.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_next_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_pause_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_play_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_previous.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_previous_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat1_active.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat_active.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle_active.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/player.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/player1.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/player1_pressed.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/player2.png delete mode 100755 TMessagesProj/src/main/res/drawable-xhdpi/player2_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow.9.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_music_big.png => attach_audio.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio_pressed.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_photo_big.png => attach_camera.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera_pressed.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_contact_big.png => attach_contact.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact_pressed.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_file_big.png => attach_file.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_file_pressed.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_gallery_big.png => attach_gallery.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery_pressed.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_hide_big.png => attach_hide1.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1_pressed.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_hide_big_icon.png => attach_hide2.png} (100%) rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_location_big.png => attach_location.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_location_pressed.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_send_big.png => attach_send1.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1_pressed.png rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_send_big_icon.png => attach_send2.png} (100%) rename TMessagesProj/src/main/res/drawable-xxhdpi/{ic_attach_video_big.png => attach_video.png} (100%) create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/attach_video_pressed.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_play.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/bluecounter.9.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_next.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_pause.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_play.png create mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_previous.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_contact.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_location.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_music.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photobig.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/nocover_big.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_back.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_next.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_next_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_play_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat1_active.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat_active.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle_active.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/player.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/player1.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/player1_pressed.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/player2.png delete mode 100755 TMessagesProj/src/main/res/drawable-xxhdpi/player2_pressed.png create mode 100644 TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png create mode 100644 TMessagesProj/src/main/res/drawable/attach_audio_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/attach_camera_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/attach_contact_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/attach_file_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/attach_gallery_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/attach_hide_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/attach_location_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/attach_send_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/attach_video_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/bar_selector_audio.xml create mode 100644 TMessagesProj/src/main/res/drawable/player_next_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/player_pause_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/player_play_states.xml create mode 100644 TMessagesProj/src/main/res/drawable/player_prev_states.xml delete mode 100644 TMessagesProj/src/main/res/drawable/search_dark_states.xml delete mode 100644 TMessagesProj/src/main/res/drawable/search_light_states.xml create mode 100755 TMessagesProj/src/main/res/layout/player_big_notification.xml create mode 100755 TMessagesProj/src/main/res/layout/player_small_notification.xml diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 0be48dbc6..207b7a544 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -73,7 +73,7 @@ android { defaultConfig { minSdkVersion 8 targetSdkVersion 22 - versionCode 572 - versionName "3.0.1" + versionCode 580 + versionName "3.1.1" } } diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index 2009cf46a..e5c2d138d 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -161,8 +161,20 @@ - + + + + + + + + + + + + + diff --git a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java index 573107797..357750329 100755 --- a/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java +++ b/TMessagesProj/src/main/java/org/telegram/SQLite/SQLitePreparedStatement.java @@ -8,7 +8,6 @@ package org.telegram.SQLite; -import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLog; import java.nio.ByteBuffer; @@ -30,7 +29,7 @@ public class SQLitePreparedStatement { public SQLitePreparedStatement(SQLiteDatabase db, String sql, boolean finalize) throws SQLiteException { finalizeAfterQuery = finalize; sqliteStatementHandle = prepare(db.getSQLiteHandle(), sql); - if (BuildVars.DEBUG_VERSION) { + /*if (BuildVars.DEBUG_VERSION) { if (hashMap == null) { hashMap = new HashMap<>(); } @@ -38,7 +37,7 @@ public class SQLitePreparedStatement { for (HashMap.Entry entry : hashMap.entrySet()) { FileLog.d("tmessages", "exist entry = " + entry.getValue()); } - } + }*/ } @@ -101,9 +100,9 @@ public class SQLitePreparedStatement { return; } try { - if (BuildVars.DEBUG_VERSION) { + /*if (BuildVars.DEBUG_VERSION) { hashMap.remove(this); - } + }*/ isFinalized = true; finalize(sqliteStatementHandle); } catch (SQLiteException e) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java index 89992d69d..681294e85 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/android/AndroidUtilities.java @@ -542,16 +542,6 @@ public class AndroidUtilities { return 0; } - public static int getCurrentActionBarHeight() { - if (isTablet()) { - return dp(64); - } else if (ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { - return dp(48); - } else { - return dp(56); - } - } - public static Point getRealScreenSize() { Point size = new Point(); try { diff --git a/TMessagesProj/src/main/java/org/telegram/android/AnimationCompat/AnimatorSetProxy.java b/TMessagesProj/src/main/java/org/telegram/android/AnimationCompat/AnimatorSetProxy.java index be5993931..c41b14bfa 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/AnimationCompat/AnimatorSetProxy.java +++ b/TMessagesProj/src/main/java/org/telegram/android/AnimationCompat/AnimatorSetProxy.java @@ -66,13 +66,13 @@ public class AnimatorSetProxy { public void playTogether(ArrayList items) { if (View10.NEED_PROXY) { - ArrayList animators = new ArrayList(); + ArrayList animators = new ArrayList<>(); for (Object obj : items) { animators.add((Animator10)obj); } ((AnimatorSet10) animatorSet).playTogether(animators); } else { - ArrayList animators = new ArrayList(); + ArrayList animators = new ArrayList<>(); for (Object obj : items) { animators.add((Animator)obj); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/ContactsController.java b/TMessagesProj/src/main/java/org/telegram/android/ContactsController.java index a4bb1c349..4e492ceaf 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ContactsController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ContactsController.java @@ -20,6 +20,7 @@ import android.database.Cursor; import android.net.Uri; import android.provider.BaseColumns; import android.provider.ContactsContract; +import android.text.TextUtils; import android.util.SparseArray; import org.telegram.PhoneFormat.PhoneFormat; @@ -330,7 +331,7 @@ public class ContactsController { ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver(); HashMap shortContacts = new HashMap<>(); - StringBuilder ids = new StringBuilder(); + ArrayList idsArr = new ArrayList<>(); Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null); if (pCur != null) { if (pCur.getCount() > 0) { @@ -355,10 +356,9 @@ public class ContactsController { } Integer id = pCur.getInt(0); - if (ids.length() != 0) { - ids.append(","); + if (!idsArr.contains(id)) { + idsArr.add(id); } - ids.append(id); int type = pCur.getInt(2); Contact contact = contactsMap.get(id); @@ -392,8 +392,9 @@ public class ContactsController { } pCur.close(); } + String ids = TextUtils.join(",", idsArr); - pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids.toString() + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null); + pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null); if (pCur != null && pCur.getCount() > 0) { while (pCur.moveToNext()) { int id = pCur.getInt(0); @@ -474,6 +475,23 @@ public class ContactsController { FileLog.e("tmessages", e); contactsMap.clear(); } + if (BuildVars.DEBUG_VERSION) { + for (HashMap.Entry entry : contactsMap.entrySet()) { + Contact contact = entry.getValue(); + FileLog.e("tmessages", "contact = " + contact.first_name + " " + contact.last_name); + if (contact.first_name.length() == 0 && contact.last_name.length() == 0 && contact.phones.size() > 0) { + FileLog.e("tmessages", "warning, empty name for contact = " + contact.id); + } + FileLog.e("tmessages", "phones:"); + for (String s : contact.phones) { + FileLog.e("tmessages", "phone = " + s); + } + FileLog.e("tmessages", "short phones:"); + for (String s : contact.shortPhones) { + FileLog.e("tmessages", "short phone = " + s); + } + } + } return contactsMap; } @@ -569,7 +587,7 @@ public class ContactsController { } } - boolean nameChanged = existing != null && (!existing.first_name.equals(value.first_name) || !existing.last_name.equals(value.last_name)); + boolean nameChanged = existing != null && (value.first_name.length() != 0 && !existing.first_name.equals(value.first_name) || value.last_name != null && !existing.last_name.equals(value.last_name)); if (existing == null || nameChanged) { for (int a = 0; a < value.phones.size(); a++) { String sphone = value.shortPhones.get(a); @@ -607,8 +625,12 @@ public class ContactsController { int index = existing.shortPhones.indexOf(sphone); if (index == -1) { if (request) { - if (contactsByPhone.containsKey(sphone)) { - continue; + TLRPC.TL_contact contact = contactsByPhone.get(sphone); + if (contact != null) { + TLRPC.User user = MessagesController.getInstance().getUser(contact.user_id); + if (user == null || user.first_name != null && user.first_name.length() != 0 || user.last_name != null && user.last_name.length() != 0) { + continue; + } } TLRPC.TL_inputPhoneContact imp = new TLRPC.TL_inputPhoneContact(); @@ -702,8 +724,12 @@ public class ContactsController { int id = pair.getKey(); for (int a = 0; a < value.phones.size(); a++) { String phone = value.shortPhones.get(a); - if (contactsByPhone.containsKey(phone)) { - continue; + TLRPC.TL_contact contact = contactsByPhone.get(phone); + if (contact != null) { + TLRPC.User user = MessagesController.getInstance().getUser(contact.user_id); + if (user == null || user.first_name != null && user.first_name.length() != 0 || user.last_name != null && user.last_name.length() != 0) { + continue; + } } TLRPC.TL_inputPhoneContact imp = new TLRPC.TL_inputPhoneContact(); imp.client_id = id; @@ -721,9 +747,9 @@ public class ContactsController { if (!toImport.isEmpty()) { if (BuildVars.DEBUG_VERSION) { FileLog.e("tmessages", "start import contacts"); -// for (TLRPC.TL_inputPhoneContact contact : toImport) { -// FileLog.e("tmessages", "add contact " + contact.first_name + " " + contact.last_name + " " + contact.phone); -// } + for (TLRPC.TL_inputPhoneContact contact : toImport) { + FileLog.e("tmessages", "add contact " + contact.first_name + " " + contact.last_name + " " + contact.phone); + } } final int count = (int)Math.ceil(toImport.size() / 500.0f); for (int a = 0; a < count; a++) { @@ -743,9 +769,9 @@ public class ContactsController { } TLRPC.TL_contacts_importedContacts res = (TLRPC.TL_contacts_importedContacts)response; if (BuildVars.DEBUG_VERSION) { -// for (TLRPC.User user : res.users) { -// FileLog.e("tmessages", "received user " + user.first_name + " " + user.last_name + " " + user.phone); -// } + for (TLRPC.User user : res.users) { + FileLog.e("tmessages", "received user " + user.first_name + " " + user.last_name + " " + user.phone); + } } MessagesStorage.getInstance().putUsersAndChats(res.users, null, true, true); ArrayList cArr = new ArrayList<>(); @@ -903,9 +929,9 @@ public class ContactsController { if (user != null) { usersDict.put(user.id, user); -// if (BuildVars.DEBUG_VERSION) { -// FileLog.e("tmessages", "loaded user contact " + user.first_name + " " + user.last_name + " " + user.phone); -// } + if (BuildVars.DEBUG_VERSION) { + FileLog.e("tmessages", "loaded user contact " + user.first_name + " " + user.last_name + " " + user.phone); + } } } @@ -1524,9 +1550,9 @@ public class ContactsController { contactsParams.add(c); req.contacts = contactsParams; req.replace = false; -// if (BuildVars.DEBUG_VERSION) { -// FileLog.e("tmessages", "add contact " + user.first_name + " " + user.last_name + " " + user.phone); -// } + if (BuildVars.DEBUG_VERSION) { + FileLog.e("tmessages", "add contact " + user.first_name + " " + user.last_name + " " + user.phone); + } ConnectionsManager.getInstance().performRpc(req, new RPCRequest.RPCRequestDelegate() { @Override public void run(TLObject response, TLRPC.TL_error error) { @@ -1536,11 +1562,11 @@ public class ContactsController { final TLRPC.TL_contacts_importedContacts res = (TLRPC.TL_contacts_importedContacts)response; MessagesStorage.getInstance().putUsersAndChats(res.users, null, true, true); -// if (BuildVars.DEBUG_VERSION) { -// for (TLRPC.User user : res.users) { -// FileLog.e("tmessages", "received user " + user.first_name + " " + user.last_name + " " + user.phone); -// } -// } + if (BuildVars.DEBUG_VERSION) { + for (TLRPC.User user : res.users) { + FileLog.e("tmessages", "received user " + user.first_name + " " + user.last_name + " " + user.phone); + } + } for (final TLRPC.User u : res.users) { Utilities.phoneBookQueue.postRunnable(new Runnable() { diff --git a/TMessagesProj/src/main/java/org/telegram/android/Emoji.java b/TMessagesProj/src/main/java/org/telegram/android/Emoji.java index 71a5e9b72..7dd282aae 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/android/Emoji.java @@ -33,13 +33,13 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.ApplicationLoader; public class Emoji { - private static HashMap rects = new HashMap<>(); - private static int drawImgSize; + private static HashMap rects = new HashMap<>(); + private static int drawImgSize; private static int bigImgSize; - private static boolean inited = false; - private static Paint placeholderPaint; - private static Bitmap emojiBmp[] = new Bitmap[5]; - private static boolean loadingEmoji[] = new boolean[5]; + private static boolean inited = false; + private static Paint placeholderPaint; + private static Bitmap emojiBmp[] = new Bitmap[5]; + private static boolean loadingEmoji[] = new boolean[5]; private static final int[] cols = { 13, 10, 15, 10, 14 @@ -60,139 +60,144 @@ public class Emoji { 0x2B1C, 0x2B50, 0x2B55, 0x3030, 0x303D, 0x3297, 0x3299 }; - public static long[][] data = { + public static long[][] data = { new long[] {}, new long[]//189 - {0x00000000D83DDE04L, 0x00000000D83DDE03L, 0x00000000D83DDE00L, 0x00000000D83DDE0AL, 0x000000000000263AL, 0x00000000D83DDE09L, 0x00000000D83DDE0DL, - 0x00000000D83DDE18L, 0x00000000D83DDE1AL, 0x00000000D83DDE17L, 0x00000000D83DDE19L, 0x00000000D83DDE1CL, 0x00000000D83DDE1DL, 0x00000000D83DDE1BL, - 0x00000000D83DDE33L, 0x00000000D83DDE01L, 0x00000000D83DDE14L, 0x00000000D83DDE0CL, 0x00000000D83DDE12L, 0x00000000D83DDE1EL, 0x00000000D83DDE23L, - 0x00000000D83DDE22L, 0x00000000D83DDE02L, 0x00000000D83DDE2DL, 0x00000000D83DDE2AL, 0x00000000D83DDE25L, 0x00000000D83DDE30L, 0x00000000D83DDE05L, - 0x00000000D83DDE13L, 0x00000000D83DDE29L, 0x00000000D83DDE2BL, 0x00000000D83DDE28L, 0x00000000D83DDE31L, 0x00000000D83DDE20L, 0x00000000D83DDE21L, - 0x00000000D83DDE24L, 0x00000000D83DDE16L, 0x00000000D83DDE06L, 0x00000000D83DDE0BL, 0x00000000D83DDE37L, 0x00000000D83DDE0EL, 0x00000000D83DDE34L, - 0x00000000D83DDE35L, 0x00000000D83DDE32L, 0x00000000D83DDE1FL, 0x00000000D83DDE26L, 0x00000000D83DDE27L, 0x00000000D83DDE08L, 0x00000000D83DDC7FL, - 0x00000000D83DDE2EL, 0x00000000D83DDE2CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L, 0x00000000D83DDE2FL, 0x00000000D83DDE36L, 0x00000000D83DDE07L, - 0x00000000D83DDE0FL, 0x00000000D83DDE11L, 0x00000000D83DDC72L, 0x00000000D83DDC73L, 0x00000000D83DDC6EL, 0x00000000D83DDC77L, 0x00000000D83DDC82L, - 0x00000000D83DDC76L, 0x00000000D83DDC66L, 0x00000000D83DDC67L, 0x00000000D83DDC68L, 0x00000000D83DDC69L, 0x00000000D83DDC74L, 0x00000000D83DDC75L, - 0x00000000D83DDC71L, 0x00000000D83DDC7CL, 0x00000000D83DDC78L, 0x00000000D83DDE3AL, 0x00000000D83DDE38L, 0x00000000D83DDE3BL, 0x00000000D83DDE3DL, - 0x00000000D83DDE3CL, 0x00000000D83DDE40L, 0x00000000D83DDE3FL, 0x00000000D83DDE39L, 0x00000000D83DDE3EL, 0x00000000D83DDC79L, 0x00000000D83DDC7AL, - 0x00000000D83DDE48L, 0x00000000D83DDE49L, 0x00000000D83DDE4AL, 0x00000000D83DDC80L, 0x00000000D83DDC7DL, 0x00000000D83DDCA9L, 0x00000000D83DDD25L, - 0x0000000000002728L, 0x00000000D83CDF1FL, 0x00000000D83DDCABL, 0x00000000D83DDCA5L, 0x00000000D83DDCA2L, 0x00000000D83DDCA6L, 0x00000000D83DDCA7L, - 0x00000000D83DDCA4L, 0x00000000D83DDCA8L, 0x00000000D83DDC42L, 0x00000000D83DDC40L, 0x00000000D83DDC43L, 0x00000000D83DDC45L, 0x00000000D83DDC44L, - 0x00000000D83DDC4DL, 0x00000000D83DDC4EL, 0x00000000D83DDC4CL, 0x00000000D83DDC4AL, 0x000000000000270AL, 0x000000000000270CL, 0x00000000D83DDC4BL, - 0x000000000000270BL, 0x00000000D83DDC50L, 0x00000000D83DDC46L, 0x00000000D83DDC47L, 0x00000000D83DDC49L, 0x00000000D83DDC48L, 0x00000000D83DDE4CL, - 0x00000000D83DDE4FL, 0x000000000000261DL, 0x00000000D83DDC4FL, 0x00000000D83DDCAAL, 0x00000000D83DDEB6L, 0x00000000D83CDFC3L, 0x00000000D83DDC83L, - 0x00000000D83DDC6BL, 0x00000000D83DDC6AL, 0x00000000D83DDC6CL, 0x00000000D83DDC6DL, 0x00000000D83DDC8FL, 0x00000000D83DDC91L, 0x00000000D83DDC6FL, - 0x00000000D83DDE46L, 0x00000000D83DDE45L, 0x00000000D83DDC81L, 0x00000000D83DDE4BL, 0x00000000D83DDC86L, 0x00000000D83DDC87L, 0x00000000D83DDC85L, - 0x00000000D83DDC70L, 0x00000000D83DDE4EL, 0x00000000D83DDE4DL, 0x00000000D83DDE47L, 0x00000000D83CDFA9L, 0x00000000D83DDC51L, 0x00000000D83DDC52L, - 0x00000000D83DDC5FL, 0x00000000D83DDC5EL, 0x00000000D83DDC61L, 0x00000000D83DDC60L, 0x00000000D83DDC62L, 0x00000000D83DDC55L, 0x00000000D83DDC54L, - 0x00000000D83DDC5AL, 0x00000000D83DDC57L, 0x00000000D83CDFBDL, 0x00000000D83DDC56L, 0x00000000D83DDC58L, 0x00000000D83DDC59L, 0x00000000D83DDCBCL, - 0x00000000D83DDC5CL, 0x00000000D83DDC5DL, 0x00000000D83DDC5BL, 0x00000000D83DDC53L, 0x00000000D83CDF80L, 0x00000000D83CDF02L, 0x00000000D83DDC84L, - 0x00000000D83DDC9BL, 0x00000000D83DDC99L, 0x00000000D83DDC9CL, 0x00000000D83DDC9AL, 0x0000000000002764L, 0x00000000D83DDC94L, 0x00000000D83DDC97L, - 0x00000000D83DDC93L, 0x00000000D83DDC95L, 0x00000000D83DDC96L, 0x00000000D83DDC9EL, 0x00000000D83DDC98L, 0x00000000D83DDC8CL, 0x00000000D83DDC8BL, - 0x00000000D83DDC8DL, 0x00000000D83DDC8EL, 0x00000000D83DDC64L, 0x00000000D83DDC65L, 0x00000000D83DDCACL, 0x00000000D83DDC63L, 0x00000000D83DDCADL}, + { + 0x00000000D83DDE04L, 0x00000000D83DDE03L, 0x00000000D83DDE00L, 0x00000000D83DDE0AL, 0x000000000000263AL, 0x00000000D83DDE09L, 0x00000000D83DDE0DL, + 0x00000000D83DDE18L, 0x00000000D83DDE1AL, 0x00000000D83DDE17L, 0x00000000D83DDE19L, 0x00000000D83DDE1CL, 0x00000000D83DDE1DL, 0x00000000D83DDE1BL, + 0x00000000D83DDE33L, 0x00000000D83DDE01L, 0x00000000D83DDE14L, 0x00000000D83DDE0CL, 0x00000000D83DDE12L, 0x00000000D83DDE1EL, 0x00000000D83DDE23L, + 0x00000000D83DDE22L, 0x00000000D83DDE02L, 0x00000000D83DDE2DL, 0x00000000D83DDE2AL, 0x00000000D83DDE25L, 0x00000000D83DDE30L, 0x00000000D83DDE05L, + 0x00000000D83DDE13L, 0x00000000D83DDE29L, 0x00000000D83DDE2BL, 0x00000000D83DDE28L, 0x00000000D83DDE31L, 0x00000000D83DDE20L, 0x00000000D83DDE21L, + 0x00000000D83DDE24L, 0x00000000D83DDE16L, 0x00000000D83DDE06L, 0x00000000D83DDE0BL, 0x00000000D83DDE37L, 0x00000000D83DDE0EL, 0x00000000D83DDE34L, + 0x00000000D83DDE35L, 0x00000000D83DDE32L, 0x00000000D83DDE1FL, 0x00000000D83DDE26L, 0x00000000D83DDE27L, 0x00000000D83DDE08L, 0x00000000D83DDC7FL, + 0x00000000D83DDE2EL, 0x00000000D83DDE2CL, 0x00000000D83DDE10L, 0x00000000D83DDE15L, 0x00000000D83DDE2FL, 0x00000000D83DDE36L, 0x00000000D83DDE07L, + 0x00000000D83DDE0FL, 0x00000000D83DDE11L, 0x00000000D83DDC72L, 0x00000000D83DDC73L, 0x00000000D83DDC6EL, 0x00000000D83DDC77L, 0x00000000D83DDC82L, + 0x00000000D83DDC76L, 0x00000000D83DDC66L, 0x00000000D83DDC67L, 0x00000000D83DDC68L, 0x00000000D83DDC69L, 0x00000000D83DDC74L, 0x00000000D83DDC75L, + 0x00000000D83DDC71L, 0x00000000D83DDC7CL, 0x00000000D83DDC78L, 0x00000000D83DDE3AL, 0x00000000D83DDE38L, 0x00000000D83DDE3BL, 0x00000000D83DDE3DL, + 0x00000000D83DDE3CL, 0x00000000D83DDE40L, 0x00000000D83DDE3FL, 0x00000000D83DDE39L, 0x00000000D83DDE3EL, 0x00000000D83DDC79L, 0x00000000D83DDC7AL, + 0x00000000D83DDE48L, 0x00000000D83DDE49L, 0x00000000D83DDE4AL, 0x00000000D83DDC80L, 0x00000000D83DDC7DL, 0x00000000D83DDCA9L, 0x00000000D83DDD25L, + 0x0000000000002728L, 0x00000000D83CDF1FL, 0x00000000D83DDCABL, 0x00000000D83DDCA5L, 0x00000000D83DDCA2L, 0x00000000D83DDCA6L, 0x00000000D83DDCA7L, + 0x00000000D83DDCA4L, 0x00000000D83DDCA8L, 0x00000000D83DDC42L, 0x00000000D83DDC40L, 0x00000000D83DDC43L, 0x00000000D83DDC45L, 0x00000000D83DDC44L, + 0x00000000D83DDC4DL, 0x00000000D83DDC4EL, 0x00000000D83DDC4CL, 0x00000000D83DDC4AL, 0x000000000000270AL, 0x000000000000270CL, 0x00000000D83DDC4BL, + 0x000000000000270BL, 0x00000000D83DDC50L, 0x00000000D83DDC46L, 0x00000000D83DDC47L, 0x00000000D83DDC49L, 0x00000000D83DDC48L, 0x00000000D83DDE4CL, + 0x00000000D83DDE4FL, 0x000000000000261DL, 0x00000000D83DDC4FL, 0x00000000D83DDCAAL, 0x00000000D83DDEB6L, 0x00000000D83CDFC3L, 0x00000000D83DDC83L, + 0x00000000D83DDC6BL, 0x00000000D83DDC6AL, 0x00000000D83DDC6CL, 0x00000000D83DDC6DL, 0x00000000D83DDC8FL, 0x00000000D83DDC91L, 0x00000000D83DDC6FL, + 0x00000000D83DDE46L, 0x00000000D83DDE45L, 0x00000000D83DDC81L, 0x00000000D83DDE4BL, 0x00000000D83DDC86L, 0x00000000D83DDC87L, 0x00000000D83DDC85L, + 0x00000000D83DDC70L, 0x00000000D83DDE4EL, 0x00000000D83DDE4DL, 0x00000000D83DDE47L, 0x00000000D83CDFA9L, 0x00000000D83DDC51L, 0x00000000D83DDC52L, + 0x00000000D83DDC5FL, 0x00000000D83DDC5EL, 0x00000000D83DDC61L, 0x00000000D83DDC60L, 0x00000000D83DDC62L, 0x00000000D83DDC55L, 0x00000000D83DDC54L, + 0x00000000D83DDC5AL, 0x00000000D83DDC57L, 0x00000000D83CDFBDL, 0x00000000D83DDC56L, 0x00000000D83DDC58L, 0x00000000D83DDC59L, 0x00000000D83DDCBCL, + 0x00000000D83DDC5CL, 0x00000000D83DDC5DL, 0x00000000D83DDC5BL, 0x00000000D83DDC53L, 0x00000000D83CDF80L, 0x00000000D83CDF02L, 0x00000000D83DDC84L, + 0x00000000D83DDC9BL, 0x00000000D83DDC99L, 0x00000000D83DDC9CL, 0x00000000D83DDC9AL, 0x0000000000002764L, 0x00000000D83DDC94L, 0x00000000D83DDC97L, + 0x00000000D83DDC93L, 0x00000000D83DDC95L, 0x00000000D83DDC96L, 0x00000000D83DDC9EL, 0x00000000D83DDC98L, 0x00000000D83DDC8CL, 0x00000000D83DDC8BL, + 0x00000000D83DDC8DL, 0x00000000D83DDC8EL, 0x00000000D83DDC64L, 0x00000000D83DDC65L, 0x00000000D83DDCACL, 0x00000000D83DDC63L, 0x00000000D83DDCADL}, new long[]//116 - {0x00000000D83DDC36L, 0x00000000D83DDC3AL, 0x00000000D83DDC31L, 0x00000000D83DDC2DL, 0x00000000D83DDC39L, 0x00000000D83DDC30L, 0x00000000D83DDC38L, 0x00000000D83DDC2FL, - 0x00000000D83DDC28L, 0x00000000D83DDC3BL, 0x00000000D83DDC37L, 0x00000000D83DDC3DL, 0x00000000D83DDC2EL, 0x00000000D83DDC17L, 0x00000000D83DDC35L, - 0x00000000D83DDC12L, 0x00000000D83DDC34L, 0x00000000D83DDC11L, 0x00000000D83DDC18L, 0x00000000D83DDC3CL, 0x00000000D83DDC27L, 0x00000000D83DDC26L, - 0x00000000D83DDC24L, 0x00000000D83DDC25L, 0x00000000D83DDC23L, 0x00000000D83DDC14L, 0x00000000D83DDC0DL, 0x00000000D83DDC22L, 0x00000000D83DDC1BL, - 0x00000000D83DDC1DL, 0x00000000D83DDC1CL, 0x00000000D83DDC1EL, 0x00000000D83DDC0CL, 0x00000000D83DDC19L, 0x00000000D83DDC1AL, 0x00000000D83DDC20L, - 0x00000000D83DDC1FL, 0x00000000D83DDC2CL, 0x00000000D83DDC33L, 0x00000000D83DDC0BL, 0x00000000D83DDC04L, 0x00000000D83DDC0FL, 0x00000000D83DDC00L, - 0x00000000D83DDC03L, 0x00000000D83DDC05L, 0x00000000D83DDC07L, 0x00000000D83DDC09L, 0x00000000D83DDC0EL, 0x00000000D83DDC10L, 0x00000000D83DDC13L, - 0x00000000D83DDC15L, 0x00000000D83DDC16L, 0x00000000D83DDC01L, 0x00000000D83DDC02L, 0x00000000D83DDC32L, 0x00000000D83DDC21L, 0x00000000D83DDC0AL, - 0x00000000D83DDC2BL, 0x00000000D83DDC2AL, 0x00000000D83DDC06L, 0x00000000D83DDC08L, 0x00000000D83DDC29L, 0x00000000D83DDC3EL, 0x00000000D83DDC90L, - 0x00000000D83CDF38L, 0x00000000D83CDF37L, 0x00000000D83CDF40L, 0x00000000D83CDF39L, 0x00000000D83CDF3BL, 0x00000000D83CDF3AL, 0x00000000D83CDF41L, - 0x00000000D83CDF43L, 0x00000000D83CDF42L, 0x00000000D83CDF3FL, 0x00000000D83CDF3EL, 0x00000000D83CDF44L, 0x00000000D83CDF35L, 0x00000000D83CDF34L, - 0x00000000D83CDF32L, 0x00000000D83CDF33L, 0x00000000D83CDF30L, 0x00000000D83CDF31L, 0x00000000D83CDF3CL, 0x00000000D83CDF10L, 0x00000000D83CDF1EL, - 0x00000000D83CDF1DL, 0x00000000D83CDF1AL, 0x00000000D83CDF11L, 0x00000000D83CDF12L, 0x00000000D83CDF13L, 0x00000000D83CDF14L, 0x00000000D83CDF15L, - 0x00000000D83CDF16L, 0x00000000D83CDF17L, 0x00000000D83CDF18L, 0x00000000D83CDF1CL, 0x00000000D83CDF1BL, 0x00000000D83CDF19L, 0x00000000D83CDF0DL, - 0x00000000D83CDF0EL, 0x00000000D83CDF0FL, 0x00000000D83CDF0BL, 0x00000000D83CDF0CL, 0x00000000D83CDF20L, 0x0000000000002B50L, 0x0000000000002600L, - 0x00000000000026C5L, 0x0000000000002601L, 0x00000000000026A1L, 0x0000000000002614L, 0x0000000000002744L, 0x00000000000026C4L, 0x00000000D83CDF00L, - 0x00000000D83CDF01L, 0x00000000D83CDF08L, 0x00000000D83CDF0AL}, + { + 0x00000000D83DDC36L, 0x00000000D83DDC3AL, 0x00000000D83DDC31L, 0x00000000D83DDC2DL, 0x00000000D83DDC39L, 0x00000000D83DDC30L, 0x00000000D83DDC38L, 0x00000000D83DDC2FL, + 0x00000000D83DDC28L, 0x00000000D83DDC3BL, 0x00000000D83DDC37L, 0x00000000D83DDC3DL, 0x00000000D83DDC2EL, 0x00000000D83DDC17L, 0x00000000D83DDC35L, + 0x00000000D83DDC12L, 0x00000000D83DDC34L, 0x00000000D83DDC11L, 0x00000000D83DDC18L, 0x00000000D83DDC3CL, 0x00000000D83DDC27L, 0x00000000D83DDC26L, + 0x00000000D83DDC24L, 0x00000000D83DDC25L, 0x00000000D83DDC23L, 0x00000000D83DDC14L, 0x00000000D83DDC0DL, 0x00000000D83DDC22L, 0x00000000D83DDC1BL, + 0x00000000D83DDC1DL, 0x00000000D83DDC1CL, 0x00000000D83DDC1EL, 0x00000000D83DDC0CL, 0x00000000D83DDC19L, 0x00000000D83DDC1AL, 0x00000000D83DDC20L, + 0x00000000D83DDC1FL, 0x00000000D83DDC2CL, 0x00000000D83DDC33L, 0x00000000D83DDC0BL, 0x00000000D83DDC04L, 0x00000000D83DDC0FL, 0x00000000D83DDC00L, + 0x00000000D83DDC03L, 0x00000000D83DDC05L, 0x00000000D83DDC07L, 0x00000000D83DDC09L, 0x00000000D83DDC0EL, 0x00000000D83DDC10L, 0x00000000D83DDC13L, + 0x00000000D83DDC15L, 0x00000000D83DDC16L, 0x00000000D83DDC01L, 0x00000000D83DDC02L, 0x00000000D83DDC32L, 0x00000000D83DDC21L, 0x00000000D83DDC0AL, + 0x00000000D83DDC2BL, 0x00000000D83DDC2AL, 0x00000000D83DDC06L, 0x00000000D83DDC08L, 0x00000000D83DDC29L, 0x00000000D83DDC3EL, 0x00000000D83DDC90L, + 0x00000000D83CDF38L, 0x00000000D83CDF37L, 0x00000000D83CDF40L, 0x00000000D83CDF39L, 0x00000000D83CDF3BL, 0x00000000D83CDF3AL, 0x00000000D83CDF41L, + 0x00000000D83CDF43L, 0x00000000D83CDF42L, 0x00000000D83CDF3FL, 0x00000000D83CDF3EL, 0x00000000D83CDF44L, 0x00000000D83CDF35L, 0x00000000D83CDF34L, + 0x00000000D83CDF32L, 0x00000000D83CDF33L, 0x00000000D83CDF30L, 0x00000000D83CDF31L, 0x00000000D83CDF3CL, 0x00000000D83CDF10L, 0x00000000D83CDF1EL, + 0x00000000D83CDF1DL, 0x00000000D83CDF1AL, 0x00000000D83CDF11L, 0x00000000D83CDF12L, 0x00000000D83CDF13L, 0x00000000D83CDF14L, 0x00000000D83CDF15L, + 0x00000000D83CDF16L, 0x00000000D83CDF17L, 0x00000000D83CDF18L, 0x00000000D83CDF1CL, 0x00000000D83CDF1BL, 0x00000000D83CDF19L, 0x00000000D83CDF0DL, + 0x00000000D83CDF0EL, 0x00000000D83CDF0FL, 0x00000000D83CDF0BL, 0x00000000D83CDF0CL, 0x00000000D83CDF20L, 0x0000000000002B50L, 0x0000000000002600L, + 0x00000000000026C5L, 0x0000000000002601L, 0x00000000000026A1L, 0x0000000000002614L, 0x0000000000002744L, 0x00000000000026C4L, 0x00000000D83CDF00L, + 0x00000000D83CDF01L, 0x00000000D83CDF08L, 0x00000000D83CDF0AL}, new long[]//230 - {0x00000000D83CDF8DL, 0x00000000D83DDC9DL, 0x00000000D83CDF8EL, 0x00000000D83CDF92L, 0x00000000D83CDF93L, 0x00000000D83CDF8FL, 0x00000000D83CDF86L, 0x00000000D83CDF87L, - 0x00000000D83CDF90L, 0x00000000D83CDF91L, 0x00000000D83CDF83L, 0x00000000D83DDC7BL, 0x00000000D83CDF85L, 0x00000000D83CDF84L, 0x00000000D83CDF81L, - 0x00000000D83CDF8BL, 0x00000000D83CDF89L, 0x00000000D83CDF8AL, 0x00000000D83CDF88L, 0x00000000D83CDF8CL, 0x00000000D83DDD2EL, 0x00000000D83CDFA5L, - 0x00000000D83DDCF7L, 0x00000000D83DDCF9L, 0x00000000D83DDCFCL, 0x00000000D83DDCBFL, 0x00000000D83DDCC0L, 0x00000000D83DDCBDL, 0x00000000D83DDCBEL, - 0x00000000D83DDCBBL, 0x00000000D83DDCF1L, 0x000000000000260EL, 0x00000000D83DDCDEL, 0x00000000D83DDCDFL, 0x00000000D83DDCE0L, 0x00000000D83DDCE1L, - 0x00000000D83DDCFAL, 0x00000000D83DDCFBL, 0x00000000D83DDD0AL, 0x00000000D83DDD09L, 0x00000000D83DDD08L, 0x00000000D83DDD07L, 0x00000000D83DDD14L, - 0x00000000D83DDD15L, 0x00000000D83DDCE2L, 0x00000000D83DDCE3L, 0x00000000000023F3L, 0x000000000000231BL, 0x00000000000023F0L, 0x000000000000231AL, - 0x00000000D83DDD13L, 0x00000000D83DDD12L, 0x00000000D83DDD0FL, 0x00000000D83DDD10L, 0x00000000D83DDD11L, 0x00000000D83DDD0EL, 0x00000000D83DDCA1L, - 0x00000000D83DDD26L, 0x00000000D83DDD06L, 0x00000000D83DDD05L, 0x00000000D83DDD0CL, 0x00000000D83DDD0BL, 0x00000000D83DDD0DL, 0x00000000D83DDEC1L, 0x00000000D83DDEC0L, - 0x00000000D83DDEBFL, 0x00000000D83DDEBDL, 0x00000000D83DDD27L, 0x00000000D83DDD29L, 0x00000000D83DDD28L, 0x00000000D83DDEAAL, 0x00000000D83DDEACL, - 0x00000000D83DDCA3L, 0x00000000D83DDD2BL, 0x00000000D83DDD2AL, 0x00000000D83DDC8AL, 0x00000000D83DDC89L, 0x00000000D83DDCB0L, 0x00000000D83DDCB4L, - 0x00000000D83DDCB5L, 0x00000000D83DDCB7L, 0x00000000D83DDCB6L, 0x00000000D83DDCB3L, 0x00000000D83DDCB8L, 0x00000000D83DDCF2L, 0x00000000D83DDCE7L, - 0x00000000D83DDCE5L, 0x00000000D83DDCE4L, 0x0000000000002709L, 0x00000000D83DDCE9L, 0x00000000D83DDCE8L, 0x00000000D83DDCEFL, 0x00000000D83DDCEBL, - 0x00000000D83DDCEAL, 0x00000000D83DDCECL, 0x00000000D83DDCEDL, 0x00000000D83DDCEEL, 0x00000000D83DDCE6L, 0x00000000D83DDCDDL, 0x00000000D83DDCC4L, - 0x00000000D83DDCC3L, 0x00000000D83DDCD1L, 0x00000000D83DDCCAL, 0x00000000D83DDCC8L, 0x00000000D83DDCC9L, 0x00000000D83DDCDCL, 0x00000000D83DDCCBL, - 0x00000000D83DDCC5L, 0x00000000D83DDCC6L, 0x00000000D83DDCC7L, 0x00000000D83DDCC1L, 0x00000000D83DDCC2L, 0x0000000000002702L, 0x00000000D83DDCCCL, - 0x00000000D83DDCCEL, 0x0000000000002712L, 0x000000000000270FL, 0x00000000D83DDCCFL, 0x00000000D83DDCD0L, 0x00000000D83DDCD5L, 0x00000000D83DDCD7L, - 0x00000000D83DDCD8L, 0x00000000D83DDCD9L, 0x00000000D83DDCD3L, 0x00000000D83DDCD4L, 0x00000000D83DDCD2L, 0x00000000D83DDCDAL, 0x00000000D83DDCD6L, - 0x00000000D83DDD16L, 0x00000000D83DDCDBL, 0x00000000D83DDD2CL, 0x00000000D83DDD2DL, 0x00000000D83DDCF0L, 0x00000000D83CDFA8L, 0x00000000D83CDFACL, - 0x00000000D83CDFA4L, 0x00000000D83CDFA7L, 0x00000000D83CDFBCL, 0x00000000D83CDFB5L, 0x00000000D83CDFB6L, 0x00000000D83CDFB9L, 0x00000000D83CDFBBL, - 0x00000000D83CDFBAL, 0x00000000D83CDFB7L, 0x00000000D83CDFB8L, 0x00000000D83DDC7EL, 0x00000000D83CDFAEL, 0x00000000D83CDCCFL, 0x00000000D83CDFB4L, - 0x00000000D83CDC04L, 0x00000000D83CDFB2L, 0x00000000D83CDFAFL, 0x00000000D83CDFC8L, 0x00000000D83CDFC0L, 0x00000000000026BDL, 0x00000000000026BEL, - 0x00000000D83CDFBEL, 0x00000000D83CDFB1L, 0x00000000D83CDFC9L, 0x00000000D83CDFB3L, 0x00000000000026F3L, 0x00000000D83DDEB5L, 0x00000000D83DDEB4L, - 0x00000000D83CDFC1L, 0x00000000D83CDFC7L, 0x00000000D83CDFC6L, 0x00000000D83CDFBFL, 0x00000000D83CDFC2L, 0x00000000D83CDFCAL, 0x00000000D83CDFC4L, - 0x00000000D83CDFA3L, 0x0000000000002615L, 0x00000000D83CDF75L, 0x00000000D83CDF76L, 0x00000000D83CDF7CL, 0x00000000D83CDF7AL, 0x00000000D83CDF7BL, - 0x00000000D83CDF78L, 0x00000000D83CDF79L, 0x00000000D83CDF77L, 0x00000000D83CDF74L, 0x00000000D83CDF55L, 0x00000000D83CDF54L, 0x00000000D83CDF5FL, - 0x00000000D83CDF57L, 0x00000000D83CDF56L, 0x00000000D83CDF5DL, 0x00000000D83CDF5BL, 0x00000000D83CDF64L, 0x00000000D83CDF71L, 0x00000000D83CDF63L, - 0x00000000D83CDF65L, 0x00000000D83CDF59L, 0x00000000D83CDF58L, 0x00000000D83CDF5AL, 0x00000000D83CDF5CL, 0x00000000D83CDF72L, 0x00000000D83CDF62L, - 0x00000000D83CDF61L, 0x00000000D83CDF73L, 0x00000000D83CDF5EL, 0x00000000D83CDF69L, 0x00000000D83CDF6EL, 0x00000000D83CDF66L, 0x00000000D83CDF68L, - 0x00000000D83CDF67L, 0x00000000D83CDF82L, 0x00000000D83CDF70L, 0x00000000D83CDF6AL, 0x00000000D83CDF6BL, 0x00000000D83CDF6CL, 0x00000000D83CDF6DL, - 0x00000000D83CDF6FL, 0x00000000D83CDF4EL, 0x00000000D83CDF4FL, 0x00000000D83CDF4AL, 0x00000000D83CDF4BL, 0x00000000D83CDF52L, 0x00000000D83CDF47L, - 0x00000000D83CDF49L, 0x00000000D83CDF53L, 0x00000000D83CDF51L, 0x00000000D83CDF48L, 0x00000000D83CDF4CL, 0x00000000D83CDF50L, 0x00000000D83CDF4DL, - 0x00000000D83CDF60L, 0x00000000D83CDF46L, 0x00000000D83CDF45L, 0x00000000D83CDF3DL}, + { + 0x00000000D83CDF8DL, 0x00000000D83DDC9DL, 0x00000000D83CDF8EL, 0x00000000D83CDF92L, 0x00000000D83CDF93L, 0x00000000D83CDF8FL, 0x00000000D83CDF86L, 0x00000000D83CDF87L, + 0x00000000D83CDF90L, 0x00000000D83CDF91L, 0x00000000D83CDF83L, 0x00000000D83DDC7BL, 0x00000000D83CDF85L, 0x00000000D83CDF84L, 0x00000000D83CDF81L, + 0x00000000D83CDF8BL, 0x00000000D83CDF89L, 0x00000000D83CDF8AL, 0x00000000D83CDF88L, 0x00000000D83CDF8CL, 0x00000000D83DDD2EL, 0x00000000D83CDFA5L, + 0x00000000D83DDCF7L, 0x00000000D83DDCF9L, 0x00000000D83DDCFCL, 0x00000000D83DDCBFL, 0x00000000D83DDCC0L, 0x00000000D83DDCBDL, 0x00000000D83DDCBEL, + 0x00000000D83DDCBBL, 0x00000000D83DDCF1L, 0x000000000000260EL, 0x00000000D83DDCDEL, 0x00000000D83DDCDFL, 0x00000000D83DDCE0L, 0x00000000D83DDCE1L, + 0x00000000D83DDCFAL, 0x00000000D83DDCFBL, 0x00000000D83DDD0AL, 0x00000000D83DDD09L, 0x00000000D83DDD08L, 0x00000000D83DDD07L, 0x00000000D83DDD14L, + 0x00000000D83DDD15L, 0x00000000D83DDCE2L, 0x00000000D83DDCE3L, 0x00000000000023F3L, 0x000000000000231BL, 0x00000000000023F0L, 0x000000000000231AL, + 0x00000000D83DDD13L, 0x00000000D83DDD12L, 0x00000000D83DDD0FL, 0x00000000D83DDD10L, 0x00000000D83DDD11L, 0x00000000D83DDD0EL, 0x00000000D83DDCA1L, + 0x00000000D83DDD26L, 0x00000000D83DDD06L, 0x00000000D83DDD05L, 0x00000000D83DDD0CL, 0x00000000D83DDD0BL, 0x00000000D83DDD0DL, 0x00000000D83DDEC1L, 0x00000000D83DDEC0L, + 0x00000000D83DDEBFL, 0x00000000D83DDEBDL, 0x00000000D83DDD27L, 0x00000000D83DDD29L, 0x00000000D83DDD28L, 0x00000000D83DDEAAL, 0x00000000D83DDEACL, + 0x00000000D83DDCA3L, 0x00000000D83DDD2BL, 0x00000000D83DDD2AL, 0x00000000D83DDC8AL, 0x00000000D83DDC89L, 0x00000000D83DDCB0L, 0x00000000D83DDCB4L, + 0x00000000D83DDCB5L, 0x00000000D83DDCB7L, 0x00000000D83DDCB6L, 0x00000000D83DDCB3L, 0x00000000D83DDCB8L, 0x00000000D83DDCF2L, 0x00000000D83DDCE7L, + 0x00000000D83DDCE5L, 0x00000000D83DDCE4L, 0x0000000000002709L, 0x00000000D83DDCE9L, 0x00000000D83DDCE8L, 0x00000000D83DDCEFL, 0x00000000D83DDCEBL, + 0x00000000D83DDCEAL, 0x00000000D83DDCECL, 0x00000000D83DDCEDL, 0x00000000D83DDCEEL, 0x00000000D83DDCE6L, 0x00000000D83DDCDDL, 0x00000000D83DDCC4L, + 0x00000000D83DDCC3L, 0x00000000D83DDCD1L, 0x00000000D83DDCCAL, 0x00000000D83DDCC8L, 0x00000000D83DDCC9L, 0x00000000D83DDCDCL, 0x00000000D83DDCCBL, + 0x00000000D83DDCC5L, 0x00000000D83DDCC6L, 0x00000000D83DDCC7L, 0x00000000D83DDCC1L, 0x00000000D83DDCC2L, 0x0000000000002702L, 0x00000000D83DDCCCL, + 0x00000000D83DDCCEL, 0x0000000000002712L, 0x000000000000270FL, 0x00000000D83DDCCFL, 0x00000000D83DDCD0L, 0x00000000D83DDCD5L, 0x00000000D83DDCD7L, + 0x00000000D83DDCD8L, 0x00000000D83DDCD9L, 0x00000000D83DDCD3L, 0x00000000D83DDCD4L, 0x00000000D83DDCD2L, 0x00000000D83DDCDAL, 0x00000000D83DDCD6L, + 0x00000000D83DDD16L, 0x00000000D83DDCDBL, 0x00000000D83DDD2CL, 0x00000000D83DDD2DL, 0x00000000D83DDCF0L, 0x00000000D83CDFA8L, 0x00000000D83CDFACL, + 0x00000000D83CDFA4L, 0x00000000D83CDFA7L, 0x00000000D83CDFBCL, 0x00000000D83CDFB5L, 0x00000000D83CDFB6L, 0x00000000D83CDFB9L, 0x00000000D83CDFBBL, + 0x00000000D83CDFBAL, 0x00000000D83CDFB7L, 0x00000000D83CDFB8L, 0x00000000D83DDC7EL, 0x00000000D83CDFAEL, 0x00000000D83CDCCFL, 0x00000000D83CDFB4L, + 0x00000000D83CDC04L, 0x00000000D83CDFB2L, 0x00000000D83CDFAFL, 0x00000000D83CDFC8L, 0x00000000D83CDFC0L, 0x00000000000026BDL, 0x00000000000026BEL, + 0x00000000D83CDFBEL, 0x00000000D83CDFB1L, 0x00000000D83CDFC9L, 0x00000000D83CDFB3L, 0x00000000000026F3L, 0x00000000D83DDEB5L, 0x00000000D83DDEB4L, + 0x00000000D83CDFC1L, 0x00000000D83CDFC7L, 0x00000000D83CDFC6L, 0x00000000D83CDFBFL, 0x00000000D83CDFC2L, 0x00000000D83CDFCAL, 0x00000000D83CDFC4L, + 0x00000000D83CDFA3L, 0x0000000000002615L, 0x00000000D83CDF75L, 0x00000000D83CDF76L, 0x00000000D83CDF7CL, 0x00000000D83CDF7AL, 0x00000000D83CDF7BL, + 0x00000000D83CDF78L, 0x00000000D83CDF79L, 0x00000000D83CDF77L, 0x00000000D83CDF74L, 0x00000000D83CDF55L, 0x00000000D83CDF54L, 0x00000000D83CDF5FL, + 0x00000000D83CDF57L, 0x00000000D83CDF56L, 0x00000000D83CDF5DL, 0x00000000D83CDF5BL, 0x00000000D83CDF64L, 0x00000000D83CDF71L, 0x00000000D83CDF63L, + 0x00000000D83CDF65L, 0x00000000D83CDF59L, 0x00000000D83CDF58L, 0x00000000D83CDF5AL, 0x00000000D83CDF5CL, 0x00000000D83CDF72L, 0x00000000D83CDF62L, + 0x00000000D83CDF61L, 0x00000000D83CDF73L, 0x00000000D83CDF5EL, 0x00000000D83CDF69L, 0x00000000D83CDF6EL, 0x00000000D83CDF66L, 0x00000000D83CDF68L, + 0x00000000D83CDF67L, 0x00000000D83CDF82L, 0x00000000D83CDF70L, 0x00000000D83CDF6AL, 0x00000000D83CDF6BL, 0x00000000D83CDF6CL, 0x00000000D83CDF6DL, + 0x00000000D83CDF6FL, 0x00000000D83CDF4EL, 0x00000000D83CDF4FL, 0x00000000D83CDF4AL, 0x00000000D83CDF4BL, 0x00000000D83CDF52L, 0x00000000D83CDF47L, + 0x00000000D83CDF49L, 0x00000000D83CDF53L, 0x00000000D83CDF51L, 0x00000000D83CDF48L, 0x00000000D83CDF4CL, 0x00000000D83CDF50L, 0x00000000D83CDF4DL, + 0x00000000D83CDF60L, 0x00000000D83CDF46L, 0x00000000D83CDF45L, 0x00000000D83CDF3DL}, new long[]//101 - {0x00000000D83CDFE0L, 0x00000000D83CDFE1L, 0x00000000D83CDFEBL, 0x00000000D83CDFE2L, 0x00000000D83CDFE3L, 0x00000000D83CDFE5L, 0x00000000D83CDFE6L, 0x00000000D83CDFEAL, - 0x00000000D83CDFE9L, 0x00000000D83CDFE8L, 0x00000000D83DDC92L, 0x00000000000026EAL, 0x00000000D83CDFECL, 0x00000000D83CDFE4L, 0x00000000D83CDF07L, - 0x00000000D83CDF06L, 0x00000000D83CDFEFL, 0x00000000D83CDFF0L, 0x00000000000026FAL, 0x00000000D83CDFEDL, 0x00000000D83DDDFCL, 0x00000000D83DDDFEL, - 0x00000000D83DDDFBL, 0x00000000D83CDF04L, 0x00000000D83CDF05L, 0x00000000D83CDF03L, 0x00000000D83DDDFDL, 0x00000000D83CDF09L, 0x00000000D83CDFA0L, - 0x00000000D83CDFA1L, 0x00000000000026F2L, 0x00000000D83CDFA2L, 0x00000000D83DDEA2L, 0x00000000000026F5L, 0x00000000D83DDEA4L, 0x00000000D83DDEA3L, - 0x0000000000002693L, 0x00000000D83DDE80L, 0x0000000000002708L, 0x00000000D83DDCBAL, 0x00000000D83DDE81L, 0x00000000D83DDE82L, 0x00000000D83DDE8AL, - 0x00000000D83DDE89L, 0x00000000D83DDE9EL, 0x00000000D83DDE86L, 0x00000000D83DDE84L, 0x00000000D83DDE85L, 0x00000000D83DDE88L, 0x00000000D83DDE87L, - 0x00000000D83DDE9DL, 0x00000000D83DDE8BL, 0x00000000D83DDE83L, 0x00000000D83DDE8EL, 0x00000000D83DDE8CL, 0x00000000D83DDE8DL, 0x00000000D83DDE99L, - 0x00000000D83DDE98L, 0x00000000D83DDE97L, 0x00000000D83DDE95L, 0x00000000D83DDE96L, 0x00000000D83DDE9BL, 0x00000000D83DDE9AL, 0x00000000D83DDEA8L, - 0x00000000D83DDE93L, 0x00000000D83DDE94L, 0x00000000D83DDE92L, 0x00000000D83DDE91L, 0x00000000D83DDE90L, 0x00000000D83DDEB2L, 0x00000000D83DDEA1L, - 0x00000000D83DDE9FL, 0x00000000D83DDEA0L, 0x00000000D83DDE9CL, 0x00000000D83DDC88L, 0x00000000D83DDE8FL, 0x00000000D83CDFABL, 0x00000000D83DDEA6L, - 0x00000000D83DDEA5L, 0x00000000000026A0L, 0x00000000D83DDEA7L, 0x00000000D83DDD30L, 0x00000000000026FDL, 0x00000000D83CDFEEL, 0x00000000D83CDFB0L, - 0x0000000000002668L, 0x00000000D83DDDFFL, 0x00000000D83CDFAAL, 0x00000000D83CDFADL, 0x00000000D83DDCCDL, 0x00000000D83DDEA9L, 0xD83CDDEFD83CDDF5L, - 0xD83CDDF0D83CDDF7L, 0xD83CDDE9D83CDDEAL, 0xD83CDDE8D83CDDF3L, 0xD83CDDFAD83CDDF8L, 0xD83CDDEBD83CDDF7L, 0xD83CDDEAD83CDDF8L, 0xD83CDDEED83CDDF9L, - 0xD83CDDF7D83CDDFAL, 0xD83CDDECD83CDDE7L}, + { + 0x00000000D83CDFE0L, 0x00000000D83CDFE1L, 0x00000000D83CDFEBL, 0x00000000D83CDFE2L, 0x00000000D83CDFE3L, 0x00000000D83CDFE5L, 0x00000000D83CDFE6L, 0x00000000D83CDFEAL, + 0x00000000D83CDFE9L, 0x00000000D83CDFE8L, 0x00000000D83DDC92L, 0x00000000000026EAL, 0x00000000D83CDFECL, 0x00000000D83CDFE4L, 0x00000000D83CDF07L, + 0x00000000D83CDF06L, 0x00000000D83CDFEFL, 0x00000000D83CDFF0L, 0x00000000000026FAL, 0x00000000D83CDFEDL, 0x00000000D83DDDFCL, 0x00000000D83DDDFEL, + 0x00000000D83DDDFBL, 0x00000000D83CDF04L, 0x00000000D83CDF05L, 0x00000000D83CDF03L, 0x00000000D83DDDFDL, 0x00000000D83CDF09L, 0x00000000D83CDFA0L, + 0x00000000D83CDFA1L, 0x00000000000026F2L, 0x00000000D83CDFA2L, 0x00000000D83DDEA2L, 0x00000000000026F5L, 0x00000000D83DDEA4L, 0x00000000D83DDEA3L, + 0x0000000000002693L, 0x00000000D83DDE80L, 0x0000000000002708L, 0x00000000D83DDCBAL, 0x00000000D83DDE81L, 0x00000000D83DDE82L, 0x00000000D83DDE8AL, + 0x00000000D83DDE89L, 0x00000000D83DDE9EL, 0x00000000D83DDE86L, 0x00000000D83DDE84L, 0x00000000D83DDE85L, 0x00000000D83DDE88L, 0x00000000D83DDE87L, + 0x00000000D83DDE9DL, 0x00000000D83DDE8BL, 0x00000000D83DDE83L, 0x00000000D83DDE8EL, 0x00000000D83DDE8CL, 0x00000000D83DDE8DL, 0x00000000D83DDE99L, + 0x00000000D83DDE98L, 0x00000000D83DDE97L, 0x00000000D83DDE95L, 0x00000000D83DDE96L, 0x00000000D83DDE9BL, 0x00000000D83DDE9AL, 0x00000000D83DDEA8L, + 0x00000000D83DDE93L, 0x00000000D83DDE94L, 0x00000000D83DDE92L, 0x00000000D83DDE91L, 0x00000000D83DDE90L, 0x00000000D83DDEB2L, 0x00000000D83DDEA1L, + 0x00000000D83DDE9FL, 0x00000000D83DDEA0L, 0x00000000D83DDE9CL, 0x00000000D83DDC88L, 0x00000000D83DDE8FL, 0x00000000D83CDFABL, 0x00000000D83DDEA6L, + 0x00000000D83DDEA5L, 0x00000000000026A0L, 0x00000000D83DDEA7L, 0x00000000D83DDD30L, 0x00000000000026FDL, 0x00000000D83CDFEEL, 0x00000000D83CDFB0L, + 0x0000000000002668L, 0x00000000D83DDDFFL, 0x00000000D83CDFAAL, 0x00000000D83CDFADL, 0x00000000D83DDCCDL, 0x00000000D83DDEA9L, 0xD83CDDEFD83CDDF5L, + 0xD83CDDF0D83CDDF7L, 0xD83CDDE9D83CDDEAL, 0xD83CDDE8D83CDDF3L, 0xD83CDDFAD83CDDF8L, 0xD83CDDEBD83CDDF7L, 0xD83CDDEAD83CDDF8L, 0xD83CDDEED83CDDF9L, + 0xD83CDDF7D83CDDFAL, 0xD83CDDECD83CDDE7L}, new long[]//209 - {0x00000000003120E3L, 0x00000000003220E3L, 0x00000000003320E3L, 0x00000000003420E3L, 0x00000000003520E3L, 0x00000000003620E3L, 0x00000000003720E3L, - 0x00000000003820E3L, 0x00000000003920E3L, 0x00000000003020E3L, 0x00000000D83DDD1FL, 0x00000000D83DDD22L, 0x00000000002320E3L, 0x00000000D83DDD23L, - 0x0000000000002B06L, 0x0000000000002B07L, 0x0000000000002B05L, 0x00000000000027A1L, 0x00000000D83DDD20L, 0x00000000D83DDD21L, 0x00000000D83DDD24L, - 0x0000000000002197L, 0x0000000000002196L, 0x0000000000002198L, 0x0000000000002199L, 0x0000000000002194L, 0x0000000000002195L, 0x00000000D83DDD04L, - 0x00000000000025C0L, 0x00000000000025B6L, 0x00000000D83DDD3CL, 0x00000000D83DDD3DL, 0x00000000000021A9L, 0x00000000000021AAL, 0x0000000000002139L, - 0x00000000000023EAL, 0x00000000000023E9L, 0x00000000000023EBL, 0x00000000000023ECL, 0x0000000000002935L, 0x0000000000002934L, 0x00000000D83CDD97L, - 0x00000000D83DDD00L, 0x00000000D83DDD01L, 0x00000000D83DDD02L, 0x00000000D83CDD95L, 0x00000000D83CDD99L, 0x00000000D83CDD92L, 0x00000000D83CDD93L, - 0x00000000D83CDD96L, 0x00000000D83DDCF6L, 0x00000000D83CDFA6L, 0x00000000D83CDE01L, 0x00000000D83CDE2FL, 0x00000000D83CDE33L, 0x00000000D83CDE35L, - 0x00000000D83CDE32L, 0x00000000D83CDE34L, 0x00000000D83CDE50L, 0x00000000D83CDE39L, 0x00000000D83CDE3AL, 0x00000000D83CDE36L, 0x00000000D83CDE1AL, - 0x00000000D83DDEBBL, 0x00000000D83DDEB9L, 0x00000000D83DDEBAL, 0x00000000D83DDEBCL, 0x00000000D83DDEBEL, 0x00000000D83DDEB0L, 0x00000000D83DDEAEL, - 0x00000000D83CDD7FL, 0x000000000000267FL, 0x00000000D83DDEADL, 0x00000000D83CDE37L, 0x00000000D83CDE38L, 0x00000000D83CDE02L, 0x00000000000024C2L, - 0x00000000D83DDEC2L, 0x00000000D83DDEC4L, 0x00000000D83DDEC5L, 0x00000000D83DDEC3L, 0x00000000D83CDE51L, 0x0000000000003299L, 0x0000000000003297L, - 0x00000000D83CDD91L, 0x00000000D83CDD98L, 0x00000000D83CDD94L, 0x00000000D83DDEABL, - 0x00000000D83DDD1EL, 0x00000000D83DDCF5L, 0x00000000D83DDEAFL, 0x00000000D83DDEB1L, 0x00000000D83DDEB3L, 0x00000000D83DDEB7L, 0x00000000D83DDEB8L, - 0x00000000000026D4L, 0x0000000000002733L, 0x0000000000002747L, 0x000000000000274EL, 0x0000000000002705L, 0x0000000000002734L, 0x00000000D83DDC9FL, - 0x00000000D83CDD9AL, 0x00000000D83DDCF3L, 0x00000000D83DDCF4L, 0x00000000D83CDD70L, 0x00000000D83CDD71L, 0x00000000D83CDD8EL, 0x00000000D83CDD7EL, - 0x00000000D83DDCA0L, 0x00000000000027BFL, 0x000000000000267BL, 0x0000000000002648L, 0x0000000000002649L, 0x000000000000264AL, 0x000000000000264BL, - 0x000000000000264CL, 0x000000000000264DL, 0x000000000000264EL, 0x000000000000264FL, 0x0000000000002650L, 0x0000000000002651L, 0x0000000000002652L, - 0x0000000000002653L, 0x00000000000026CEL, 0x00000000D83DDD2FL, 0x00000000D83CDFE7L, 0x00000000D83DDCB9L, 0x00000000D83DDCB2L, 0x00000000D83DDCB1L, - 0x00000000000000A9L, 0x00000000000000AEL, 0x0000000000002122L, 0x000000000000303DL, 0x0000000000003030L, 0x00000000D83DDD1DL, 0x00000000D83DDD1AL, - 0x00000000D83DDD19L, 0x00000000D83DDD1BL, 0x00000000D83DDD1CL, 0x000000000000274CL, 0x0000000000002B55L, 0x0000000000002757L, 0x000000000000203CL, - 0x0000000000002049L, 0x0000000000002753L, - 0x0000000000002755L, 0x0000000000002754L, 0x00000000D83DDD03L, 0x00000000D83DDD5BL, 0x00000000D83DDD67L, 0x00000000D83DDD50L, 0x00000000D83DDD5CL, - 0x00000000D83DDD51L, 0x00000000D83DDD5DL, 0x00000000D83DDD52L, 0x00000000D83DDD5EL, 0x00000000D83DDD53L, 0x00000000D83DDD5FL, 0x00000000D83DDD54L, - 0x00000000D83DDD60L, 0x00000000D83DDD55L, 0x00000000D83DDD56L, 0x00000000D83DDD57L, 0x00000000D83DDD58L, 0x00000000D83DDD59L, 0x00000000D83DDD5AL, - 0x00000000D83DDD61L, 0x00000000D83DDD62L, 0x00000000D83DDD63L, 0x00000000D83DDD64L, 0x00000000D83DDD65L, 0x00000000D83DDD66L, 0x0000000000002716L, - 0x0000000000002795L, 0x0000000000002796L, 0x0000000000002797L, 0x0000000000002660L, 0x0000000000002665L, 0x0000000000002663L, 0x0000000000002666L, - 0x00000000D83DDCAEL, 0x00000000D83DDCAFL, 0x0000000000002714L, 0x0000000000002611L, 0x00000000D83DDD18L, 0x00000000D83DDD17L, 0x00000000000027B0L, - 0x00000000D83DDD31L, 0x00000000D83DDD32L, 0x00000000D83DDD33L, 0x00000000000025FCL, 0x00000000000025FBL, 0x00000000000025FEL, 0x00000000000025FDL, - 0x00000000000025AAL, 0x00000000000025ABL, 0x00000000D83DDD3AL, 0x0000000000002B1CL, 0x0000000000002B1BL, 0x00000000000026ABL, 0x00000000000026AAL, - 0x00000000D83DDD34L, 0x00000000D83DDD35L, 0x00000000D83DDD3BL, 0x00000000D83DDD36L, 0x00000000D83DDD37L, 0x00000000D83DDD38L, 0x00000000D83DDD39L}}; - - static { + { + 0x00000000003120E3L, 0x00000000003220E3L, 0x00000000003320E3L, 0x00000000003420E3L, 0x00000000003520E3L, 0x00000000003620E3L, 0x00000000003720E3L, + 0x00000000003820E3L, 0x00000000003920E3L, 0x00000000003020E3L, 0x00000000D83DDD1FL, 0x00000000D83DDD22L, 0x00000000002320E3L, 0x00000000D83DDD23L, + 0x0000000000002B06L, 0x0000000000002B07L, 0x0000000000002B05L, 0x00000000000027A1L, 0x00000000D83DDD20L, 0x00000000D83DDD21L, 0x00000000D83DDD24L, + 0x0000000000002197L, 0x0000000000002196L, 0x0000000000002198L, 0x0000000000002199L, 0x0000000000002194L, 0x0000000000002195L, 0x00000000D83DDD04L, + 0x00000000000025C0L, 0x00000000000025B6L, 0x00000000D83DDD3CL, 0x00000000D83DDD3DL, 0x00000000000021A9L, 0x00000000000021AAL, 0x0000000000002139L, + 0x00000000000023EAL, 0x00000000000023E9L, 0x00000000000023EBL, 0x00000000000023ECL, 0x0000000000002935L, 0x0000000000002934L, 0x00000000D83CDD97L, + 0x00000000D83DDD00L, 0x00000000D83DDD01L, 0x00000000D83DDD02L, 0x00000000D83CDD95L, 0x00000000D83CDD99L, 0x00000000D83CDD92L, 0x00000000D83CDD93L, + 0x00000000D83CDD96L, 0x00000000D83DDCF6L, 0x00000000D83CDFA6L, 0x00000000D83CDE01L, 0x00000000D83CDE2FL, 0x00000000D83CDE33L, 0x00000000D83CDE35L, + 0x00000000D83CDE32L, 0x00000000D83CDE34L, 0x00000000D83CDE50L, 0x00000000D83CDE39L, 0x00000000D83CDE3AL, 0x00000000D83CDE36L, 0x00000000D83CDE1AL, + 0x00000000D83DDEBBL, 0x00000000D83DDEB9L, 0x00000000D83DDEBAL, 0x00000000D83DDEBCL, 0x00000000D83DDEBEL, 0x00000000D83DDEB0L, 0x00000000D83DDEAEL, + 0x00000000D83CDD7FL, 0x000000000000267FL, 0x00000000D83DDEADL, 0x00000000D83CDE37L, 0x00000000D83CDE38L, 0x00000000D83CDE02L, 0x00000000000024C2L, + 0x00000000D83DDEC2L, 0x00000000D83DDEC4L, 0x00000000D83DDEC5L, 0x00000000D83DDEC3L, 0x00000000D83CDE51L, 0x0000000000003299L, 0x0000000000003297L, + 0x00000000D83CDD91L, 0x00000000D83CDD98L, 0x00000000D83CDD94L, 0x00000000D83DDEABL, + 0x00000000D83DDD1EL, 0x00000000D83DDCF5L, 0x00000000D83DDEAFL, 0x00000000D83DDEB1L, 0x00000000D83DDEB3L, 0x00000000D83DDEB7L, 0x00000000D83DDEB8L, + 0x00000000000026D4L, 0x0000000000002733L, 0x0000000000002747L, 0x000000000000274EL, 0x0000000000002705L, 0x0000000000002734L, 0x00000000D83DDC9FL, + 0x00000000D83CDD9AL, 0x00000000D83DDCF3L, 0x00000000D83DDCF4L, 0x00000000D83CDD70L, 0x00000000D83CDD71L, 0x00000000D83CDD8EL, 0x00000000D83CDD7EL, + 0x00000000D83DDCA0L, 0x00000000000027BFL, 0x000000000000267BL, 0x0000000000002648L, 0x0000000000002649L, 0x000000000000264AL, 0x000000000000264BL, + 0x000000000000264CL, 0x000000000000264DL, 0x000000000000264EL, 0x000000000000264FL, 0x0000000000002650L, 0x0000000000002651L, 0x0000000000002652L, + 0x0000000000002653L, 0x00000000000026CEL, 0x00000000D83DDD2FL, 0x00000000D83CDFE7L, 0x00000000D83DDCB9L, 0x00000000D83DDCB2L, 0x00000000D83DDCB1L, + 0x00000000000000A9L, 0x00000000000000AEL, 0x0000000000002122L, 0x000000000000303DL, 0x0000000000003030L, 0x00000000D83DDD1DL, 0x00000000D83DDD1AL, + 0x00000000D83DDD19L, 0x00000000D83DDD1BL, 0x00000000D83DDD1CL, 0x000000000000274CL, 0x0000000000002B55L, 0x0000000000002757L, 0x000000000000203CL, + 0x0000000000002049L, 0x0000000000002753L, + 0x0000000000002755L, 0x0000000000002754L, 0x00000000D83DDD03L, 0x00000000D83DDD5BL, 0x00000000D83DDD67L, 0x00000000D83DDD50L, 0x00000000D83DDD5CL, + 0x00000000D83DDD51L, 0x00000000D83DDD5DL, 0x00000000D83DDD52L, 0x00000000D83DDD5EL, 0x00000000D83DDD53L, 0x00000000D83DDD5FL, 0x00000000D83DDD54L, + 0x00000000D83DDD60L, 0x00000000D83DDD55L, 0x00000000D83DDD56L, 0x00000000D83DDD57L, 0x00000000D83DDD58L, 0x00000000D83DDD59L, 0x00000000D83DDD5AL, + 0x00000000D83DDD61L, 0x00000000D83DDD62L, 0x00000000D83DDD63L, 0x00000000D83DDD64L, 0x00000000D83DDD65L, 0x00000000D83DDD66L, 0x0000000000002716L, + 0x0000000000002795L, 0x0000000000002796L, 0x0000000000002797L, 0x0000000000002660L, 0x0000000000002665L, 0x0000000000002663L, 0x0000000000002666L, + 0x00000000D83DDCAEL, 0x00000000D83DDCAFL, 0x0000000000002714L, 0x0000000000002611L, 0x00000000D83DDD18L, 0x00000000D83DDD17L, 0x00000000000027B0L, + 0x00000000D83DDD31L, 0x00000000D83DDD32L, 0x00000000D83DDD33L, 0x00000000000025FCL, 0x00000000000025FBL, 0x00000000000025FEL, 0x00000000000025FDL, + 0x00000000000025AAL, 0x00000000000025ABL, 0x00000000D83DDD3AL, 0x0000000000002B1CL, 0x0000000000002B1BL, 0x00000000000026ABL, 0x00000000000026AAL, + 0x00000000D83DDD34L, 0x00000000D83DDD35L, 0x00000000D83DDD3BL, 0x00000000D83DDD36L, 0x00000000D83DDD37L, 0x00000000D83DDD38L, 0x00000000D83DDD39L}}; + + static { int emojiFullSize; if (AndroidUtilities.density <= 1.0f) { emojiFullSize = 32; @@ -203,25 +208,25 @@ public class Emoji { } else { emojiFullSize = 96; } - drawImgSize = AndroidUtilities.dp(20); + drawImgSize = AndroidUtilities.dp(20); if (AndroidUtilities.isTablet()) { bigImgSize = AndroidUtilities.dp(40); } else { bigImgSize = AndroidUtilities.dp(32); } - for (int j = 1; j < data.length; j++) { - for (int i = 0; i < data[j].length; i++) { + for (int j = 1; j < data.length; j++) { + for (int i = 0; i < data[j].length; i++) { Rect rect = new Rect((i % cols[j - 1]) * emojiFullSize, (i / cols[j - 1]) * emojiFullSize, (i % cols[j - 1] + 1) * emojiFullSize, (i / cols[j - 1] + 1) * emojiFullSize); - rects.put(data[j][i], new DrawableInfo(rect, (byte)(j - 1))); - } - } - placeholderPaint = new Paint(); - placeholderPaint.setColor(0x00000000); - } + rects.put(data[j][i], new DrawableInfo(rect, (byte) (j - 1))); + } + } + placeholderPaint = new Paint(); + placeholderPaint.setColor(0x00000000); + } - private static void loadEmoji(final int page) { - try { + private static void loadEmoji(final int page) { + try { float scale; int imageResize = 1; if (AndroidUtilities.density <= 1.0f) { @@ -290,64 +295,64 @@ public class Emoji { NotificationCenter.getInstance().postNotificationName(NotificationCenter.emojiDidLoaded); } }); - } catch(Throwable x) { + } catch (Throwable x) { FileLog.e("tmessages", "Error loading emoji", x); } - } - - private static void loadEmojiAsync(final int page) { - if (loadingEmoji[page]) { + } + + private static void loadEmojiAsync(final int page) { + if (loadingEmoji[page]) { return; } loadingEmoji[page] = true; - new Thread(new Runnable() { + new Thread(new Runnable() { public void run() { loadEmoji(page); loadingEmoji[page] = false; } }).start(); - } - - public static void invalidateAll(View view) { - if (view instanceof ViewGroup) { - ViewGroup g = (ViewGroup)view; - for (int i = 0; i < g.getChildCount(); i++) { - invalidateAll(g.getChildAt(i)); - } - } else if (view instanceof TextView) { - view.invalidate(); - } - } - - public static EmojiDrawable getEmojiDrawable(long code) { - DrawableInfo info = rects.get(code); - if (info == null) { + } + + public static void invalidateAll(View view) { + if (view instanceof ViewGroup) { + ViewGroup g = (ViewGroup) view; + for (int i = 0; i < g.getChildCount(); i++) { + invalidateAll(g.getChildAt(i)); + } + } else if (view instanceof TextView) { + view.invalidate(); + } + } + + public static EmojiDrawable getEmojiDrawable(long code) { + DrawableInfo info = rects.get(code); + if (info == null) { FileLog.e("tmessages", "No emoji drawable for code " + String.format("%016X", code)); - return null; - } - EmojiDrawable ed = new EmojiDrawable(info); - ed.setBounds(0, 0, drawImgSize, drawImgSize); - return ed; - } - - public static Drawable getEmojiBigDrawable(long code) { - EmojiDrawable ed = getEmojiDrawable(code); - if (ed == null) { return null; } - ed.setBounds(0, 0, bigImgSize, bigImgSize); - ed.fullSize = true; - return ed; - } - - public static class EmojiDrawable extends Drawable { + EmojiDrawable ed = new EmojiDrawable(info); + ed.setBounds(0, 0, drawImgSize, drawImgSize); + return ed; + } + + public static Drawable getEmojiBigDrawable(long code) { + EmojiDrawable ed = getEmojiDrawable(code); + if (ed == null) { + return null; + } + ed.setBounds(0, 0, bigImgSize, bigImgSize); + ed.fullSize = true; + return ed; + } + + public static class EmojiDrawable extends Drawable { private DrawableInfo info; - private boolean fullSize = false; - private static Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); - - public EmojiDrawable(DrawableInfo i) { - info = i; - } + private boolean fullSize = false; + private static Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); + + public EmojiDrawable(DrawableInfo i) { + info = i; + } public DrawableInfo getDrawableInfo() { return info; @@ -364,12 +369,12 @@ public class Emoji { } @Override - public void draw(Canvas canvas) { - if (emojiBmp[info.page] == null) { + public void draw(Canvas canvas) { + if (emojiBmp[info.page] == null) { loadEmojiAsync(info.page); - canvas.drawRect(getBounds(), placeholderPaint); - return; - } + canvas.drawRect(getBounds(), placeholderPaint); + return; + } Rect b; if (fullSize) { b = getDrawRect(); @@ -380,33 +385,33 @@ public class Emoji { if (!canvas.quickReject(b.left, b.top, b.right, b.bottom, Canvas.EdgeType.AA)) { canvas.drawBitmap(emojiBmp[info.page], info.rect, b, paint); } - } + } - @Override - public int getOpacity() { - return 0; - } + @Override + public int getOpacity() { + return 0; + } - @Override - public void setAlpha(int alpha) { + @Override + public void setAlpha(int alpha) { } - @Override - public void setColorFilter(ColorFilter cf) { + @Override + public void setColorFilter(ColorFilter cf) { } - } - - private static class DrawableInfo { + } + + private static class DrawableInfo { public Rect rect; public byte page; - public DrawableInfo(Rect r, byte p) { - rect = r; + public DrawableInfo(Rect r, byte p) { + rect = r; page = p; - } - } + } + } private static boolean inArray(char c, char[] a) { for (char cc : a) { @@ -425,18 +430,22 @@ public class Emoji { return value == 0xd83cdffb || value == 0xd83cdffc || value == 0xd83cdffd || value == 0xd83cdffe || value == 0xd83cdfff; } - public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size) { + public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew) { if (cs == null || cs.length() == 0) { return cs; } + //SpannableStringLight.isFieldsAvailable(); + //SpannableStringLight s = new SpannableStringLight(cs.toString()); Spannable s; - if (cs instanceof Spannable) { - s = (Spannable)cs; + if (!createNew && cs instanceof Spannable) { + s = (Spannable) cs; } else { - s = Spannable.Factory.getInstance().newSpannable(cs); + s = Spannable.Factory.getInstance().newSpannable(cs.toString()); } long buf = 0; int emojiCount = 0; + //s.setSpansCount(emojiCount); + try { for (int i = 0; i < cs.length(); i++) { char c = cs.charAt(i); @@ -450,12 +459,12 @@ public class Emoji { if (d != null) { boolean nextIsSkinTone = isNextCharIsColor(cs, i); EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); - emojiCount++; if (c >= 0xDDE6 && c <= 0xDDFA) { s.setSpan(span, i - 3, i + (nextIsSkinTone ? 3 : 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else { s.setSpan(span, i - 1, i + (nextIsSkinTone ? 3 : 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } + emojiCount++; if (nextIsSkinTone) { i += 2; } @@ -472,8 +481,8 @@ public class Emoji { if (d != null) { boolean nextIsSkinTone = isNextCharIsColor(cs, i); EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); - emojiCount++; s.setSpan(span, i - 1, i + (nextIsSkinTone ? 3 : 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + emojiCount++; if (nextIsSkinTone) { i += 2; } @@ -486,8 +495,8 @@ public class Emoji { if (d != null) { boolean nextIsSkinTone = isNextCharIsColor(cs, i); EmojiSpan span = new EmojiSpan(d, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); - emojiCount++; s.setSpan(span, i, i + (nextIsSkinTone ? 3 : 1), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + emojiCount++; if (nextIsSkinTone) { i += 2; } diff --git a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java index 3cf8e8277..21355c5d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/android/ImageLoader.java @@ -1285,6 +1285,9 @@ public class ImageLoader { } public Float getFileProgress(String location) { + if (location == null) { + return null; + } return fileProgresses.get(location); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MediaController.java b/TMessagesProj/src/main/java/org/telegram/android/MediaController.java index 273f3ba88..d7fda8509 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MediaController.java @@ -46,6 +46,8 @@ import android.os.Vibrator; import android.provider.MediaStore; import android.view.View; +import org.telegram.android.audioinfo.AudioInfo; +import org.telegram.android.query.SharedMediaQuery; import org.telegram.android.video.InputSurface; import org.telegram.android.video.MP4Builder; import org.telegram.android.video.Mp4Movie; @@ -78,22 +80,34 @@ import java.util.concurrent.Semaphore; public class MediaController implements NotificationCenter.NotificationCenterDelegate, SensorEventListener { private native int startRecord(String path); + private native int writeFrame(ByteBuffer frame, int len); + private native void stopRecord(); + private native int openOpusFile(String path); + private native int seekOpusFile(float position); + private native int isOpusFile(String path); + private native void closeOpusFile(); + private native void readOpusFile(ByteBuffer buffer, int capacity, int[] args); + private native long getTotalPcmDuration(); public static int[] readArgs = new int[3]; 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(); } @@ -127,6 +141,16 @@ public class MediaController implements NotificationCenter.NotificationCenterDel MediaStore.Video.Media.DATE_TAKEN }; + public static class AudioEntry { + public long id; + public String author; + public String title; + public String genre; + public int duration; + public String path; + public MessageObject messageObject; + } + public static class AlbumEntry { public int bucketId; public String bucketName; @@ -221,7 +245,10 @@ public class MediaController implements NotificationCenter.NotificationCenterDel private HashMap downloadQueueKeys = new HashMap<>(); private boolean saveToGallery = true; + private boolean shuffleMusic; + private int repeatMode; + private Runnable refreshGalleryRunnable; public static AlbumEntry allPhotosAlbumEntry; private HashMap>> loadingFileObservers = new HashMap<>(); @@ -249,6 +276,11 @@ public class MediaController implements NotificationCenter.NotificationCenterDel private final Object progressTimerSync = new Object(); private boolean useFrontSpeaker; private int buffersWrited; + private ArrayList playlist = new ArrayList<>(); + private ArrayList shuffledPlaylist = new ArrayList<>(); + private int currentPlaylistNum; + private boolean downloadingCurrentMessage; + private AudioInfo audioInfo; private AudioRecord audioRecorder = null; private TLRPC.TL_audio recordingAudio = null; @@ -271,6 +303,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel private int recordBufferSize; private boolean sendAfterDone; + private Runnable recordStartRunnable; private DispatchQueue recordQueue; private DispatchQueue fileEncodingQueue; private Runnable recordRunnable = new Runnable() { @@ -359,7 +392,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } - /*private class GalleryObserverInternal extends ContentObserver { + private class GalleryObserverInternal extends ContentObserver { public GalleryObserverInternal() { super(null); } @@ -367,9 +400,13 @@ public class MediaController implements NotificationCenter.NotificationCenterDel @Override public void onChange(boolean selfChange) { super.onChange(selfChange); - AndroidUtilities.runOnUIThread(new Runnable() { + if (refreshGalleryRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(refreshGalleryRunnable); + } + AndroidUtilities.runOnUIThread(refreshGalleryRunnable = new Runnable() { @Override public void run() { + refreshGalleryRunnable = null; loadGalleryPhotosAlbums(0); } }, 2000); @@ -384,14 +421,18 @@ public class MediaController implements NotificationCenter.NotificationCenterDel @Override public void onChange(boolean selfChange) { super.onChange(selfChange); - AndroidUtilities.runOnUIThread(new Runnable() { + if (refreshGalleryRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(refreshGalleryRunnable); + } + AndroidUtilities.runOnUIThread(refreshGalleryRunnable = new Runnable() { @Override public void run() { + refreshGalleryRunnable = null; loadGalleryPhotosAlbums(0); } }, 2000); } - }*/ + } private ExternalObserver externalObserver = null; private InternalObserver internalObserver = null; @@ -402,6 +443,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel private ArrayList lastSecretChatVisibleMessages = null; private int startObserverToken = 0; private StopMediaObserverRunnable stopMediaObserverRunnable = null; + private final class StopMediaObserverRunnable implements Runnable { public int currentObserverToken = 0; @@ -427,9 +469,11 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } } + private String[] mediaProjections = null; private static volatile MediaController Instance = null; + public static MediaController getInstance() { MediaController localInstance = Instance; if (localInstance == null) { @@ -484,6 +528,8 @@ public class MediaController implements NotificationCenter.NotificationCenterDel wifiDownloadMask = preferences.getInt("wifiDownloadMask", AUTODOWNLOAD_MASK_PHOTO | AUTODOWNLOAD_MASK_AUDIO); roamingDownloadMask = preferences.getInt("roamingDownloadMask", 0); saveToGallery = preferences.getBoolean("save_gallery", false); + shuffleMusic = preferences.getBoolean("shuffleMusic", false); + repeatMode = preferences.getInt("repeatMode", 0); NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidFailedLoad); NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileDidLoaded); @@ -491,6 +537,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileUploadProgressChanged); NotificationCenter.getInstance().addObserver(this, NotificationCenter.messagesDeleted); NotificationCenter.getInstance().addObserver(this, NotificationCenter.removeAllMessagesFromDialog); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.musicDidLoaded); BroadcastReceiver networkStateReceiver = new BroadcastReceiver() { @Override @@ -506,7 +553,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } if (Build.VERSION.SDK_INT >= 16) { - mediaProjections = new String[] { + mediaProjections = new String[]{ MediaStore.Images.ImageColumns.DATA, MediaStore.Images.ImageColumns.DISPLAY_NAME, MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, @@ -516,7 +563,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel MediaStore.Images.ImageColumns.HEIGHT }; } else { - mediaProjections = new String[] { + mediaProjections = new String[]{ MediaStore.Images.ImageColumns.DATA, MediaStore.Images.ImageColumns.DISPLAY_NAME, MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, @@ -525,7 +572,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel }; } - /*try { + try { ApplicationLoader.applicationContext.getContentResolver().registerContentObserver(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, false, new GalleryObserverExternal()); } catch (Exception e) { FileLog.e("tmessages", e); @@ -534,7 +581,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel ApplicationLoader.applicationContext.getContentResolver().registerContentObserver(MediaStore.Images.Media.INTERNAL_CONTENT_URI, false, new GalleryObserverInternal()); } catch (Exception e) { FileLog.e("tmessages", e); - }*/ + } } private void startProgressTimer() { @@ -606,12 +653,13 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } public void cleanup() { - clenupPlayer(false); + clenupPlayer(false, true); if (currentGifDrawable != null) { currentGifDrawable.recycle(); currentGifDrawable = null; } currentMediaCell = null; + audioInfo = null; currentGifMessageObject = null; photoDownloadQueue.clear(); audioDownloadQueue.clear(); @@ -619,6 +667,8 @@ public class MediaController implements NotificationCenter.NotificationCenterDel videoDownloadQueue.clear(); downloadQueueKeys.clear(); videoConvertQueue.clear(); + playlist.clear(); + shuffledPlaylist.clear(); typingTimes.clear(); cancelVideoConvert(null); } @@ -652,7 +702,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } else { for (DownloadObject downloadObject : photoDownloadQueue) { - FileLoader.getInstance().cancelLoadFile((TLRPC.PhotoSize)downloadObject.object); + FileLoader.getInstance().cancelLoadFile((TLRPC.PhotoSize) downloadObject.object); } photoDownloadQueue.clear(); } @@ -662,7 +712,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } else { for (DownloadObject downloadObject : audioDownloadQueue) { - FileLoader.getInstance().cancelLoadFile((TLRPC.Audio)downloadObject.object); + FileLoader.getInstance().cancelLoadFile((TLRPC.Audio) downloadObject.object); } audioDownloadQueue.clear(); } @@ -672,7 +722,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } else { for (DownloadObject downloadObject : documentDownloadQueue) { - FileLoader.getInstance().cancelLoadFile((TLRPC.Document)downloadObject.object); + FileLoader.getInstance().cancelLoadFile((TLRPC.Document) downloadObject.object); } documentDownloadQueue.clear(); } @@ -682,7 +732,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } else { for (DownloadObject downloadObject : videoDownloadQueue) { - FileLoader.getInstance().cancelLoadFile((TLRPC.Video)downloadObject.object); + FileLoader.getInstance().cancelLoadFile((TLRPC.Video) downloadObject.object); } videoDownloadQueue.clear(); } @@ -713,7 +763,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel private int getCurrentDownloadMask() { if (ConnectionsManager.isConnectedToWiFi()) { return wifiDownloadMask; - } else if(ConnectionsManager.isRoaming()) { + } else if (ConnectionsManager.isRoaming()) { return roamingDownloadMask; } else { return mobileDataDownloadMask; @@ -742,13 +792,13 @@ public class MediaController implements NotificationCenter.NotificationCenterDel boolean added = true; if (downloadObject.object instanceof TLRPC.Audio) { - FileLoader.getInstance().loadFile((TLRPC.Audio)downloadObject.object, false); + FileLoader.getInstance().loadFile((TLRPC.Audio) downloadObject.object, false); } else if (downloadObject.object instanceof TLRPC.PhotoSize) { - FileLoader.getInstance().loadFile((TLRPC.PhotoSize)downloadObject.object, null, false); + FileLoader.getInstance().loadFile((TLRPC.PhotoSize) downloadObject.object, null, false); } else if (downloadObject.object instanceof TLRPC.Video) { - FileLoader.getInstance().loadFile((TLRPC.Video)downloadObject.object, false); + FileLoader.getInstance().loadFile((TLRPC.Video) downloadObject.object, false); } else if (downloadObject.object instanceof TLRPC.Document) { - FileLoader.getInstance().loadFile((TLRPC.Document)downloadObject.object, false, false); + FileLoader.getInstance().loadFile((TLRPC.Document) downloadObject.object, false, false); } else { added = false; } @@ -986,7 +1036,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel public void didReceivedNotification(int id, Object... args) { if (id == NotificationCenter.FileDidFailedLoad) { listenerInProgress = true; - String fileName = (String)args[0]; + String fileName = (String) args[0]; ArrayList> arrayList = loadingFileObservers.get(fileName); if (arrayList != null) { for (WeakReference reference : arrayList) { @@ -999,10 +1049,16 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } listenerInProgress = false; processLaterArrays(); - checkDownloadFinished(fileName, (Integer)args[1]); + checkDownloadFinished(fileName, (Integer) args[1]); } else if (id == NotificationCenter.FileDidLoaded) { listenerInProgress = true; - String fileName = (String)args[0]; + String fileName = (String) args[0]; + if (downloadingCurrentMessage && playingMessageObject != null) { + String file = FileLoader.getAttachFileName(playingMessageObject.messageOwner.media.document); + if (file.equals(fileName)) { + playAudio(playingMessageObject); + } + } ArrayList> arrayList = loadingFileObservers.get(fileName); if (arrayList != null) { for (WeakReference reference : arrayList) { @@ -1018,10 +1074,10 @@ public class MediaController implements NotificationCenter.NotificationCenterDel checkDownloadFinished(fileName, 0); } else if (id == NotificationCenter.FileLoadProgressChanged) { listenerInProgress = true; - String fileName = (String)args[0]; + String fileName = (String) args[0]; ArrayList> arrayList = loadingFileObservers.get(fileName); if (arrayList != null) { - Float progress = (Float)args[1]; + Float progress = (Float) args[1]; for (WeakReference reference : arrayList) { if (reference.get() != null) { reference.get().onProgressDownload(fileName, progress); @@ -1032,11 +1088,11 @@ public class MediaController implements NotificationCenter.NotificationCenterDel processLaterArrays(); } else if (id == NotificationCenter.FileUploadProgressChanged) { listenerInProgress = true; - String fileName = (String)args[0]; + String fileName = (String) args[0]; ArrayList> arrayList = loadingFileObservers.get(fileName); if (arrayList != null) { - Float progress = (Float)args[1]; - Boolean enc = (Boolean)args[2]; + Float progress = (Float) args[1]; + Boolean enc = (Boolean) args[2]; for (WeakReference reference : arrayList) { if (reference.get() != null) { reference.get().onProgressUpload(fileName, progress, enc); @@ -1070,15 +1126,27 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } else if (id == NotificationCenter.messagesDeleted) { if (playingMessageObject != null) { - ArrayList markAsDeletedMessages = (ArrayList)args[0]; + ArrayList markAsDeletedMessages = (ArrayList) args[0]; if (markAsDeletedMessages.contains(playingMessageObject.getId())) { - clenupPlayer(false); + clenupPlayer(false, true); } } } else if (id == NotificationCenter.removeAllMessagesFromDialog) { - long did = (Long)args[0]; + long did = (Long) args[0]; if (playingMessageObject != null && playingMessageObject.getDialogId() == did) { - clenupPlayer(false); + clenupPlayer(false, true); + } + } else if (id == NotificationCenter.musicDidLoaded) { + long did = (Long) args[0]; + if (playingMessageObject != null && playingMessageObject.isMusic() && playingMessageObject.getDialogId() == did) { + ArrayList arrayList = (ArrayList) args[1]; + playlist.addAll(0, arrayList); + if (shuffleMusic) { + buildShuffledPlayList(); + currentPlaylistNum = 0; + } else { + currentPlaylistNum += arrayList.size(); + } } } } @@ -1174,7 +1242,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel audioTrackPlayer.setNotificationMarkerPosition(1); } if (finalBuffersWrited == 1) { - clenupPlayer(true); + clenupPlayer(true, true); } } } @@ -1221,7 +1289,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioRouteChanged, useFrontSpeaker); MessageObject currentMessageObject = playingMessageObject; float progress = playingMessageObject.audioProgress; - clenupPlayer(false); + clenupPlayer(false, true); currentMessageObject.audioProgress = progress; playAudio(currentMessageObject); ignoreProximity = false; @@ -1266,9 +1334,9 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } - private void clenupPlayer(boolean notify) { + public void clenupPlayer(boolean notify, boolean stopService) { stopProximitySensor(); - if (audioPlayer != null || audioTrackPlayer != null) { + if (playingMessageObject != null) { if (audioPlayer != null) { try { audioPlayer.stop(); @@ -1301,12 +1369,20 @@ public class MediaController implements NotificationCenter.NotificationCenterDel lastProgress = 0; buffersWrited = 0; isPaused = false; + if (downloadingCurrentMessage) { + FileLoader.getInstance().cancelLoadFile(playingMessageObject.messageOwner.media.document); + } MessageObject lastFile = playingMessageObject; playingMessageObject.audioProgress = 0.0f; playingMessageObject.audioProgressSec = 0; playingMessageObject = null; + downloadingCurrentMessage = false; if (notify) { - NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidReset, lastFile.getId()); + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidReset, lastFile.getId(), stopService); + } + if (stopService) { + Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class); + ApplicationLoader.applicationContext.stopService(intent); } } } @@ -1364,6 +1440,151 @@ public class MediaController implements NotificationCenter.NotificationCenterDel return true; } + public MessageObject getPlayingMessageObject() { + return playingMessageObject; + } + + private void buildShuffledPlayList() { + ArrayList all = new ArrayList<>(playlist); + shuffledPlaylist.clear(); + + MessageObject messageObject = playlist.get(currentPlaylistNum); + all.remove(currentPlaylistNum); + shuffledPlaylist.add(messageObject); + + int count = all.size(); + for (int a = 0; a < count; a++) { + int index = Utilities.random.nextInt(all.size()); + shuffledPlaylist.add(all.get(index)); + all.remove(index); + } + } + + public boolean setPlaylist(ArrayList messageObjects, MessageObject current) { + if (playingMessageObject == current) { + return playAudio(current); + } + playlist.clear(); + for (int a = messageObjects.size() - 1; a >= 0; a--) { + MessageObject messageObject = messageObjects.get(a); + if (messageObject.isMusic()) { + playlist.add(messageObject); + } + } + currentPlaylistNum = playlist.indexOf(current); + if (currentPlaylistNum == -1) { + playlist.clear(); + shuffledPlaylist.clear(); + return false; + } + if (shuffleMusic) { + buildShuffledPlayList(); + currentPlaylistNum = 0; + } + SharedMediaQuery.loadMusic(current.getDialogId(), playlist.get(0).getId()); + return playAudio(current); + } + + public void playNextMessage() { + playNextMessage(false); + } + + private void playNextMessage(boolean byStop) { + ArrayList currentPlayList = shuffleMusic ? shuffledPlaylist : playlist; + + if (byStop && repeatMode == 2) { + clenupPlayer(false, false); + playAudio(currentPlayList.get(currentPlaylistNum)); + return; + } + currentPlaylistNum++; + if (currentPlaylistNum >= currentPlayList.size()) { + currentPlaylistNum = 0; + if (byStop && repeatMode == 0) { + stopProximitySensor(); + if (audioPlayer != null || audioTrackPlayer != null) { + if (audioPlayer != null) { + try { + audioPlayer.stop(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + try { + audioPlayer.release(); + audioPlayer = null; + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } else if (audioTrackPlayer != null) { + synchronized (playerObjectSync) { + try { + audioTrackPlayer.pause(); + audioTrackPlayer.flush(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + try { + audioTrackPlayer.release(); + audioTrackPlayer = null; + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + } + stopProgressTimer(); + lastProgress = 0; + buffersWrited = 0; + isPaused = true; + playingMessageObject.audioProgress = 0.0f; + playingMessageObject.audioProgressSec = 0; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioPlayStateChanged, playingMessageObject.getId()); + } + return; + } + } + if (currentPlaylistNum < 0 || currentPlaylistNum >= currentPlayList.size()) { + return; + } + playAudio(currentPlayList.get(currentPlaylistNum)); + } + + public void playPreviousMessage() { + ArrayList currentPlayList = shuffleMusic ? shuffledPlaylist : playlist; + + currentPlaylistNum--; + if (currentPlaylistNum < 0) { + currentPlaylistNum = currentPlayList.size() - 1; + } + if (currentPlaylistNum < 0 || currentPlaylistNum >= currentPlayList.size()) { + return; + } + playAudio(currentPlayList.get(currentPlaylistNum)); + } + + private void checkIsNextMusicFileDownloaded() { + ArrayList currentPlayList = shuffleMusic ? shuffledPlaylist : playlist; + if (currentPlayList == null || currentPlayList.size() < 2) { + return; + } + int nextIndex = currentPlaylistNum + 1; + if (nextIndex >= currentPlayList.size()) { + nextIndex = 0; + } + MessageObject nextAudio = currentPlayList.get(nextIndex); + File file = null; + if (nextAudio.messageOwner.attachPath != null && nextAudio.messageOwner.attachPath.length() > 0) { + file = new File(nextAudio.messageOwner.attachPath); + if (!file.exists()) { + file = null; + } + } + final File cacheFile = file != null ? file : FileLoader.getPathToMessage(nextAudio.messageOwner); + boolean exist = cacheFile != null && cacheFile.exists(); + if (cacheFile != null && cacheFile != file && !cacheFile.exists() && nextAudio.isMusic()) { + FileLoader.getInstance().loadFile(nextAudio.messageOwner.media.document, true, false); + } + } + public boolean playAudio(MessageObject messageObject) { if (messageObject == null) { return false; @@ -1374,8 +1595,10 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } return true; } - NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidStarted, messageObject); - clenupPlayer(true); + if (audioTrackPlayer != null) { + MusicPlayerService.setIgnoreAudioFocus(); + } + clenupPlayer(true, false); File file = null; if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() > 0) { file = new File(messageObject.messageOwner.attachPath); @@ -1384,8 +1607,33 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } final File cacheFile = file != null ? file : FileLoader.getPathToMessage(messageObject.messageOwner); + if (cacheFile != null && cacheFile != file && !cacheFile.exists() && messageObject.isMusic()) { + FileLoader.getInstance().loadFile(messageObject.messageOwner.media.document, true, false); + downloadingCurrentMessage = true; + isPaused = false; + lastProgress = 0; + lastPlayPcm = 0; + audioInfo = null; + playingMessageObject = messageObject; + if (playingMessageObject.messageOwner.media.document != null) { + Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class); + ApplicationLoader.applicationContext.startService(intent); + } else { + Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class); + ApplicationLoader.applicationContext.stopService(intent); + } + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioPlayStateChanged, playingMessageObject.getId()); + return true; + } else { + downloadingCurrentMessage = false; + } + if (messageObject.isMusic()) { + checkIsNextMusicFileDownloaded(); + } if (isOpusFile(cacheFile.getAbsolutePath()) == 1) { + playlist.clear(); + shuffledPlaylist.clear(); synchronized (playerObjectSync) { try { ignoreFirstProgress = 3; @@ -1410,7 +1658,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel audioTrackPlayer.setPlaybackPositionUpdateListener(new AudioTrack.OnPlaybackPositionUpdateListener() { @Override public void onMarkerReached(AudioTrack audioTrack) { - clenupPlayer(true); + clenupPlayer(true, true); } @Override @@ -1420,7 +1668,9 @@ public class MediaController implements NotificationCenter.NotificationCenterDel }); audioTrackPlayer.play(); startProgressTimer(); - startProximitySensor(); + if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaAudio) { + startProximitySensor(); + } } catch (Exception e) { FileLog.e("tmessages", e); if (audioTrackPlayer != null) { @@ -1428,6 +1678,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel audioTrackPlayer = null; isPaused = false; playingMessageObject = null; + downloadingCurrentMessage = false; } return false; } @@ -1440,13 +1691,28 @@ public class MediaController implements NotificationCenter.NotificationCenterDel audioPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mediaPlayer) { - clenupPlayer(true); + if (!playlist.isEmpty() && playlist.size() > 1) { + playNextMessage(true); + } else { + clenupPlayer(true, true); + } } }); audioPlayer.prepare(); audioPlayer.start(); startProgressTimer(); - startProximitySensor(); + if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaAudio) { + audioInfo = null; + playlist.clear(); + shuffledPlaylist.clear(); + startProximitySensor(); + } else { + try { + audioInfo = AudioInfo.getAudioInfo(cacheFile); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } } catch (Exception e) { FileLog.e("tmessages", e); if (audioPlayer != null) { @@ -1454,6 +1720,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel audioPlayer = null; isPaused = false; playingMessageObject = null; + downloadingCurrentMessage = false; } return false; } @@ -1463,6 +1730,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel lastProgress = 0; lastPlayPcm = 0; playingMessageObject = messageObject; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioDidStarted, messageObject); if (audioPlayer != null) { try { @@ -1484,7 +1752,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel public void run() { try { if (playingMessageObject != null && playingMessageObject.audioProgress != 0) { - lastPlayPcm = (long)(currentTotalPcmDuration * playingMessageObject.audioProgress); + lastPlayPcm = (long) (currentTotalPcmDuration * playingMessageObject.audioProgress); seekOpusFile(playingMessageObject.audioProgress); } } catch (Exception e) { @@ -1500,6 +1768,14 @@ public class MediaController implements NotificationCenter.NotificationCenterDel }); } + if (playingMessageObject.messageOwner.media.document != null) { + Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class); + ApplicationLoader.applicationContext.startService(intent); + } else { + Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class); + ApplicationLoader.applicationContext.stopService(intent); + } + return true; } @@ -1533,7 +1809,55 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } stopProgressTimer(); playingMessageObject = null; + downloadingCurrentMessage = false; isPaused = false; + + Intent intent = new Intent(ApplicationLoader.applicationContext, MusicPlayerService.class); + ApplicationLoader.applicationContext.stopService(intent); + } + + public AudioInfo getAudioInfo() { + return audioInfo; + } + + public boolean isShuffleMusic() { + return shuffleMusic; + } + + public int getRepeatMode() { + return repeatMode; + } + + public void toggleShuffleMusic() { + shuffleMusic = !shuffleMusic; + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("shuffleMusic", shuffleMusic); + editor.commit(); + if (shuffleMusic) { + buildShuffledPlayList(); + currentPlaylistNum = 0; + } else { + if (playingMessageObject != null) { + currentPlaylistNum = playlist.indexOf(playingMessageObject); + if (currentPlaylistNum == -1) { + playlist.clear(); + shuffledPlaylist.clear(); + clenupPlayer(true, true); + } + } + } + } + + public void toggleRepeatMode() { + repeatMode++; + if (repeatMode > 2) { + repeatMode = 0; + } + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + editor.putInt("repeatMode", repeatMode); + editor.commit(); } public boolean pauseAudio(MessageObject messageObject) { @@ -1549,6 +1873,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel audioTrackPlayer.pause(); } isPaused = true; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioPlayStateChanged, playingMessageObject.getId()); } catch (Exception e) { FileLog.e("tmessages", e); isPaused = false; @@ -1561,7 +1886,9 @@ public class MediaController implements NotificationCenter.NotificationCenterDel if (audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.getId() != messageObject.getId()) { return false; } - startProximitySensor(); + if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaAudio) { + startProximitySensor(); + } try { startProgressTimer(); if (audioPlayer != null) { @@ -1571,6 +1898,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel checkPlayerQueue(); } isPaused = false; + NotificationCenter.getInstance().postNotificationName(NotificationCenter.audioPlayStateChanged, playingMessageObject.getId()); } catch (Exception e) { FileLog.e("tmessages", e); return false; @@ -1579,15 +1907,23 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } public boolean isPlayingAudio(MessageObject messageObject) { - return !(audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && playingMessageObject.getId() != messageObject.getId()); + return !(audioTrackPlayer == null && audioPlayer == null || messageObject == null || playingMessageObject == null || playingMessageObject != null && (playingMessageObject.getId() != messageObject.getId() || downloadingCurrentMessage)); } public boolean isAudioPaused() { - return isPaused; + return isPaused || downloadingCurrentMessage; + } + + public boolean isDownloadingCurrentMessage() { + return downloadingCurrentMessage; } public void startRecording(final long dialog_id, final MessageObject reply_to_msg) { - clenupPlayer(true); + boolean paused = false; + if (playingMessageObject != null && isPlayingAudio(playingMessageObject) && !isAudioPaused()) { + paused = true; + pauseAudio(playingMessageObject); + } try { Vibrator v = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE); @@ -1596,13 +1932,14 @@ public class MediaController implements NotificationCenter.NotificationCenterDel FileLog.e("tmessages", e); } - recordQueue.postRunnable(new Runnable() { + recordQueue.postRunnable(recordStartRunnable = new Runnable() { @Override public void run() { if (audioRecorder != null) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + recordStartRunnable = null; NotificationCenter.getInstance().postNotificationName(NotificationCenter.recordStartError); } }); @@ -1624,6 +1961,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + recordStartRunnable = null; NotificationCenter.getInstance().postNotificationName(NotificationCenter.recordStartError); } }); @@ -1653,6 +1991,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + recordStartRunnable = null; NotificationCenter.getInstance().postNotificationName(NotificationCenter.recordStartError); } }); @@ -1663,11 +2002,12 @@ public class MediaController implements NotificationCenter.NotificationCenterDel AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { + recordStartRunnable = null; NotificationCenter.getInstance().postNotificationName(NotificationCenter.recordStarted); } }); } - }); + }, paused ? 500 : 0); } private void stopRecordingInternal(final boolean send) { @@ -1709,6 +2049,9 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } public void stopRecording(final boolean send) { + if (recordStartRunnable != null) { + recordQueue.cancelRunnable(recordStartRunnable); + } recordQueue.postRunnable(new Runnable() { @Override public void run() { @@ -1790,10 +2133,15 @@ public class MediaController implements NotificationCenter.NotificationCenterDel destFile = AndroidUtilities.generateVideoPath(); } else if (type == 2) { File f = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); + f.mkdir(); + destFile = new File(f, name); + } else if (type == 3) { + File f = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC); + f.mkdirs(); destFile = new File(f, name); } - if(!destFile.exists()) { + if (!destFile.exists()) { destFile.createNewFile(); } FileChannel source = null; @@ -1835,7 +2183,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel } } - if (result && (type == 0 || type == 1)) { + if (result && (type == 0 || type == 1 || type == 3)) { AndroidUtilities.addMediaToGallery(Uri.fromFile(destFile)); } } catch (Exception e) { @@ -1940,7 +2288,7 @@ public class MediaController implements NotificationCenter.NotificationCenterDel String str = new String(header); if (str != null) { str = str.toLowerCase(); - if (str.startsWith("riff") && str.endsWith("webp")){ + if (str.startsWith("riff") && str.endsWith("webp")) { return true; } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java index 48aaa2651..7569f9cb0 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessageObject.java @@ -313,6 +313,8 @@ public class MessageObject { } else { messageText = LocaleController.getString("AttachSticker", R.string.AttachSticker); } + } else if (isMusic()) { + messageText = LocaleController.getString("AttachMusic", R.string.AttachMusic); } else { String name = FileLoader.getDocumentFileName(message.media.document); if (name != null && name.length() > 0) { @@ -327,7 +329,9 @@ public class MessageObject { } else { messageText = message.message; } - messageText = Emoji.replaceEmoji(messageText, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20)); + if (generateLayout) { + messageText = Emoji.replaceEmoji(messageText, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + } if (message instanceof TLRPC.TL_message || message instanceof TLRPC.TL_messageForwarded_old2) { if (isMediaEmpty()) { @@ -355,6 +359,9 @@ public class MessageObject { type = 8; } else if (message.media.document.mime_type.equals("image/webp") && isSticker()) { type = 13; + } else if (isMusic()) { + type = 14; + contentType = 8; } else { type = 9; } @@ -600,7 +607,7 @@ public class MessageObject { return; } if (messageOwner.media != null && messageOwner.media.caption != null && messageOwner.media.caption.length() > 0) { - caption = Emoji.replaceEmoji(messageOwner.media.caption, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20)); + caption = Emoji.replaceEmoji(messageOwner.media.caption, textPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); if (containsUrls(caption)) { try { Linkify.addLinks((Spannable) caption, Linkify.WEB_URLS); @@ -950,6 +957,17 @@ public class MessageObject { return false; } + public static boolean isMusicMessage(TLRPC.Message message) { + if (message.media != null && message.media.document != null) { + for (TLRPC.DocumentAttribute attribute : message.media.document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeAudio) { + return true; + } + } + } + return false; + } + public static TLRPC.InputStickerSet getInputStickerSet(TLRPC.Message message) { if (message.media != null && message.media.document != null) { for (TLRPC.DocumentAttribute attribute : message.media.document.attributes) { @@ -986,6 +1004,8 @@ public class MessageObject { return AndroidUtilities.dp(100); } else if (type == 4) { return AndroidUtilities.dp(114); + } else if (type == 14) { + return AndroidUtilities.dp(78); } else if (type == 13) { float maxHeight = AndroidUtilities.displaySize.y * 0.4f; float maxWidth; @@ -1061,6 +1081,39 @@ public class MessageObject { return isStickerMessage(messageOwner); } + public boolean isMusic() { + return isMusicMessage(messageOwner); + } + + public String getMusicTitle() { + for (TLRPC.DocumentAttribute attribute : messageOwner.media.document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeAudio) { + String title = attribute.title; + if (title == null || title.length() == 0) { + title = FileLoader.getDocumentFileName(messageOwner.media.document); + if (title == null || title.length() == 0) { + title = LocaleController.getString("AudioUnknownTitle", R.string.AudioUnknownTitle); + } + } + return title; + } + } + return ""; + } + + public String getMusicAuthor() { + for (TLRPC.DocumentAttribute attribute : messageOwner.media.document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeAudio) { + String performer = attribute.performer; + if (performer == null || performer.length() == 0) { + performer = LocaleController.getString("AudioUnknownArtist", R.string.AudioUnknownArtist); + } + return performer; + } + } + return ""; + } + public TLRPC.InputStickerSet getInputStickerSet() { return getInputStickerSet(messageOwner); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java index 156d4b38c..6bcaf3359 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesController.java @@ -3900,7 +3900,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter } if (!markAsReadMessagesInbox.isEmpty() || !markAsReadMessagesOutbox.isEmpty() || !markAsReadEncrypted.isEmpty()) { if (!markAsReadMessagesInbox.isEmpty() || !markAsReadMessagesOutbox.isEmpty()) { - MessagesStorage.getInstance().updateDialogsWithReadedMessages(markAsReadMessagesInbox, true); + MessagesStorage.getInstance().updateDialogsWithReadMessages(markAsReadMessagesInbox, true); } MessagesStorage.getInstance().markMessagesAsRead(markAsReadMessagesInbox, markAsReadMessagesOutbox, markAsReadEncrypted, true); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java index b5030041b..ad37757fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/android/MessagesStorage.java @@ -1149,7 +1149,7 @@ public class MessagesStorage { }); } - private void updateDialogsWithReadedMessagesInternal(final ArrayList messages, final HashMap inbox) { + private void updateDialogsWithReadMessagesInternal(final ArrayList messages, final HashMap inbox) { try { HashMap dialogsToUpdate = new HashMap<>(); StringBuilder dialogsToReload = new StringBuilder(); @@ -1184,14 +1184,13 @@ public class MessagesStorage { SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM messages WHERE uid = %d AND mid <= %d AND read_state IN(0,2) AND out = 0", entry.getKey(), entry.getValue())); if (cursor.next()) { int count = cursor.intValue(0); - if (count == 0) { - continue; + if (count != 0) { + dialogsToUpdate.put((long) entry.getKey(), count); + if (dialogsToReload.length() != 0) { + dialogsToReload.append(","); + } + dialogsToReload.append(entry.getKey()); } - dialogsToUpdate.put((long) entry.getKey(), count); - if (dialogsToReload.length() != 0) { - dialogsToReload.append(","); - } - dialogsToReload.append(entry.getKey()); } cursor.dispose(); } @@ -1231,7 +1230,7 @@ public class MessagesStorage { } } - public void updateDialogsWithReadedMessages(final HashMap inbox, boolean useQueue) { + public void updateDialogsWithReadMessages(final HashMap inbox, boolean useQueue) { if (inbox.isEmpty()) { return; } @@ -1239,11 +1238,11 @@ public class MessagesStorage { storageQueue.postRunnable(new Runnable() { @Override public void run() { - updateDialogsWithReadedMessagesInternal(null, inbox); + updateDialogsWithReadMessagesInternal(null, inbox); } }); } else { - updateDialogsWithReadedMessagesInternal(null, inbox); + updateDialogsWithReadMessagesInternal(null, inbox); } } @@ -3473,7 +3472,7 @@ public class MessagesStorage { NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDeleted, mids); } }); - MessagesStorage.getInstance().updateDialogsWithReadedMessagesInternal(mids, null); + MessagesStorage.getInstance().updateDialogsWithReadMessagesInternal(mids, null); MessagesStorage.getInstance().markMessagesAsDeletedInternal(mids); MessagesStorage.getInstance().updateDialogsWithDeletedMessagesInternal(mids); } diff --git a/TMessagesProj/src/main/java/org/telegram/android/MusicPlayerReceiver.java b/TMessagesProj/src/main/java/org/telegram/android/MusicPlayerReceiver.java new file mode 100644 index 000000000..eb129930e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/MusicPlayerReceiver.java @@ -0,0 +1,69 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.android; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.view.KeyEvent; + +public class MusicPlayerReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) { + if (intent.getExtras() == null) { + return; + } + KeyEvent keyEvent = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT); + if (keyEvent == null) { + return; + } + if (keyEvent.getAction() != KeyEvent.ACTION_DOWN) + return; + + switch (keyEvent.getKeyCode()) { + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + if (MediaController.getInstance().isAudioPaused()) { + MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject()); + } else { + MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); + } + break; + case KeyEvent.KEYCODE_MEDIA_PLAY: + MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject()); + break; + case KeyEvent.KEYCODE_MEDIA_PAUSE: + MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); + break; + case KeyEvent.KEYCODE_MEDIA_STOP: + break; + case KeyEvent.KEYCODE_MEDIA_NEXT: + MediaController.getInstance().playNextMessage(); + break; + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + MediaController.getInstance().playPreviousMessage(); + break; + } + } else { + if (intent.getAction().equals(MusicPlayerService.NOTIFY_PLAY)) { + MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject()); + } else if (intent.getAction().equals(MusicPlayerService.NOTIFY_PAUSE) || intent.getAction().equals(android.media.AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { + MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); + } else if (intent.getAction().equals(MusicPlayerService.NOTIFY_NEXT)) { + MediaController.getInstance().playNextMessage(); + } else if (intent.getAction().equals(MusicPlayerService.NOTIFY_CLOSE)) { + MediaController.getInstance().clenupPlayer(true, true); + } else if (intent.getAction().equals(MusicPlayerService.NOTIFY_PREVIOUS)) { + MediaController.getInstance().playPreviousMessage(); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/MusicPlayerService.java b/TMessagesProj/src/main/java/org/telegram/android/MusicPlayerService.java new file mode 100644 index 000000000..6201d7e08 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/MusicPlayerService.java @@ -0,0 +1,295 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.android; + +import android.annotation.SuppressLint; +import android.app.Notification; +import android.app.PendingIntent; +import android.app.Service; +import android.content.ComponentName; +import android.content.Intent; +import android.graphics.Bitmap; +import android.media.AudioManager; +import android.media.MediaMetadataRetriever; +import android.media.RemoteControlClient; +import android.os.Build; +import android.os.IBinder; +import android.support.v4.app.NotificationCompat; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; +import android.view.View; +import android.widget.RemoteViews; + +import org.telegram.android.audioinfo.AudioInfo; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; +import org.telegram.ui.LaunchActivity; + +public class MusicPlayerService extends Service implements AudioManager.OnAudioFocusChangeListener, NotificationCenter.NotificationCenterDelegate { + + public static final String NOTIFY_PREVIOUS = "org.telegram.android.musicplayer.previous"; + public static final String NOTIFY_CLOSE = "org.telegram.android.musicplayer.close"; + public static final String NOTIFY_PAUSE = "org.telegram.android.musicplayer.pause"; + public static final String NOTIFY_PLAY = "org.telegram.android.musicplayer.play"; + public static final String NOTIFY_NEXT = "org.telegram.android.musicplayer.next"; + + private RemoteControlClient remoteControlClient; + private AudioManager audioManager; + private static boolean ignoreAudioFocus = false; + private PhoneStateListener phoneStateListener; + + private static boolean supportBigNotifications = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; + private static boolean supportLockScreenControls = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH; + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioProgressDidChanged); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged); + try { + phoneStateListener = new PhoneStateListener() { + @Override + public void onCallStateChanged(int state, String incomingNumber) { + if (state == TelephonyManager.CALL_STATE_RINGING) { + if (MediaController.getInstance().isPlayingAudio(MediaController.getInstance().getPlayingMessageObject()) && !MediaController.getInstance().isAudioPaused()) { + MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); + } + } else if (state == TelephonyManager.CALL_STATE_IDLE) { + + } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) { + + } + super.onCallStateChanged(state, incomingNumber); + } + }; + TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); + if (mgr != null) { + mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + super.onCreate(); + } + + @SuppressLint("NewApi") + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + try { + MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + if (messageObject == null) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + stopSelf(); + } + }); + return START_STICKY; + } + if (supportLockScreenControls) { + ComponentName remoteComponentName = new ComponentName(getApplicationContext(), MusicPlayerReceiver.class.getName()); + try { + if (remoteControlClient == null) { + audioManager.registerMediaButtonEventReceiver(remoteComponentName); + Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); + mediaButtonIntent.setComponent(remoteComponentName); + PendingIntent mediaPendingIntent = PendingIntent.getBroadcast(this, 0, mediaButtonIntent, 0); + remoteControlClient = new RemoteControlClient(mediaPendingIntent); + audioManager.registerRemoteControlClient(remoteControlClient); + } + remoteControlClient.setTransportControlFlags(RemoteControlClient.FLAG_KEY_MEDIA_PLAY | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE | + RemoteControlClient.FLAG_KEY_MEDIA_STOP | RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS | RemoteControlClient.FLAG_KEY_MEDIA_NEXT); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + } + createNotification(messageObject); + } catch (Exception e) { + e.printStackTrace(); + } + return START_STICKY; + } + + @SuppressLint("NewApi") + private void createNotification(MessageObject messageObject) { + String songName = messageObject.getMusicTitle(); + String authorName = messageObject.getMusicAuthor(); + AudioInfo audioInfo = MediaController.getInstance().getAudioInfo(); + + RemoteViews simpleContentView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.player_small_notification); + RemoteViews expandedView = null; + if (supportBigNotifications) { + expandedView = new RemoteViews(getApplicationContext().getPackageName(), R.layout.player_big_notification); + } + + Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class); + intent.setAction("com.tmessages.openplayer"); + intent.setFlags(32768); + PendingIntent contentIntent = PendingIntent.getActivity(ApplicationLoader.applicationContext, 0, intent, 0); + + Notification notification = new NotificationCompat.Builder(getApplicationContext()) + .setSmallIcon(R.drawable.player) + .setContentIntent(contentIntent) + .setContentTitle(songName).build(); + + notification.contentView = simpleContentView; + if (supportBigNotifications) { + notification.bigContentView = expandedView; + } + + setListeners(simpleContentView); + if (supportBigNotifications) { + setListeners(expandedView); + } + + Bitmap albumArt = audioInfo != null ? audioInfo.getSmallCover() : null; + if (albumArt != null) { + notification.contentView.setImageViewBitmap(R.id.player_album_art, albumArt); + if (supportBigNotifications) { + notification.bigContentView.setImageViewBitmap(R.id.player_album_art, albumArt); + } + } else { + notification.contentView.setImageViewResource(R.id.player_album_art, R.drawable.nocover_small); + if (supportBigNotifications) { + notification.bigContentView.setImageViewResource(R.id.player_album_art, R.drawable.nocover_big); + } + } + if (MediaController.getInstance().isDownloadingCurrentMessage()) { + notification.contentView.setViewVisibility(R.id.player_pause, View.GONE); + notification.contentView.setViewVisibility(R.id.player_play, View.GONE); + notification.contentView.setViewVisibility(R.id.player_next, View.GONE); + notification.contentView.setViewVisibility(R.id.player_previous, View.GONE); + notification.contentView.setViewVisibility(R.id.player_progress_bar, View.VISIBLE); + if (supportBigNotifications) { + notification.bigContentView.setViewVisibility(R.id.player_pause, View.GONE); + notification.bigContentView.setViewVisibility(R.id.player_play, View.GONE); + notification.bigContentView.setViewVisibility(R.id.player_next, View.GONE); + notification.bigContentView.setViewVisibility(R.id.player_previous, View.GONE); + notification.bigContentView.setViewVisibility(R.id.player_progress_bar, View.VISIBLE); + } + } else { + notification.contentView.setViewVisibility(R.id.player_progress_bar, View.GONE); + notification.contentView.setViewVisibility(R.id.player_next, View.VISIBLE); + notification.contentView.setViewVisibility(R.id.player_previous, View.VISIBLE); + if (supportBigNotifications) { + notification.bigContentView.setViewVisibility(R.id.player_next, View.VISIBLE); + notification.bigContentView.setViewVisibility(R.id.player_previous, View.VISIBLE); + notification.bigContentView.setViewVisibility(R.id.player_progress_bar, View.GONE); + } + + if (MediaController.getInstance().isAudioPaused()) { + notification.contentView.setViewVisibility(R.id.player_pause, View.GONE); + notification.contentView.setViewVisibility(R.id.player_play, View.VISIBLE); + if (supportBigNotifications) { + notification.bigContentView.setViewVisibility(R.id.player_pause, View.GONE); + notification.bigContentView.setViewVisibility(R.id.player_play, View.VISIBLE); + } + } else { + notification.contentView.setViewVisibility(R.id.player_pause, View.VISIBLE); + notification.contentView.setViewVisibility(R.id.player_play, View.GONE); + if (supportBigNotifications) { + notification.bigContentView.setViewVisibility(R.id.player_pause, View.VISIBLE); + notification.bigContentView.setViewVisibility(R.id.player_play, View.GONE); + } + } + } + + notification.contentView.setTextViewText(R.id.player_song_name, songName); + notification.contentView.setTextViewText(R.id.player_author_name, authorName); + if (supportBigNotifications) { + notification.bigContentView.setTextViewText(R.id.player_song_name, songName); + notification.bigContentView.setTextViewText(R.id.player_author_name, authorName); + } + notification.flags |= Notification.FLAG_ONGOING_EVENT; + startForeground(5, notification); + + if (remoteControlClient != null) { + RemoteControlClient.MetadataEditor metadataEditor = remoteControlClient.editMetadata(true); + metadataEditor.putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, authorName); + metadataEditor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, songName); + if (audioInfo != null && audioInfo.getCover() != null) { + metadataEditor.putBitmap(RemoteControlClient.MetadataEditor.BITMAP_KEY_ARTWORK, audioInfo.getCover()); + } + metadataEditor.apply(); + audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); + } + } + + public void setListeners(RemoteViews view) { + PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PREVIOUS), PendingIntent.FLAG_UPDATE_CURRENT); + view.setOnClickPendingIntent(R.id.player_previous, pendingIntent); + pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_CLOSE), PendingIntent.FLAG_UPDATE_CURRENT); + view.setOnClickPendingIntent(R.id.player_close, pendingIntent); + pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PAUSE), PendingIntent.FLAG_UPDATE_CURRENT); + view.setOnClickPendingIntent(R.id.player_pause, pendingIntent); + pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_NEXT), PendingIntent.FLAG_UPDATE_CURRENT); + view.setOnClickPendingIntent(R.id.player_next, pendingIntent); + pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent(NOTIFY_PLAY), PendingIntent.FLAG_UPDATE_CURRENT); + view.setOnClickPendingIntent(R.id.player_play, pendingIntent); + } + + @SuppressLint("NewApi") + @Override + public void onDestroy() { + super.onDestroy(); + if (remoteControlClient != null) { + RemoteControlClient.MetadataEditor metadataEditor = remoteControlClient.editMetadata(true); + metadataEditor.clear(); + metadataEditor.apply(); + audioManager.unregisterRemoteControlClient(remoteControlClient); + } + try { + TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); + if (mgr != null) { + mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE); + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioProgressDidChanged); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged); + } + + @Override + public void onAudioFocusChange(int focusChange) { + if (ignoreAudioFocus) { + ignoreAudioFocus = false; + return; + } + if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { + if (MediaController.getInstance().isPlayingAudio(MediaController.getInstance().getPlayingMessageObject()) && !MediaController.getInstance().isAudioPaused()) { + MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); + } + } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { + //MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject()); + } + } + + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.audioPlayStateChanged) { + MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + if (messageObject != null) { + createNotification(messageObject); + } else { + stopSelf(); + } + } + } + + public static void setIgnoreAudioFocus() { + ignoreAudioFocus = true; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java index ffaf321a6..474d0c770 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationCenter.java @@ -64,6 +64,7 @@ public class NotificationCenter { public static final int botInfoDidLoaded = totalEvents++; public static final int botKeyboardDidLoaded = totalEvents++; public static final int chatSearchResultsAvailable = totalEvents++; + public static final int musicDidLoaded = totalEvents++; public static final int httpFileDidLoaded = totalEvents++; public static final int httpFileDidFailedLoad = totalEvents++; @@ -89,6 +90,7 @@ public class NotificationCenter { public static final int audioProgressDidChanged = totalEvents++; public static final int audioDidReset = totalEvents++; + public static final int audioPlayStateChanged = totalEvents++; public static final int recordProgressChanged = totalEvents++; public static final int recordStarted = totalEvents++; public static final int recordStartError = totalEvents++; diff --git a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java index 3283523ab..5983c3855 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/android/NotificationsController.java @@ -31,8 +31,6 @@ import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationManagerCompat; import android.support.v4.app.RemoteInput; -import org.json.JSONArray; -import org.json.JSONObject; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLog; @@ -602,11 +600,8 @@ public class NotificationsController { } String lastMessage = null; - String lastMessageFull = null; if (pushMessages.size() == 1) { - String message = lastMessageFull = getStringForMessage(pushMessages.get(0), false); - //lastMessage = getStringForMessage(pushMessages.get(0), true); - lastMessage = lastMessageFull; + String message = lastMessage = getStringForMessage(pushMessages.get(0), false); if (message == null) { return; } @@ -630,8 +625,7 @@ public class NotificationsController { continue; } if (i == 0) { - lastMessageFull = message; - lastMessage = lastMessageFull; + lastMessage = message; } if (pushDialogs.size() == 1) { if (replace) { @@ -692,9 +686,6 @@ public class NotificationsController { showExtraNotifications(mBuilder, notifyAboutLast); notificationManager.notify(1, mBuilder.build()); - if (preferences.getBoolean("EnablePebbleNotifications", false)) { - sendAlertToPebble(lastMessageFull); - } scheduleNotificationRepeat(); } catch (Exception e) { @@ -897,26 +888,6 @@ public class NotificationsController { } } - private void sendAlertToPebble(String message) { - try { - final Intent i = new Intent("com.getpebble.action.SEND_NOTIFICATION"); - - final HashMap data = new HashMap<>(); - data.put("title", LocaleController.getString("AppName", R.string.AppName)); - data.put("body", message); - final JSONObject jsonData = new JSONObject(data); - final String notificationData = new JSONArray().put(jsonData).toString(); - - i.putExtra("messageType", "PEBBLE_ALERT"); - i.putExtra("sender", LocaleController.formatString("AppName", R.string.AppName)); - i.putExtra("notificationData", notificationData); - - ApplicationLoader.applicationContext.sendBroadcast(i); - } catch (Exception e) { - FileLog.e("tmessages", e); - } - } - public void processReadMessages(HashMap inbox, long dialog_id, int max_date, int max_id, boolean isPopup) { int oldCount = popupMessages.size(); if (inbox != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java index 060d21799..230497db8 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/android/SendMessagesHelper.java @@ -19,6 +19,7 @@ import android.provider.MediaStore; import android.webkit.MimeTypeMap; import android.widget.Toast; +import org.telegram.android.audioinfo.AudioInfo; import org.telegram.messenger.ConnectionsManager; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; @@ -557,6 +558,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter for (int a = 0; a < messages.size(); a++) { MessageObject msgObj = messages.get(a); + if (msgObj.getId() <= 0) { + continue; + } final TLRPC.Message newMsg = new TLRPC.TL_message(); newMsg.flags |= TLRPC.MESSAGE_FLAG_FWD; @@ -1858,6 +1862,7 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter return false; } MimeTypeMap myMime = MimeTypeMap.getSingleton(); + TLRPC.TL_documentAttributeAudio attributeAudio = null; if (uri != null) { String extension = null; if (mime != null) { @@ -1885,8 +1890,31 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter if (idx != -1) { ext = path.substring(idx + 1); } + if (ext.toLowerCase().equals("mp3") || ext.toLowerCase().equals("m4a")) { + AudioInfo audioInfo = AudioInfo.getAudioInfo(f); + if (audioInfo != null && audioInfo.getDuration() != 0) { + if (isEncrypted) { + attributeAudio = new TLRPC.TL_documentAttributeAudio_old(); + } else { + attributeAudio = new TLRPC.TL_documentAttributeAudio(); + } + attributeAudio.duration = (int) (audioInfo.getDuration() / 1000); + attributeAudio.title = audioInfo.getTitle(); + attributeAudio.performer = audioInfo.getArtist(); + if (attributeAudio.title == null) { + attributeAudio.title = ""; + } + if (attributeAudio.performer == null) { + attributeAudio.performer = ""; + } + } + } if (originalPath != null) { - originalPath += "" + f.length(); + if (attributeAudio != null) { + originalPath += "audio" + f.length(); + } else { + originalPath += "" + f.length(); + } } TLRPC.TL_document document = null; @@ -1905,6 +1933,9 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter document.attributes.add(fileName); document.size = (int) f.length(); document.dc_id = 0; + if (attributeAudio != null) { + document.attributes.add(attributeAudio); + } if (ext.length() != 0) { if (ext.toLowerCase().equals("webp")) { document.mime_type = "image/webp"; @@ -1990,6 +2021,56 @@ public class SendMessagesHelper implements NotificationCenter.NotificationCenter prepareSendingDocuments(paths, originalPaths, uris, mine, dialog_id, reply_to_msg); } + public static void prepareSendingAudioDocuments(final ArrayList messageObjects, final long dialog_id, final MessageObject reply_to_msg) { + new Thread(new Runnable() { + @Override + public void run() { + int size = messageObjects.size(); + for (int a = 0; a < size; a++) { + final MessageObject messageObject = messageObjects.get(a); + String originalPath = messageObject.messageOwner.attachPath; + final File f = new File(originalPath); + + boolean isEncrypted = (int) dialog_id == 0; + + + if (originalPath != null) { + originalPath += "audio" + f.length(); + } + + TLRPC.TL_document document = null; + if (!isEncrypted) { + document = (TLRPC.TL_document) MessagesStorage.getInstance().getSentFile(originalPath, !isEncrypted ? 1 : 4); + } + if (document == null) { + document = (TLRPC.TL_document) messageObject.messageOwner.media.document; + } + + if (isEncrypted) { + for (int b = 0; b < document.attributes.size(); b++) { + if (document.attributes.get(b) instanceof TLRPC.TL_documentAttributeAudio) { + TLRPC.TL_documentAttributeAudio_old old = new TLRPC.TL_documentAttributeAudio_old(); + old.duration = document.attributes.get(b).duration; + document.attributes.remove(b); + document.attributes.add(old); + break; + } + } + } + + final String originalPathFinal = originalPath; + final TLRPC.TL_document documentFinal = document; + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + SendMessagesHelper.getInstance().sendMessage(documentFinal, originalPathFinal, messageObject.messageOwner.attachPath, dialog_id, reply_to_msg); + } + }); + } + } + }).start(); + } + 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; diff --git a/TMessagesProj/src/main/java/org/telegram/android/UserObject.java b/TMessagesProj/src/main/java/org/telegram/android/UserObject.java index 1fe80d039..7a0ad4ff7 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/UserObject.java +++ b/TMessagesProj/src/main/java/org/telegram/android/UserObject.java @@ -8,6 +8,7 @@ package org.telegram.android; +import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; @@ -29,7 +30,8 @@ public class UserObject { if (user == null || isDeleted(user)) { return LocaleController.getString("HiddenName", R.string.HiddenName); } - return ContactsController.formatName(user.first_name, user.last_name); + String name = ContactsController.formatName(user.first_name, user.last_name); + return name.length() != 0 || user.phone == null || user.phone.length() == 0 ? name : PhoneFormat.getInstance().format("+" + user.phone); } public static String getFirstName(TLRPC.User user) { @@ -40,6 +42,6 @@ public class UserObject { if (name == null || name.length() == 0) { name = user.last_name; } - return name != null && name.length() > 0 ? name : "DELETED"; + return name != null && name.length() > 0 ? name : LocaleController.getString("HiddenName", R.string.HiddenName); } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/AudioInfo.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/AudioInfo.java new file mode 100755 index 000000000..19e16415f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/AudioInfo.java @@ -0,0 +1,154 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo; + +import android.graphics.Bitmap; + +import org.telegram.android.audioinfo.m4a.M4AInfo; +import org.telegram.android.audioinfo.mp3.MP3Info; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.RandomAccessFile; + +public abstract class AudioInfo { + protected String brand; // brand, e.g. "M4A", "ID3", ... + protected String version; // version, e.g. "0", "2.3.0", ... + + protected long duration; // track duration (milliseconds) + + protected String title; // track title + protected String artist; // track artist + protected String albumArtist; // album artist + protected String album; // album title + protected short year; // year... + protected String genre; // genre name + protected String comment; // comment... + protected short track; // track number + protected short tracks; // number of tracks + protected short disc; // disc number + protected short discs; // number of discs + protected String copyright; // copyright notice + protected String composer; // composer name + protected String grouping; // track grouping + protected boolean compilation; // compilation flag + protected String lyrics; // song lyrics + protected Bitmap cover; // cover image data + protected Bitmap smallCover; // cover image data + + public String getBrand() { + return brand; + } + + public String getVersion() { + return version; + } + + public long getDuration() { + return duration; + } + + public String getTitle() { + return title; + } + + public String getArtist() { + return artist; + } + + public String getAlbumArtist() { + return albumArtist; + } + + public String getAlbum() { + return album; + } + + public short getYear() { + return year; + } + + public String getGenre() { + return genre; + } + + public String getComment() { + return comment; + } + + public short getTrack() { + return track; + } + + public short getTracks() { + return tracks; + } + + public short getDisc() { + return disc; + } + + public short getDiscs() { + return discs; + } + + public String getCopyright() { + return copyright; + } + + public String getComposer() { + return composer; + } + + public String getGrouping() { + return grouping; + } + + public boolean isCompilation() { + return compilation; + } + + public String getLyrics() { + return lyrics; + } + + public Bitmap getCover() { + return cover; + } + + public Bitmap getSmallCover() { + return smallCover; + } + + public static AudioInfo getAudioInfo(File file) { + try { + byte header[] = new byte[12]; + RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r"); + randomAccessFile.readFully(header, 0, 8); + randomAccessFile.close(); + InputStream input = new BufferedInputStream(new FileInputStream(file)); + if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') { + return new M4AInfo(input); + } else { + return new MP3Info(input, file.length()); + } + } catch (Exception e) { + return null; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/M4AInfo.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/M4AInfo.java new file mode 100755 index 000000000..82d3f6458 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/M4AInfo.java @@ -0,0 +1,325 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.m4a; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import org.telegram.android.audioinfo.AudioInfo; +import org.telegram.android.audioinfo.mp3.ID3v1Genre; + +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class M4AInfo extends AudioInfo { + static final Logger LOGGER = Logger.getLogger(M4AInfo.class.getName()); + + private static final String ASCII = "ISO8859_1"; + private static final String UTF_8 = "UTF-8"; + + private BigDecimal volume; // normal = 1.0 + private BigDecimal speed; // normal = 1.0 + + private short tempo; + private byte rating; // none = 0, clean = 2, explicit = 4 + + private final Level debugLevel; + + public M4AInfo(InputStream input) throws IOException { + this(input, Level.FINEST); + } + + public M4AInfo(InputStream input, Level debugLevel) throws IOException { + this.debugLevel = debugLevel; + MP4Input mp4 = new MP4Input(input); + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, mp4.toString()); + } + ftyp(mp4.nextChild("ftyp")); + moov(mp4.nextChildUpTo("moov")); + } + + void ftyp(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + brand = atom.readString(4, ASCII).trim(); + if (brand.matches("M4V|MP4|mp42|isom")) { // experimental file types + LOGGER.warning(atom.getPath() + ": brand=" + brand + " (experimental)"); + } else if (!brand.matches("M4A|M4P")) { + LOGGER.warning(atom.getPath() + ": brand=" + brand + " (expected M4A or M4P)"); + } + version = String.valueOf(atom.readInt()); + } + + void moov(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + while (atom.hasMoreChildren()) { + MP4Atom child = atom.nextChild(); + switch (child.getType()) { + case "mvhd": + mvhd(child); + break; + case "trak": + trak(child); + break; + case "udta": + udta(child); + break; + default: + break; + } + } + } + + void mvhd(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + byte version = atom.readByte(); + atom.skip(3); // flags + atom.skip(version == 1 ? 16 : 8); // created/modified date + int scale = atom.readInt(); + long units = version == 1 ? atom.readLong() : atom.readInt(); + if (duration == 0) { + duration = 1000 * units / scale; + } else if (LOGGER.isLoggable(debugLevel) && Math.abs(duration - 1000 * units / scale) > 2) { + LOGGER.log(debugLevel, "mvhd: duration " + duration + " -> " + (1000 * units / scale)); + } + speed = atom.readIntegerFixedPoint(); + volume = atom.readShortFixedPoint(); + } + + void trak(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + mdia(atom.nextChildUpTo("mdia")); + } + + void mdia(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + mdhd(atom.nextChild("mdhd")); + } + + void mdhd(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + byte version = atom.readByte(); + atom.skip(3); + atom.skip(version == 1 ? 16 : 8); // created/modified date + int sampleRate = atom.readInt(); + long samples = version == 1 ? atom.readLong() : atom.readInt(); + if (duration == 0) { + duration = 1000 * samples / sampleRate; + } else if (LOGGER.isLoggable(debugLevel) && Math.abs(duration - 1000 * samples / sampleRate) > 2) { + LOGGER.log(debugLevel, "mdhd: duration " + duration + " -> " + (1000 * samples / sampleRate)); + } + } + + void udta(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + while (atom.hasMoreChildren()) { + MP4Atom child = atom.nextChild(); + if ("meta".equals(child.getType())) { + meta(child); + break; + } + } + } + + void meta(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + atom.skip(4); // version/flags + while (atom.hasMoreChildren()) { + MP4Atom child = atom.nextChild(); + if ("ilst".equals(child.getType())) { + ilst(child); + break; + } + } + } + + void ilst(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + while (atom.hasMoreChildren()) { + MP4Atom child = atom.nextChild(); + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, child.toString()); + } + if (child.getRemaining() == 0) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, child.getPath() + ": contains no value"); + } + continue; + } + data(child.nextChildUpTo("data")); + } + } + + void data(MP4Atom atom) throws IOException { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, atom.toString()); + } + atom.skip(4); // version & flags + atom.skip(4); // reserved + switch (atom.getParent().getType()) { + case "©alb": + album = atom.readString(UTF_8); + break; + case "aART": + albumArtist = atom.readString(UTF_8); + break; + case "©ART": + artist = atom.readString(UTF_8); + break; + case "©cmt": + comment = atom.readString(UTF_8); + break; + case "©com": + case "©wrt": + if (composer == null || composer.trim().length() == 0) { + composer = atom.readString(UTF_8); + } + break; + case "covr": + try { + byte[] bytes = atom.readBytes(); + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inJustDecodeBounds = true; + opts.inSampleSize = 1; + BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts); + if (opts.outWidth > 800 || opts.outHeight > 800) { + int size = Math.max(opts.outWidth, opts.outHeight); + while (size > 800) { + opts.inSampleSize *= 2; + size /= 2; + } + } + opts.inJustDecodeBounds = false; + cover = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts); + if (cover != null) { + float scale = Math.max(cover.getWidth(), cover.getHeight()) / 120.0f; + if (scale > 0) { + smallCover = Bitmap.createScaledBitmap(cover, (int) (cover.getWidth() / scale), (int) (cover.getHeight() / scale), true); + } else { + smallCover = cover; + } + if (smallCover == null) { + smallCover = cover; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + break; + case "cpil": + compilation = atom.readBoolean(); + break; + case "cprt": + case "©cpy": + if (copyright == null || copyright.trim().length() == 0) { + copyright = atom.readString(UTF_8); + } + break; + case "©day": + String day = atom.readString(UTF_8).trim(); + if (day.length() >= 4) { + try { + year = Short.valueOf(day.substring(0, 4)); + } catch (NumberFormatException e) { + // ignore + } + } + break; + case "disk": + atom.skip(2); // padding? + disc = atom.readShort(); + discs = atom.readShort(); + break; + case "gnre": + if (genre == null || genre.trim().length() == 0) { + if (atom.getRemaining() == 2) { // id3v1 genre? + int index = atom.readShort() - 1; + ID3v1Genre id3v1Genre = ID3v1Genre.getGenre(index); + if (id3v1Genre != null) { + genre = id3v1Genre.getDescription(); + } + } else { + genre = atom.readString(UTF_8); + } + } + break; + case "©gen": + if (genre == null || genre.trim().length() == 0) { + genre = atom.readString(UTF_8); + } + break; + case "©grp": + grouping = atom.readString(UTF_8); + break; + case "©lyr": + lyrics = atom.readString(UTF_8); + break; + case "©nam": + title = atom.readString(UTF_8); + break; + case "rtng": + rating = atom.readByte(); + break; + case "tmpo": + tempo = atom.readShort(); + break; + case "trkn": + atom.skip(2); // padding? + track = atom.readShort(); + tracks = atom.readShort(); + break; + default: + break; + } + } + + public short getTempo() { + return tempo; + } + + public byte getRating() { + return rating; + } + + public BigDecimal getSpeed() { + return speed; + } + + public BigDecimal getVolume() { + return volume; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Atom.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Atom.java new file mode 100755 index 000000000..7b99fe812 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Atom.java @@ -0,0 +1,151 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.m4a; + +import org.telegram.android.audioinfo.util.RangeInputStream; + +import java.io.EOFException; +import java.io.IOException; +import java.math.BigDecimal; + +public class MP4Atom extends MP4Box { + public MP4Atom(RangeInputStream input, MP4Box parent, String type) { + super(input, parent, type); + } + + public long getLength() { + return getInput().getPosition() + getInput().getRemainingLength(); + } + + public long getOffset() { + return getParent().getPosition() - getPosition(); + } + + public long getRemaining() { + return getInput().getRemainingLength(); + } + + public boolean hasMoreChildren() { + return (getChild() != null ? getChild().getRemaining() : 0) < getRemaining(); + } + + public MP4Atom nextChildUpTo(String expectedTypeExpression) throws IOException { + while (getRemaining() > 0) { + MP4Atom atom = nextChild(); + if (atom.getType().matches(expectedTypeExpression)) { + return atom; + } + } + throw new IOException("atom type mismatch, not found: " + expectedTypeExpression); + } + + public boolean readBoolean() throws IOException { + return data.readBoolean(); + } + + public byte readByte() throws IOException { + return data.readByte(); + } + + public short readShort() throws IOException { + return data.readShort(); + } + + public int readInt() throws IOException { + return data.readInt(); + } + + public long readLong() throws IOException { + return data.readLong(); + } + + public byte[] readBytes(int len) throws IOException { + byte[] bytes = new byte[len]; + data.readFully(bytes); + return bytes; + } + + public byte[] readBytes() throws IOException { + return readBytes((int) getRemaining()); + } + + public BigDecimal readShortFixedPoint() throws IOException { + int integer = data.readByte(); + int decimal = data.readUnsignedByte(); + return new BigDecimal(String.valueOf(integer) + "" + String.valueOf(decimal)); + } + + public BigDecimal readIntegerFixedPoint() throws IOException { + int integer = data.readShort(); + int decimal = data.readUnsignedShort(); + return new BigDecimal(String.valueOf(integer) + "" + String.valueOf(decimal)); + } + + public String readString(int len, String enc) throws IOException { + String s = new String(readBytes(len), enc); + int end = s.indexOf(0); + return end < 0 ? s : s.substring(0, end); + } + + public String readString(String enc) throws IOException { + return readString((int) getRemaining(), enc); + } + + public void skip(int len) throws IOException { + int total = 0; + while (total < len) { + int current = data.skipBytes(len - total); + if (current > 0) { + total += current; + } else { + throw new EOFException(); + } + } + } + + public void skip() throws IOException { + while (getRemaining() > 0) { + if (getInput().skip(getRemaining()) == 0) { + throw new EOFException("Cannot skip atom"); + } + } + } + + private StringBuffer appendPath(StringBuffer s, MP4Box box) { + if (box.getParent() != null) { + appendPath(s, box.getParent()); + s.append("/"); + } + return s.append(box.getType()); + } + + public String getPath() { + return appendPath(new StringBuffer(), this).toString(); + } + + public String toString() { + StringBuffer s = new StringBuffer(); + appendPath(s, this); + s.append("[off="); + s.append(getOffset()); + s.append(",pos="); + s.append(getPosition()); + s.append(",len="); + s.append(getLength()); + s.append("]"); + return s.toString(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Box.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Box.java new file mode 100755 index 000000000..66e8050d8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Box.java @@ -0,0 +1,87 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.m4a; + +import org.telegram.android.audioinfo.util.PositionInputStream; +import org.telegram.android.audioinfo.util.RangeInputStream; + +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; + +public class MP4Box { + protected static final String ASCII = "ISO8859_1"; + + private final I input; + private final MP4Box parent; + private final String type; + + protected final DataInput data; + + private MP4Atom child; + + public MP4Box(I input, MP4Box parent, String type) { + this.input = input; + this.parent = parent; + this.type = type; + this.data = new DataInputStream(input); + } + + public String getType() { + return type; + } + + public MP4Box getParent() { + return parent; + } + + public long getPosition() { + return input.getPosition(); + } + + public I getInput() { + return input; + } + + protected MP4Atom getChild() { + return child; + } + + public MP4Atom nextChild() throws IOException { + if (child != null) { + child.skip(); + } + int atomLength = data.readInt(); + byte[] typeBytes = new byte[4]; + data.readFully(typeBytes); + String atomType = new String(typeBytes, ASCII); + RangeInputStream atomInput; + if (atomLength == 1) { // extended length + atomInput = new RangeInputStream(input, 16, data.readLong() - 16); + } else { + atomInput = new RangeInputStream(input, 8, atomLength - 8); + } + return child = new MP4Atom(atomInput, this, atomType); + } + + public MP4Atom nextChild(String expectedTypeExpression) throws IOException { + MP4Atom atom = nextChild(); + if (atom.getType().matches(expectedTypeExpression)) { + return atom; + } + throw new IOException("atom type mismatch, expected " + expectedTypeExpression + ", got " + atom.getType()); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Input.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Input.java new file mode 100755 index 000000000..caacb2510 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/m4a/MP4Input.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.m4a; + +import org.telegram.android.audioinfo.util.PositionInputStream; + +import java.io.IOException; +import java.io.InputStream; + +public final class MP4Input extends MP4Box { + + public MP4Input(InputStream delegate) { + super(new PositionInputStream(delegate), null, ""); + } + + public MP4Atom nextChildUpTo(String expectedTypeExpression) throws IOException { + while (true) { + MP4Atom atom = nextChild(); + if (atom.getType().matches(expectedTypeExpression)) { + return atom; + } + } + } + + public String toString() { + return "mp4[pos=" + getPosition() + "]"; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v1Genre.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v1Genre.java new file mode 100755 index 000000000..c43a85e62 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v1Genre.java @@ -0,0 +1,171 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +public enum ID3v1Genre { + /* + * The following genres is defined in ID3v1 (0-79) + */ + Blues("Blues"), + ClassicRock("Classic Rock"), + Country("Country"), + Dance("Dance"), + Disco("Disco"), + Funk("Funk"), + Grunge("Grunge"), + HipHop("Hip-Hop"), + Jazz("Jazz"), + Metal("Metal"), + NewAge("New Age"), + Oldies("Oldies"), + Other("Other"), + Pop("Pop"), + RnB("R&B"), + Rap("Rap"), + Reggae("Reggae"), + Rock("Rock"), + Techno("Techno"), + Industrial("Industrial"), + Alternative("Alternative"), + Ska("Ska"), + DeathMetal("Death Metal"), + Pranks("Pranks"), + Soundtrack("Soundtrack"), + EuroTechno("Euro-Techno"), + Ambient("Ambient"), + TripHop("Trip-Hop"), + Vocal("Vocal"), + JazzFunk("Jazz+Funk"), + Fusion("Fusion"), + Trance("Trance"), + Classical("Classical"), + Instrumental("Instrumental"), + Acid("Acid"), + House("House"), + Game("Game"), + SoundClip("Sound Clip"), + Gospel("Gospel"), + Noise("Noise"), + AlternRock("AlternRock"), + Bass("Bass"), + Soul("Soul"), + Punk("Punk"), + Space("Space"), + Meditative("Meditative"), + InstrumentalPop("Instrumental Pop"), + InstrumentalRock("Instrumental Rock"), + Ethnic("Ethnic"), + Gothic("Gothic"), + Darkwave("Darkwave"), + TechnoIndustrial("Techno-Industrial"), + Electronic("Electronic"), + PopFolk("Pop-Folk"), + Eurodance("Eurodance"), + Dream("Dream"), + SouthernRock("Southern Rock"), + Comedy("Comedy"), + Cult("Cult"), + Gangsta("Gangsta"), + Top40("Top 40"), + ChristianRap("Christian Rap"), + PopFunk("Pop/Funk"), + Jungle("Jungle"), + NativeAmerican("Native American"), + Cabaret("Cabaret"), + NewWave("New Wave"), + Psychadelic("Psychadelic"), + Rave("Rave"), + Showtunes("Showtunes"), + Trailer("Trailer"), + LoFi("Lo-Fi"), + Tribal("Tribal"), + AcidPunk("Acid Punk"), + AcidJazz("Acid Jazz"), + Polka("Polka"), + Retro("Retro"), + Musical("Musical"), + RockAndRoll("Rock & Roll"), + HardRock("Hard Rock"), + + /* + * The following genres are Winamp extensions (80-125) + */ + Folk("Folk"), + FolkRock("Folk-Rock"), + NationalFolk("National Folk"), + Swing("Swing"), + FastFusion("Fast Fusion"), + Bebop("Bebop"), + Latin("Latin"), + Revival("Revival"), + Celtic("Celtic"), + Bluegrass("Bluegrass"), + Avantgarde("Avantgarde"), + GothicRock("Gothic Rock"), + ProgressiveRock("Progressive Rock"), + PsychedelicRock("Psychedelic Rock"), + SymphonicRock("Symphonic Rock"), + SlowRock("Slow Rock"), + BigBand("Big Band"), + Chorus("Chorus"), + EasyListening("Easy Listening"), + Acoustic("Acoustic"), + Humour("Humour"), + Speech("Speech"), + Chanson("Chanson"), + Opera("Opera"), + ChamberMusic("Chamber Music"), + Sonata("Sonata"), + Symphony("Symphony"), + BootyBass("Booty Bass"), + Primus("Primus"), + PornGroove("Porn Groove"), + Satire("Satire"), + SlowJam("Slow Jam"), + Club("Club"), + Tango("Tango"), + Samba("Samba"), + Folklore("Folklore"), + Ballad("Ballad"), + PowerBallad("Power Ballad"), + RhytmicSoul("Rhythmic Soul"), + Freestyle("Freestyle"), + Duet("Duet"), + PunkRock("Punk Rock"), + DrumSolo("Drum Solo"), + ACapella("A capella"), + EuroHouse("Euro-House"), + DanceHall("Dance Hall"); + + public static ID3v1Genre getGenre(int id) { + ID3v1Genre[] values = values(); + return id >= 0 && id < values.length ? values[id] : null; + } + + private final String description; + + ID3v1Genre(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + public int getId() { + return ordinal(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v1Info.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v1Info.java new file mode 100755 index 000000000..1ca33999a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v1Info.java @@ -0,0 +1,86 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import org.telegram.android.audioinfo.AudioInfo; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +public class ID3v1Info extends AudioInfo { + public static boolean isID3v1StartPosition(InputStream input) throws IOException { + input.mark(3); + try { + return input.read() == 'T' && input.read() == 'A' && input.read() == 'G'; + } finally { + input.reset(); + } + } + + public ID3v1Info(InputStream input) throws IOException { + if (isID3v1StartPosition(input)) { + brand = "ID3"; + version = "1.0"; + byte[] bytes = readBytes(input, 128); + title = extractString(bytes, 3, 30); + artist = extractString(bytes, 33, 30); + album = extractString(bytes, 63, 30); + try { + year = Short.parseShort(extractString(bytes, 93, 4)); + } catch (NumberFormatException e) { + year = 0; + } + comment = extractString(bytes, 97, 30); + ID3v1Genre id3v1Genre = ID3v1Genre.getGenre(bytes[127]); + if (id3v1Genre != null) { + genre = id3v1Genre.getDescription(); + } + + /* + * ID3v1.1 + */ + if (bytes[125] == 0 && bytes[126] != 0) { + version = "1.1"; + track = (short) (bytes[126] & 0xFF); + } + } + } + + byte[] readBytes(InputStream input, int len) throws IOException { + int total = 0; + byte[] bytes = new byte[len]; + while (total < len) { + int current = input.read(bytes, total, len - total); + if (current > 0) { + total += current; + } else { + throw new EOFException(); + } + } + return bytes; + } + + String extractString(byte[] bytes, int offset, int length) { + try { + String text = new String(bytes, offset, length, "ISO-8859-1"); + int zeroIndex = text.indexOf(0); + return zeroIndex < 0 ? text : text.substring(0, zeroIndex); + } catch (Exception e) { + return ""; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2DataInput.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2DataInput.java new file mode 100755 index 000000000..2a4ba062e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2DataInput.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +public class ID3v2DataInput { + private final InputStream input; + + public ID3v2DataInput(InputStream in) { + this.input = in; + } + + public final void readFully(byte b[], int off, int len) throws IOException { + int total = 0; + while (total < len) { + int current = input.read(b, off + total, len - total); + if (current > 0) { + total += current; + } else { + throw new EOFException(); + } + } + } + + public byte[] readFully(int len) throws IOException { + byte[] bytes = new byte[len]; + readFully(bytes, 0, len); + return bytes; + } + + public void skipFully(long len) throws IOException { + long total = 0; + while (total < len) { + long current = input.skip(len - total); + if (current > 0) { + total += current; + } else { + throw new EOFException(); + } + } + } + + public byte readByte() throws IOException { + int b = input.read(); + if (b < 0) { + throw new EOFException(); + } + return (byte) b; + } + + public int readInt() throws IOException { + return ((readByte() & 0xFF) << 24) | ((readByte() & 0xFF) << 16) | ((readByte() & 0xFF) << 8) | (readByte() & 0xFF); + } + + public int readSyncsafeInt() throws IOException { + return ((readByte() & 0x7F) << 21) | ((readByte() & 0x7F) << 14) | ((readByte() & 0x7F) << 7) | (readByte() & 0x7F); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Encoding.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Encoding.java new file mode 100755 index 000000000..4d9d5c696 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Encoding.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import java.nio.charset.Charset; + +public enum ID3v2Encoding { + ISO_8859_1(Charset.forName("ISO-8859-1"), 1), + UTF_16(Charset.forName("UTF-16"), 2), + UTF_16BE(Charset.forName("UTF-16BE"), 2), + UTF_8(Charset.forName("UTF-8"), 1); + + private final Charset charset; + private final int zeroBytes; + + ID3v2Encoding(Charset charset, int zeroBytes) { + this.charset = charset; + this.zeroBytes = zeroBytes; + } + + public Charset getCharset() { + return charset; + } + + public int getZeroBytes() { + return zeroBytes; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Exception.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Exception.java new file mode 100755 index 000000000..1321f1477 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Exception.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +public class ID3v2Exception extends Exception { + private static final long serialVersionUID = 1L; + + public ID3v2Exception(String message) { + super(message); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2FrameBody.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2FrameBody.java new file mode 100755 index 000000000..c1187911f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2FrameBody.java @@ -0,0 +1,155 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import org.telegram.android.audioinfo.util.RangeInputStream; + +import java.io.IOException; +import java.io.InputStream; + +public class ID3v2FrameBody { + + static final class Buffer { + byte[] bytes; + + Buffer(int initialLength) { + bytes = new byte[initialLength]; + } + + byte[] bytes(int minLength) { + if (minLength > bytes.length) { + int length = bytes.length * 2; + while (minLength > length) { + length *= 2; + } + bytes = new byte[length]; + } + return bytes; + } + } + + static final ThreadLocal textBuffer = new ThreadLocal() { + @Override + protected Buffer initialValue() { + return new Buffer(4096); + } + }; + + private final RangeInputStream input; + private final ID3v2TagHeader tagHeader; + private final ID3v2FrameHeader frameHeader; + private final ID3v2DataInput data; + + ID3v2FrameBody(InputStream delegate, long position, int dataLength, ID3v2TagHeader tagHeader, ID3v2FrameHeader frameHeader) throws IOException { + this.input = new RangeInputStream(delegate, position, dataLength); + this.data = new ID3v2DataInput(input); + this.tagHeader = tagHeader; + this.frameHeader = frameHeader; + } + + public ID3v2DataInput getData() { + return data; + } + + public long getPosition() { + return input.getPosition(); + } + + public long getRemainingLength() { + return input.getRemainingLength(); + } + + public ID3v2TagHeader getTagHeader() { + return tagHeader; + } + + public ID3v2FrameHeader getFrameHeader() { + return frameHeader; + } + + private String extractString(byte[] bytes, int offset, int length, ID3v2Encoding encoding, boolean searchZeros) { + if (searchZeros) { + int zeros = 0; + for (int i = 0; i < length; i++) { + // UTF-16LE may have a zero byte as second byte of a 2-byte character -> skip first zero at odd index + if (bytes[offset + i] == 0 && (encoding != ID3v2Encoding.UTF_16 || zeros != 0 || (offset + i) % 2 == 0)) { + if (++zeros == encoding.getZeroBytes()) { + length = i + 1 - encoding.getZeroBytes(); + break; + } + } else { + zeros = 0; + } + } + } + try { + String string = new String(bytes, offset, length, encoding.getCharset().name()); + if (string.length() > 0 && string.charAt(0) == '\uFEFF') { // remove BOM + string = string.substring(1); + } + return string; + } catch (Exception e) { + return ""; + } + } + + public String readZeroTerminatedString(int maxLength, ID3v2Encoding encoding) throws IOException, ID3v2Exception { + int zeros = 0; + int length = Math.min(maxLength, (int) getRemainingLength()); + byte[] bytes = textBuffer.get().bytes(length); + for (int i = 0; i < length; i++) { + // UTF-16LE may have a zero byte as second byte of a 2-byte character -> skip first zero at odd index + if ((bytes[i] = data.readByte()) == 0 && (encoding != ID3v2Encoding.UTF_16 || zeros != 0 || i % 2 == 0)) { + if (++zeros == encoding.getZeroBytes()) { + return extractString(bytes, 0, i + 1 - encoding.getZeroBytes(), encoding, false); + } + } else { + zeros = 0; + } + } + throw new ID3v2Exception("Could not read zero-termiated string"); + } + + public String readFixedLengthString(int length, ID3v2Encoding encoding) throws IOException, ID3v2Exception { + if (length > getRemainingLength()) { + throw new ID3v2Exception("Could not read fixed-length string of length: " + length); + } + byte[] bytes = textBuffer.get().bytes(length); + data.readFully(bytes, 0, length); + return extractString(bytes, 0, length, encoding, true); + } + + public ID3v2Encoding readEncoding() throws IOException, ID3v2Exception { + byte value = data.readByte(); + switch (value) { + case 0: + return ID3v2Encoding.ISO_8859_1; + case 1: + return ID3v2Encoding.UTF_16; + case 2: + return ID3v2Encoding.UTF_16BE; + case 3: + return ID3v2Encoding.UTF_8; + default: + break; + } + throw new ID3v2Exception("Invalid encoding: " + value); + } + + public String toString() { + return "id3v2frame[pos=" + getPosition() + ", " + getRemainingLength() + " left]"; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2FrameHeader.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2FrameHeader.java new file mode 100755 index 000000000..7d25ff403 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2FrameHeader.java @@ -0,0 +1,165 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import java.io.IOException; + +public class ID3v2FrameHeader { + private String frameId; + private int headerSize; + private int bodySize; + private boolean unsynchronization; + private boolean compression; + private boolean encryption; + private int dataLengthIndicator; + + public ID3v2FrameHeader(ID3v2TagBody input) throws IOException, ID3v2Exception { + long startPosition = input.getPosition(); + + ID3v2DataInput data = input.getData(); + + /* + * Frame Id + */ + if (input.getTagHeader().getVersion() == 2) { // $xx xx xx (three characters) + frameId = new String(data.readFully(3), "ISO-8859-1"); + } else { // $xx xx xx xx (four characters) + frameId = new String(data.readFully(4), "ISO-8859-1"); + } + + /* + * Size + */ + if (input.getTagHeader().getVersion() == 2) { // $xx xx xx + bodySize = ((data.readByte() & 0xFF) << 16) | ((data.readByte() & 0xFF) << 8) | (data.readByte() & 0xFF); + } else if (input.getTagHeader().getVersion() == 3) { // $xx xx xx xx + bodySize = data.readInt(); + } else { // 4 * %0xxxxxxx (sync-save integer) + bodySize = data.readSyncsafeInt(); + } + + /* + * Flags + */ + if (input.getTagHeader().getVersion() > 2) { // $xx xx + data.readByte(); // status flags + byte formatFlags = data.readByte(); + int compressionMask; + int encryptionMask; + int groupingIdentityMask; + int unsynchronizationMask = 0x00; + int dataLengthIndicatorMask = 0x00; + if (input.getTagHeader().getVersion() == 3) { // %(compression)(encryption)(groupingIdentity)00000 + compressionMask = 0x80; + encryptionMask = 0x40; + groupingIdentityMask = 0x20; + } else { // %0(groupingIdentity)00(compression)(encryption)(unsynchronization)(dataLengthIndicator) + groupingIdentityMask = 0x40; + compressionMask = 0x08; + encryptionMask = 0x04; + unsynchronizationMask = 0x02; + dataLengthIndicatorMask = 0x01; + } + compression = (formatFlags & compressionMask) != 0; + unsynchronization = (formatFlags & unsynchronizationMask) != 0; + encryption = (formatFlags & encryptionMask) != 0; + + /* + * Read flag attachments in the order of the flags (version dependent). + */ + if (input.getTagHeader().getVersion() == 3) { + if (compression) { + dataLengthIndicator = data.readInt(); + bodySize -= 4; + } + if (encryption) { + data.readByte(); // just skip + bodySize -= 1; + } + if ((formatFlags & groupingIdentityMask) != 0) { + data.readByte(); // just skip + bodySize -= 1; + } + } else { + if ((formatFlags & groupingIdentityMask) != 0) { + data.readByte(); // just skip + bodySize -= 1; + } + if (encryption) { + data.readByte(); // just skip + bodySize -= 1; + } + if ((formatFlags & dataLengthIndicatorMask) != 0) { + dataLengthIndicator = data.readSyncsafeInt(); + bodySize -= 4; + } + } + } + + headerSize = (int) (input.getPosition() - startPosition); + } + + public String getFrameId() { + return frameId; + } + + public int getHeaderSize() { + return headerSize; + } + + public int getBodySize() { + return bodySize; + } + + public boolean isCompression() { + return compression; + } + + public boolean isEncryption() { + return encryption; + } + + public boolean isUnsynchronization() { + return unsynchronization; + } + + public int getDataLengthIndicator() { + return dataLengthIndicator; + } + + public boolean isValid() { + for (int i = 0; i < frameId.length(); i++) { + if ((frameId.charAt(i) < 'A' || frameId.charAt(i) > 'Z') && (frameId.charAt(i) < '0' || frameId.charAt(i) > '9')) { + return false; + } + } + return bodySize > 0; + } + + public boolean isPadding() { + for (int i = 0; i < frameId.length(); i++) { + if (frameId.charAt(0) != 0) { + return false; + } + } + return bodySize == 0; + } + + @Override + public String toString() { + return String.format("%s[id=%s, bodysize=%d]", getClass().getSimpleName(), frameId, bodySize); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Info.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Info.java new file mode 100755 index 000000000..a7490e1ac --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2Info.java @@ -0,0 +1,376 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +import org.telegram.android.audioinfo.AudioInfo; + +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class ID3v2Info extends AudioInfo { + static final Logger LOGGER = Logger.getLogger(ID3v2Info.class.getName()); + + static class AttachedPicture { + static final byte TYPE_OTHER = 0x00; + static final byte TYPE_COVER_FRONT = 0x03; + + final byte type; + final String description; + final String imageType; + final byte[] imageData; + + public AttachedPicture(byte type, String description, String imageType, byte[] imageData) { + this.type = type; + this.description = description; + this.imageType = imageType; + this.imageData = imageData; + } + } + + static class CommentOrUnsynchronizedLyrics { + final String language; + final String description; + final String text; + + public CommentOrUnsynchronizedLyrics(String language, String description, String text) { + this.language = language; + this.description = description; + this.text = text; + } + } + + public static boolean isID3v2StartPosition(InputStream input) throws IOException { + input.mark(3); + try { + return input.read() == 'I' && input.read() == 'D' && input.read() == '3'; + } finally { + input.reset(); + } + } + + private final Level debugLevel; + + private byte coverPictureType; + + public ID3v2Info(InputStream input) throws IOException, ID3v2Exception { + this(input, Level.FINEST); + } + + public ID3v2Info(InputStream input, Level debugLevel) throws IOException, ID3v2Exception { + this.debugLevel = debugLevel; + if (isID3v2StartPosition(input)) { + ID3v2TagHeader tagHeader = new ID3v2TagHeader(input); + brand = "ID3"; + version = String.format("2.%d.%d", tagHeader.getVersion(), tagHeader.getRevision()); + ID3v2TagBody tagBody = tagHeader.tagBody(input); + try { + while (tagBody.getRemainingLength() > 10) { // TODO > tag.minimumFrameSize() + ID3v2FrameHeader frameHeader = new ID3v2FrameHeader(tagBody); + if (frameHeader.isPadding()) { // we ran into padding + break; + } + if (frameHeader.getBodySize() > tagBody.getRemainingLength()) { // something wrong... + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "ID3 frame claims to extend frames area"); + } + break; + } + if (frameHeader.isValid() && !frameHeader.isEncryption()) { + ID3v2FrameBody frameBody = tagBody.frameBody(frameHeader); + try { + parseFrame(frameBody); + } catch (ID3v2Exception e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, String.format("ID3 exception occured in frame %s: %s", frameHeader.getFrameId(), e.getMessage())); + } + } finally { + frameBody.getData().skipFully(frameBody.getRemainingLength()); + } + } else { + tagBody.getData().skipFully(frameHeader.getBodySize()); + } + } + } catch (ID3v2Exception e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "ID3 exception occured: " + e.getMessage()); + } + } + tagBody.getData().skipFully(tagBody.getRemainingLength()); + if (tagHeader.getFooterSize() > 0) { + input.skip(tagHeader.getFooterSize()); + } + } + } + + void parseFrame(ID3v2FrameBody frame) throws IOException, ID3v2Exception { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Parsing frame: " + frame.getFrameHeader().getFrameId()); + } + switch (frame.getFrameHeader().getFrameId()) { + case "PIC": + case "APIC": // cover: prefer TYPE_COVER_FRONT, then TYPE_OTHER, then anything else + if (cover == null || coverPictureType != AttachedPicture.TYPE_COVER_FRONT) { + AttachedPicture picture = parseAttachedPictureFrame(frame); + if (cover == null || picture.type == AttachedPicture.TYPE_COVER_FRONT || picture.type == AttachedPicture.TYPE_OTHER) { + try { + byte[] bytes = picture.imageData; + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inJustDecodeBounds = true; + opts.inSampleSize = 1; + BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts); + if (opts.outWidth > 800 || opts.outHeight > 800) { + int size = Math.max(opts.outWidth, opts.outHeight); + while (size > 800) { + opts.inSampleSize *= 2; + size /= 2; + } + } + opts.inJustDecodeBounds = false; + cover = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opts); + if (cover != null) { + float scale = Math.max(cover.getWidth(), cover.getHeight()) / 120.0f; + if (scale > 0) { + smallCover = Bitmap.createScaledBitmap(cover, (int) (cover.getWidth() / scale), (int) (cover.getHeight() / scale), true); + } else { + smallCover = cover; + } + if (smallCover == null) { + smallCover = cover; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + coverPictureType = picture.type; + } + } + break; + case "COM": + case "COMM": + CommentOrUnsynchronizedLyrics comm = parseCommentOrUnsynchronizedLyricsFrame(frame); + if (comment == null || comm.description == null || "".equals(comm.description)) { // prefer "default" comment (without description) + comment = comm.text; + } + break; + case "TAL": + case "TALB": + album = parseTextFrame(frame); + break; + case "TCP": + case "TCMP": + compilation = "1".equals(parseTextFrame(frame)); + break; + case "TCM": + case "TCOM": + composer = parseTextFrame(frame); + break; + case "TCO": + case "TCON": + String tcon = parseTextFrame(frame); + if (tcon.length() > 0) { + genre = tcon; + try { + ID3v1Genre id3v1Genre = null; + if (tcon.charAt(0) == '(') { + int pos = tcon.indexOf(')'); + if (pos > 1) { // (123) + id3v1Genre = ID3v1Genre.getGenre(Integer.parseInt(tcon.substring(1, pos))); + if (id3v1Genre == null && tcon.length() > pos + 1) { // (789)Special + genre = tcon.substring(pos + 1); + } + } + } else { // 123 + id3v1Genre = ID3v1Genre.getGenre(Integer.parseInt(tcon)); + } + if (id3v1Genre != null) { + genre = id3v1Genre.getDescription(); + } + } catch (NumberFormatException e) { + // ignore + } + } + break; + case "TCR": + case "TCOP": + copyright = parseTextFrame(frame); + break; + case "TDRC": // v2.4, replaces TYER + String tdrc = parseTextFrame(frame); + if (tdrc.length() >= 4) { + try { + year = Short.valueOf(tdrc.substring(0, 4)); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse year from: " + tdrc); + } + } + } + break; + case "TLE": + case "TLEN": + String tlen = parseTextFrame(frame); + try { + duration = Long.valueOf(tlen); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse track duration: " + tlen); + } + } + break; + case "TP1": + case "TPE1": + artist = parseTextFrame(frame); + break; + case "TP2": + case "TPE2": + albumArtist = parseTextFrame(frame); + break; + case "TPA": + case "TPOS": + String tpos = parseTextFrame(frame); + if (tpos.length() > 0) { + int index = tpos.indexOf('/'); + if (index < 0) { + try { + disc = Short.valueOf(tpos); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse disc number: " + tpos); + } + } + } else { + try { + disc = Short.valueOf(tpos.substring(0, index)); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse disc number: " + tpos); + } + } + try { + discs = Short.valueOf(tpos.substring(index + 1)); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse number of discs: " + tpos); + } + } + } + } + break; + case "TRK": + case "TRCK": + String trck = parseTextFrame(frame); + if (trck.length() > 0) { + int index = trck.indexOf('/'); + if (index < 0) { + try { + track = Short.valueOf(trck); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse track number: " + trck); + } + } + } else { + try { + track = Short.valueOf(trck.substring(0, index)); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse track number: " + trck); + } + } + try { + tracks = Short.valueOf(trck.substring(index + 1)); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse number of tracks: " + trck); + } + } + } + } + break; + case "TT1": + case "TIT1": + grouping = parseTextFrame(frame); + break; + case "TT2": + case "TIT2": + title = parseTextFrame(frame); + break; + case "TYE": + case "TYER": + String tyer = parseTextFrame(frame); + if (tyer.length() > 0) { + try { + year = Short.valueOf(tyer); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not parse year: " + tyer); + } + } + } + break; + case "ULT": + case "USLT": + if (lyrics == null) { + lyrics = parseCommentOrUnsynchronizedLyricsFrame(frame).text; + } + break; + default: + break; + } + } + + String parseTextFrame(ID3v2FrameBody frame) throws IOException, ID3v2Exception { + ID3v2Encoding encoding = frame.readEncoding(); + return frame.readFixedLengthString((int) frame.getRemainingLength(), encoding); + } + + CommentOrUnsynchronizedLyrics parseCommentOrUnsynchronizedLyricsFrame(ID3v2FrameBody data) throws IOException, ID3v2Exception { + ID3v2Encoding encoding = data.readEncoding(); + String language = data.readFixedLengthString(3, ID3v2Encoding.ISO_8859_1); + String description = data.readZeroTerminatedString(200, encoding); + String text = data.readFixedLengthString((int) data.getRemainingLength(), encoding); + return new CommentOrUnsynchronizedLyrics(language, description, text); + } + + AttachedPicture parseAttachedPictureFrame(ID3v2FrameBody data) throws IOException, ID3v2Exception { + ID3v2Encoding encoding = data.readEncoding(); + String imageType; + if (data.getTagHeader().getVersion() == 2) { // file type, e.g. "JPG" + String fileType = data.readFixedLengthString(3, ID3v2Encoding.ISO_8859_1); + switch (fileType.toUpperCase()) { + case "PNG": + imageType = "image/png"; + break; + case "JPG": + imageType = "image/jpeg"; + break; + default: + imageType = "image/unknown"; + } + } else { // mime type, e.g. "image/jpeg" + imageType = data.readZeroTerminatedString(20, ID3v2Encoding.ISO_8859_1); + } + byte pictureType = data.getData().readByte(); + String description = data.readZeroTerminatedString(200, encoding); + byte[] imageData = data.getData().readFully((int) data.getRemainingLength()); + return new AttachedPicture(pictureType, description, imageType, imageData); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2TagBody.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2TagBody.java new file mode 100755 index 000000000..222e65fb6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2TagBody.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import org.telegram.android.audioinfo.util.RangeInputStream; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.InflaterInputStream; + +public class ID3v2TagBody { + private final RangeInputStream input; + private final ID3v2TagHeader tagHeader; + private final ID3v2DataInput data; + + ID3v2TagBody(InputStream delegate, long position, int length, ID3v2TagHeader tagHeader) throws IOException { + this.input = new RangeInputStream(delegate, position, length); + this.data = new ID3v2DataInput(input); + this.tagHeader = tagHeader; + } + + public ID3v2DataInput getData() { + return data; + } + + public long getPosition() { + return input.getPosition(); + } + + public long getRemainingLength() { + return input.getRemainingLength(); + } + + public ID3v2TagHeader getTagHeader() { + return tagHeader; + } + + public ID3v2FrameBody frameBody(ID3v2FrameHeader frameHeader) throws IOException, ID3v2Exception { + int dataLength = frameHeader.getBodySize(); + InputStream input = this.input; + if (frameHeader.isUnsynchronization()) { + byte[] bytes = data.readFully(frameHeader.getBodySize()); + boolean ff = false; + int len = 0; + for (byte b : bytes) { + if (!ff || b != 0) { + bytes[len++] = b; + } + ff = (b == 0xFF); + } + dataLength = len; + input = new ByteArrayInputStream(bytes, 0, len); + } + if (frameHeader.isEncryption()) { + throw new ID3v2Exception("Frame encryption is not supported"); + } + if (frameHeader.isCompression()) { + dataLength = frameHeader.getDataLengthIndicator(); + input = new InflaterInputStream(input); + } + return new ID3v2FrameBody(input, frameHeader.getHeaderSize(), dataLength, tagHeader, frameHeader); + } + + public String toString() { + return "id3v2tag[pos=" + getPosition() + ", " + getRemainingLength() + " left]"; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2TagHeader.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2TagHeader.java new file mode 100755 index 000000000..d2431cd05 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/ID3v2TagHeader.java @@ -0,0 +1,191 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import org.telegram.android.audioinfo.util.PositionInputStream; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class ID3v2TagHeader { + private int version = 0; + private int revision = 0; + private int headerSize = 0; // size of header, including extended header (with attachments) + private int totalTagSize = 0; // everything, i.e. inluding tag header, extended header, footer & padding + private int paddingSize = 0; // size of zero padding after frames + private int footerSize = 0; // size of footer (version 4 only) + private boolean unsynchronization; + private boolean compression; + + public ID3v2TagHeader(InputStream input) throws IOException, ID3v2Exception { + this(new PositionInputStream(input)); + } + + ID3v2TagHeader(PositionInputStream input) throws IOException, ID3v2Exception { + long startPosition = input.getPosition(); + + ID3v2DataInput data = new ID3v2DataInput(input); + + /* + * Identifier: "ID3" + */ + String id = new String(data.readFully(3), "ISO-8859-1"); + if (!"ID3".equals(id)) { + throw new ID3v2Exception("Invalid ID3 identifier: " + id); + } + + /* + * Version: $02, $03 or $04 + */ + version = data.readByte(); + if (version != 2 && version != 3 && version != 4) { + throw new ID3v2Exception("Unsupported ID3v2 version: " + version); + } + + /* + * Revision: $xx + */ + revision = data.readByte(); + + /* + * Flags (evaluated below) + */ + byte flags = data.readByte(); + + /* + * Size: 4 * %0xxxxxxx (sync-save integer) + */ + totalTagSize = 10 + data.readSyncsafeInt(); + + /* + * Evaluate flags + */ + if (version == 2) { // %(unsynchronisation)(compression)000000 + unsynchronization = (flags & 0x80) != 0; + compression = (flags & 0x40) != 0; + } else { // %(unsynchronisation)(extendedHeader)(experimentalIndicator)(version == 3 ? 0 : footerPresent)0000 + unsynchronization = (flags & 0x80) != 0; + + /* + * Extended Header + */ + if ((flags & 0x40) != 0) { + if (version == 3) { + /* + * Extended header size: $xx xx xx xx (6 or 10 if CRC data present) + * In version 3, the size excludes itself. + */ + int extendedHeaderSize = data.readInt(); + + /* + * Extended Flags: $xx xx (skip) + */ + data.readByte(); // flags... + data.readByte(); // more flags... + + /* + * Size of padding: $xx xx xx xx + */ + paddingSize = data.readInt(); + + /* + * consume the rest + */ + data.skipFully(extendedHeaderSize - 6); + } else { + /* + * Extended header size: 4 * %0xxxxxxx (sync-save integer) + * In version 4, the size includes itself. + */ + int extendedHeaderSize = data.readSyncsafeInt(); + + /* + * consume the rest + */ + data.skipFully(extendedHeaderSize - 4); + } + } + + /* + * Footer Present + */ + if (version >= 4 && (flags & 0x10) != 0) { // footer present + footerSize = 10; + totalTagSize += 10; + } + } + + headerSize = (int) (input.getPosition() - startPosition); + } + + public ID3v2TagBody tagBody(InputStream input) throws IOException, ID3v2Exception { + if (compression) { + throw new ID3v2Exception("Tag compression is not supported"); + } + if (version < 4 && unsynchronization) { + byte[] bytes = new ID3v2DataInput(input).readFully(totalTagSize - headerSize); + boolean ff = false; + int len = 0; + for (byte b : bytes) { + if (!ff || b != 0) { + bytes[len++] = b; + } + ff = (b == 0xFF); + } + return new ID3v2TagBody(new ByteArrayInputStream(bytes, 0, len), headerSize, len, this); + } else { + return new ID3v2TagBody(input, headerSize, totalTagSize - headerSize - footerSize, this); + } + } + + public int getVersion() { + return version; + } + + public int getRevision() { + return revision; + } + + public int getTotalTagSize() { + return totalTagSize; + } + + public boolean isUnsynchronization() { + return unsynchronization; + } + + public boolean isCompression() { + return compression; + } + + public int getHeaderSize() { + return headerSize; + } + + public int getFooterSize() { + return footerSize; + } + + public int getPaddingSize() { + return paddingSize; + } + + @Override + public String toString() { + return String.format("%s[version=%s, totalTagSize=%d]", getClass().getSimpleName(), version, totalTagSize); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Exception.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Exception.java new file mode 100755 index 000000000..2b9abf2e2 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Exception.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +public class MP3Exception extends Exception { + private static final long serialVersionUID = 1L; + + public MP3Exception(String message) { + super(message); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Frame.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Frame.java new file mode 100755 index 000000000..60f7ba679 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Frame.java @@ -0,0 +1,315 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + + +public class MP3Frame { + static final class CRC16 { + private short crc = (short) 0xFFFF; + + public void update(int value, int length) { + int mask = 1 << (length - 1); + do { + if (((crc & 0x8000) == 0) ^ ((value & mask) == 0)) { + crc <<= 1; + crc ^= 0x8005; + } else { + crc <<= 1; + } + } while ((mask >>>= 1) != 0); + } + + public void update(byte value) { + update(value, 8); + } + + public short getValue() { + return crc; + } + + public void reset() { + crc = (short) 0xFFFF; + } + } + + public static class Header { + private static final int MPEG_LAYER_RESERVED = 0; + private static final int MPEG_VERSION_RESERVED = 1; + private static final int MPEG_BITRATE_FREE = 0; + private static final int MPEG_BITRATE_RESERVED = 15; + private static final int MPEG_FRQUENCY_RESERVED = 3; + + // [frequency][version] + private static final int[][] FREQUENCIES = new int[][] { + // 2.5 reserved 2 1 + { 11025, -1, 22050, 44100 }, + { 12000, -1, 24000, 48000 }, + { 8000, -1, 16000, 32000 }, + { -1, -1, -1, -1 } // reserved + }; + + // [bitrate][version,layer] + private static final int[][] BITRATES = new int[][] { + { 0, 0, 0, 0, 0 }, // free + { 32000, 32000, 32000, 32000, 8000 }, + { 64000, 48000, 40000, 48000, 16000 }, + { 96000, 56000, 48000, 56000, 24000 }, + { 128000, 64000, 56000, 64000, 32000 }, + { 160000, 80000, 64000, 80000, 40000 }, + { 192000, 96000, 80000, 96000, 48000 }, + { 224000, 112000, 96000, 112000, 56000 }, + { 256000, 128000, 112000, 128000, 64000 }, + { 288000, 160000, 128000, 144000, 80000 }, + { 320000, 192000, 160000, 160000, 96000 }, + { 352000, 224000, 192000, 176000, 112000 }, + { 384000, 256000, 224000, 192000, 128000 }, + { 416000, 320000, 256000, 224000, 144000 }, + { 448000, 384000, 320000, 256000, 160000 }, + { -1, -1, -1, -1, -1 } // reserved + }; + + // [version][layer] + private static final int[][] BITRATES_COLUMN = new int[][] { + // reserved III II I + { -1, 4, 4, 3 }, // 2.5 + { -1, -1, -1, -1 }, // reserved + { -1, 4, 4, 3 }, // 2 + { -1, 2, 1, 0 } // 1 + }; + + // [version][layer] + private static final int[][] SIZE_COEFFICIENTS = new int[][] { + // reserved III II I + { -1, 72, 144, 12 }, // 2.5 + { -1, -1, -1, -1 }, // reserved + { -1, 72, 144, 12 }, // 2 + { -1, 144, 144, 12 } // 1 + }; + + // [layer] + private static final int[] SLOT_SIZES = new int[] { + // reserved III II I + -1, 1, 1, 4 + }; + + // [channelMode][version] + private static final int[][] SIDE_INFO_SIZES = new int[][] { + // 2.5 reserved 2 1 + { 17, -1, 17, 32 }, // stereo + { 17, -1, 17, 32 }, // joint stereo + { 17, -1, 17, 32 }, // dual channel + { 9, -1, 9, 17 }, // mono + }; + + public static final int MPEG_LAYER_1 = 3; + public static final int MPEG_LAYER_2 = 2; + public static final int MPEG_LAYER_3 = 1; + + public static final int MPEG_VERSION_1 = 3; + public static final int MPEG_VERSION_2 = 2; + public static final int MPEG_VERSION_2_5 = 0; + + public static final int MPEG_CHANNEL_MODE_MONO = 3; + public static final int MPEG_PROTECTION_CRC = 0; + + private final int version; + private final int layer; + private final int frequency; + private final int bitrate; + private final int channelMode; + private final int padding; + private final int protection; + + public Header(int b1, int b2, int b3) throws MP3Exception { + version = b1 >> 3 & 0x3; + if (version == MPEG_VERSION_RESERVED) { + throw new MP3Exception("Reserved version"); + } + layer = b1 >> 1 & 0x3; + if (layer == MPEG_LAYER_RESERVED) { + throw new MP3Exception("Reserved layer"); + } + bitrate = b2 >> 4 & 0xF; + if (bitrate == MPEG_BITRATE_RESERVED) { + throw new MP3Exception("Reserved bitrate"); + } + if (bitrate == MPEG_BITRATE_FREE) { + throw new MP3Exception("Free bitrate"); + } + frequency = b2 >> 2 & 0x3; + if (frequency == MPEG_FRQUENCY_RESERVED) { + throw new MP3Exception("Reserved frequency"); + } + channelMode = b3 >> 6 & 0x3; + padding = b2 >> 1 & 0x1; + protection = b1 & 0x1; + + int minFrameSize = 4; + if (protection == MPEG_PROTECTION_CRC) { + minFrameSize += 2; + } + if (layer == MPEG_LAYER_3) { + minFrameSize += getSideInfoSize(); + } + if (getFrameSize() < minFrameSize) { + throw new MP3Exception("Frame size must be at least " + minFrameSize); + } + } + + public int getVersion() { + return version; + } + + public int getLayer() { + return layer; + } + + public int getFrequency() { + return FREQUENCIES[frequency][version]; + } + + public int getChannelMode() { + return channelMode; + } + + public int getProtection() { + return protection; + } + + public int getSampleCount() { + if (layer == MPEG_LAYER_1) { + return 384; + } else { // TODO correct? + return 1152; + } + } + + public int getFrameSize() { + return ((SIZE_COEFFICIENTS[version][layer] * getBitrate() / getFrequency()) + padding) * SLOT_SIZES[layer]; + } + + public int getBitrate() { + return BITRATES[bitrate][BITRATES_COLUMN[version][layer]]; + } + + public int getDuration() { + return (int)getTotalDuration(getFrameSize()); + } + + public long getTotalDuration(long totalSize) { + long duration = 1000L * (getSampleCount() * totalSize) / (getFrameSize() * getFrequency()); + if (getVersion() != MPEG_VERSION_1 && getChannelMode() == MPEG_CHANNEL_MODE_MONO) { + duration /= 2; + } + return duration; + } + + public boolean isCompatible(Header header) { + return layer == header.layer && version == header.version && frequency == header.frequency && channelMode == header.channelMode; + } + + public int getSideInfoSize() { + return SIDE_INFO_SIZES[channelMode][version]; + } + + public int getXingOffset() { + return 4 + getSideInfoSize(); + } + + public int getVBRIOffset() { + return 4 + 32; + } + } + + private final byte[] bytes; + private final Header header; + + MP3Frame(Header header, byte[] bytes) { + this.header = header; + this.bytes = bytes; + } + + boolean isChecksumError() { + if (header.getProtection() == Header.MPEG_PROTECTION_CRC) { + if (header.getLayer() == Header.MPEG_LAYER_3) { + CRC16 crc16 = new CRC16(); + crc16.update(bytes[2]); + crc16.update(bytes[3]); + // skip crc bytes 4+5 + int sideInfoSize = header.getSideInfoSize(); + for (int i = 0; i < sideInfoSize; i++) { + crc16.update(bytes[6 + i]); + } + int crc = ((bytes[4] & 0xFF) << 8) | (bytes[5] & 0xFF); + return crc != crc16.getValue(); + } + } + return false; + } + + public int getSize() { + return bytes.length; + } + + public Header getHeader() { + return header; + } + + boolean isXingFrame() { + int xingOffset = header.getXingOffset(); + if (bytes.length < xingOffset + 12) { // minimum Xing header size == 12 + return false; + } + if (xingOffset < 0 || bytes.length < xingOffset + 8) { + return false; + } + if (bytes[xingOffset] == 'X' && bytes[xingOffset + 1] == 'i' && bytes[xingOffset + 2] == 'n' && bytes[xingOffset + 3] == 'g') { + return true; + } + if (bytes[xingOffset] == 'I' && bytes[xingOffset + 1] == 'n' && bytes[xingOffset + 2] == 'f' && bytes[xingOffset + 3] == 'o') { + return true; + } + return false; + } + + boolean isVBRIFrame() { + int vbriOffset = header.getVBRIOffset(); + if (bytes.length < vbriOffset + 26) { // minimum VBRI header size == 26 + return false; + } + return bytes[vbriOffset] == 'V' && bytes[vbriOffset + 1] == 'B' && bytes[vbriOffset + 2] == 'R' && bytes[vbriOffset + 3] == 'I'; + } + + public int getNumberOfFrames() { + if (isXingFrame()) { + int xingOffset = header.getXingOffset(); + byte flags = bytes[xingOffset + 7]; + if ((flags & 0x01) != 0) { + return ((bytes[xingOffset + 8] & 0xFF) << 24) | + ((bytes[xingOffset + 9] & 0xFF) << 16) | + ((bytes[xingOffset + 10] & 0xFF) << 8) | + ( bytes[xingOffset + 11] & 0xFF); + } + } else if (isVBRIFrame()) { + int vbriOffset = header.getVBRIOffset(); + return ((bytes[vbriOffset + 14] & 0xFF) << 24) | + ((bytes[vbriOffset + 15] & 0xFF) << 16) | + ((bytes[vbriOffset + 16] & 0xFF) << 8) | + ( bytes[vbriOffset + 17] & 0xFF); + } + return -1; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Info.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Info.java new file mode 100755 index 000000000..9a2a616b0 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Info.java @@ -0,0 +1,270 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import org.telegram.android.audioinfo.AudioInfo; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class MP3Info extends AudioInfo { + static final Logger LOGGER = Logger.getLogger(MP3Info.class.getName()); + + interface StopReadCondition { + boolean stopRead(MP3Input data) throws IOException; + } + + public MP3Info(InputStream input, long fileLength) throws IOException, ID3v2Exception, MP3Exception { + this(input, fileLength, Level.FINEST); + } + + public MP3Info(InputStream input, final long fileLength, Level debugLevel) throws IOException, ID3v2Exception, MP3Exception { + brand = "MP3"; + version = "0"; + MP3Input data = new MP3Input(input); + if (ID3v2Info.isID3v2StartPosition(data)) { + ID3v2Info info = new ID3v2Info(data, debugLevel); + album = info.getAlbum(); + albumArtist = info.getAlbumArtist(); + artist = info.getArtist(); + comment = info.getComment(); + cover = info.getCover(); + smallCover = info.getSmallCover(); + compilation = info.isCompilation(); + composer = info.getComposer(); + copyright = info.getCopyright(); + disc = info.getDisc(); + discs = info.getDiscs(); + duration = info.getDuration(); + genre = info.getGenre(); + grouping = info.getGrouping(); + lyrics = info.getLyrics(); + title = info.getTitle(); + track = info.getTrack(); + tracks = info.getTracks(); + year = info.getYear(); + } + if (duration <= 0 || duration >= 3600000L) { // don't trust strange durations (e.g. old lame versions always write TLEN 97391548) + try { + duration = calculateDuration(data, fileLength, new StopReadCondition() { + final long stopPosition = fileLength - 128; + + @Override + public boolean stopRead(MP3Input data) throws IOException { + return (data.getPosition() == stopPosition) && ID3v1Info.isID3v1StartPosition(data); + } + }); + } catch (MP3Exception e) { + if (LOGGER.isLoggable(debugLevel)) { + LOGGER.log(debugLevel, "Could not determine MP3 duration", e); + } + } + } + if (title == null || album == null || artist == null) { + if (data.getPosition() <= fileLength - 128) { // position to last 128 bytes + data.skipFully(fileLength - 128 - data.getPosition()); + if (ID3v1Info.isID3v1StartPosition(input)) { + ID3v1Info info = new ID3v1Info(input); + if (album == null) { + album = info.getAlbum(); + } + if (artist == null) { + artist = info.getArtist(); + } + if (comment == null) { + comment = info.getComment(); + } + if (genre == null) { + genre = info.getGenre(); + } + if (title == null) { + title = info.getTitle(); + } + if (track == 0) { + track = info.getTrack(); + } + if (year == 0) { + year = info.getYear(); + } + } + } + } + } + + MP3Frame readFirstFrame(MP3Input data, StopReadCondition stopCondition) throws IOException { + int b0 = 0; + int b1 = stopCondition.stopRead(data) ? -1 : data.read(); + while (b1 != -1) { + if (b0 == 0xFF && (b1 & 0xE0) == 0xE0) { // first 11 bits should be 1 + data.mark(2); // set mark at b2 + int b2 = stopCondition.stopRead(data) ? -1 : data.read(); + if (b2 == -1) { + break; + } + int b3 = stopCondition.stopRead(data) ? -1 : data.read(); + if (b3 == -1) { + break; + } + MP3Frame.Header header = null; + try { + header = new MP3Frame.Header(b1, b2, b3); + } catch (MP3Exception e) { + // not a valid frame header + } + if (header != null) { // we have a candidate + /* + * The code gets a bit complex here, because we need to be able to reset() to b2 if + * the check fails. Thus, we have to reset() to b2 before doing a call to mark(). + */ + data.reset(); // reset input to b2 + data.mark(header.getFrameSize() + 2); // rest of frame (size - 2) + next header + /* + * read frame data + */ + byte[] frameBytes = new byte[header.getFrameSize()]; + frameBytes[0] = (byte) 0xFF; + frameBytes[1] = (byte) b1; + try { + data.readFully(frameBytes, 2, frameBytes.length - 2); // may throw EOFException + } catch (EOFException e) { + break; + } + + MP3Frame frame = new MP3Frame(header, frameBytes); + /* + * read next header + */ + if (!frame.isChecksumError()) { + int nextB0 = stopCondition.stopRead(data) ? -1 : data.read(); + int nextB1 = stopCondition.stopRead(data) ? -1 : data.read(); + if (nextB0 == -1 || nextB1 == -1) { + return frame; + } + if (nextB0 == 0xFF && (nextB1 & 0xFE) == (b1 & 0xFE)) { // quick check: nextB1 must match b1's version & layer + int nextB2 = stopCondition.stopRead(data) ? -1 : data.read(); + int nextB3 = stopCondition.stopRead(data) ? -1 : data.read(); + if (nextB2 == -1 || nextB3 == -1) { + return frame; + } + try { + if (new MP3Frame.Header(nextB1, nextB2, nextB3).isCompatible(header)) { + data.reset(); // reset input to b2 + data.skipFully(frameBytes.length - 2); // skip to end of frame + return frame; + } + } catch (MP3Exception e) { + // not a valid frame header + } + } + } + } + + /* + * seems to be a false sync... + */ + data.reset(); // reset input to b2 + } + + /* + * read next byte + */ + b0 = b1; + b1 = stopCondition.stopRead(data) ? -1 : data.read(); + } + return null; + } + + MP3Frame readNextFrame(MP3Input data, StopReadCondition stopCondition, MP3Frame previousFrame) throws IOException { + MP3Frame.Header previousHeader = previousFrame.getHeader(); + data.mark(4); + int b0 = stopCondition.stopRead(data) ? -1 : data.read(); + int b1 = stopCondition.stopRead(data) ? -1 : data.read(); + if (b0 == -1 || b1 == -1) { + return null; + } + if (b0 == 0xFF && (b1 & 0xE0) == 0xE0) { // first 11 bits should be 1 + int b2 = stopCondition.stopRead(data) ? -1 : data.read(); + int b3 = stopCondition.stopRead(data) ? -1 : data.read(); + if (b2 == -1 || b3 == -1) { + return null; + } + MP3Frame.Header nextHeader = null; + try { + nextHeader = new MP3Frame.Header(b1, b2, b3); + } catch (MP3Exception e) { + // not a valid frame header + } + if (nextHeader != null && nextHeader.isCompatible(previousHeader)) { + byte[] frameBytes = new byte[nextHeader.getFrameSize()]; + frameBytes[0] = (byte) b0; + frameBytes[1] = (byte) b1; + frameBytes[2] = (byte) b2; + frameBytes[3] = (byte) b3; + try { + data.readFully(frameBytes, 4, frameBytes.length - 4); + } catch (EOFException e) { + return null; + } + return new MP3Frame(nextHeader, frameBytes); + } + } + data.reset(); + return null; + } + + long calculateDuration(MP3Input data, long totalLength, StopReadCondition stopCondition) throws IOException, MP3Exception { + MP3Frame frame = readFirstFrame(data, stopCondition); + if (frame != null) { + // check for Xing header + int numberOfFrames = frame.getNumberOfFrames(); + if (numberOfFrames > 0) { // from Xing/VBRI header + return frame.getHeader().getTotalDuration(numberOfFrames * frame.getSize()); + } else { // scan file + numberOfFrames = 1; + + long firstFramePosition = data.getPosition() - frame.getSize(); + long frameSizeSum = frame.getSize(); + + int firstFrameBitrate = frame.getHeader().getBitrate(); + long bitrateSum = firstFrameBitrate; + boolean vbr = false; + int cbrThreshold = 10000 / frame.getHeader().getDuration(); // assume CBR after 10 seconds + + while (true) { + if (numberOfFrames == cbrThreshold && !vbr && totalLength > 0) { + return frame.getHeader().getTotalDuration(totalLength - firstFramePosition); + } + if ((frame = readNextFrame(data, stopCondition, frame)) == null) { + break; + } + int bitrate = frame.getHeader().getBitrate(); + if (bitrate != firstFrameBitrate) { + vbr = true; + } + bitrateSum += bitrate; + frameSizeSum += frame.getSize(); + numberOfFrames++; + } + return 1000L * frameSizeSum * numberOfFrames * 8 / bitrateSum; + } + } else { + throw new MP3Exception("No audio frame"); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Input.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Input.java new file mode 100755 index 000000000..f27aa8112 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/mp3/MP3Input.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.mp3; + +import org.telegram.android.audioinfo.util.PositionInputStream; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +public class MP3Input extends PositionInputStream { + public MP3Input(InputStream delegate) throws IOException { + super(delegate); + } + + public MP3Input(InputStream delegate, long position) { + super(delegate, position); + } + + public final void readFully(byte b[], int off, int len) throws IOException { + int total = 0; + while (total < len) { + int current = read(b, off + total, len - total); + if (current > 0) { + total += current; + } else { + throw new EOFException(); + } + } + } + + public void skipFully(long len) throws IOException { + long total = 0; + while (total < len) { + long current = skip(len - total); + if (current > 0) { + total += current; + } else { + throw new EOFException(); + } + } + } + + public String toString() { + return "mp3[pos=" + getPosition() + "]"; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/util/PositionInputStream.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/util/PositionInputStream.java new file mode 100755 index 000000000..ad29d6185 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/util/PositionInputStream.java @@ -0,0 +1,79 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.util; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class PositionInputStream extends FilterInputStream { + private long position; + private long positionMark; + + public PositionInputStream(InputStream delegate) { + this(delegate, 0L); + } + + public PositionInputStream(InputStream delegate, long position) { + super(delegate); + this.position = position; + } + + @Override + public synchronized void mark(int readlimit) { + positionMark = position; + super.mark(readlimit); + } + + @Override + public synchronized void reset() throws IOException { + super.reset(); + position = positionMark; + } + + public int read() throws IOException { + int data = super.read(); + if (data >= 0) { + position++; + } + return data; + } + + public int read(byte[] b, int off, int len) throws IOException { + long p = position; + int read = super.read(b, off, len); + if (read > 0) { + position = p + read; + } + return read; + } + + @Override + public final int read(byte[] b) throws IOException { + return read(b, 0, b.length); + } + + public long skip(long n) throws IOException { + long p = position; + long skipped = super.skip(n); + position = p + skipped; + return skipped; + } + + public long getPosition() { + return position; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/audioinfo/util/RangeInputStream.java b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/util/RangeInputStream.java new file mode 100755 index 000000000..7c4dbef5f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/audioinfo/util/RangeInputStream.java @@ -0,0 +1,63 @@ +/* + * Copyright 2013-2014 Odysseus Software GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.telegram.android.audioinfo.util; + +import java.io.IOException; +import java.io.InputStream; + +/** + * Input stream filter that keeps track of the current read position + * and has a read length limit. + */ +public class RangeInputStream extends PositionInputStream { + private final long endPosition; + + public RangeInputStream(InputStream delegate, long position, long length) throws IOException { + super(delegate, position); + this.endPosition = position + length; + } + + public long getRemainingLength() { + return endPosition - getPosition(); + } + + @Override + public int read() throws IOException { + if (getPosition() == endPosition) { + return -1; + } + return super.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (getPosition() + len > endPosition) { + len = (int)(endPosition - getPosition()); + if (len == 0) { + return -1; + } + } + return super.read(b, off, len); + } + + @Override + public long skip(long n) throws IOException { + if (getPosition() + n > endPosition) { + n = (int)(endPosition - getPosition()); + } + return super.skip(n); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/query/SharedMediaQuery.java b/TMessagesProj/src/main/java/org/telegram/android/query/SharedMediaQuery.java index f1acd0285..492fea8d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/query/SharedMediaQuery.java +++ b/TMessagesProj/src/main/java/org/telegram/android/query/SharedMediaQuery.java @@ -400,4 +400,38 @@ public class SharedMediaQuery { } }); } + + public static void loadMusic(final long uid, final int max_id) { + MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() { + @Override + public void run() { + final ArrayList arrayList = new ArrayList<>(); + try { + SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT 1000", uid, max_id, MEDIA_FILE)); + + 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.TLdeserialize(data, data.readInt32(false), false); + if (MessageObject.isMusicMessage(message)) { + message.id = cursor.intValue(1); + message.dialog_id = uid; + arrayList.add(0, new MessageObject(message, null, false)); + } + } + MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data); + } + cursor.dispose(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + NotificationCenter.getInstance().postNotificationName(NotificationCenter.musicDidLoaded, uid, arrayList); + } + }); + } + }); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/util/SortedList.java b/TMessagesProj/src/main/java/org/telegram/android/support/util/SortedList.java index 688e032c8..c8bb6d3e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/util/SortedList.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/util/SortedList.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package android.support.v7.util; +package org.telegram.android.support.util; import java.lang.reflect.Array; +import java.util.Arrays; /** * A Sorted list implementation that can keep items in order and also notify for changes in the @@ -418,6 +419,19 @@ public class SortedList { mSize++; } + /** + * Removes all items from the SortedList. + */ + public void clear() { + if (mSize == 0) { + return; + } + final int prevSize = mSize; + Arrays.fill(mData, 0, prevSize, null); + mSize = 0; + mCallback.onRemoved(0, prevSize); + } + /** * The class that controls the behavior of the {@link SortedList}. *

diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/AdapterHelper.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/AdapterHelper.java index 3b4c28c1a..d56fb0b99 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/AdapterHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/AdapterHelper.java @@ -19,6 +19,9 @@ package org.telegram.android.support.widget; import android.support.v4.util.Pools; import android.util.Log; +import org.telegram.android.support.widget.OpReorderer; +import org.telegram.android.support.widget.RecyclerView; + import java.util.ArrayList; import java.util.Collections; import java.util.List; diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/DefaultItemAnimator.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/DefaultItemAnimator.java index bbbc20a54..0d7e11af7 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/DefaultItemAnimator.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/DefaultItemAnimator.java @@ -18,6 +18,7 @@ package org.telegram.android.support.widget; import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPropertyAnimatorCompat; import android.support.v4.view.ViewPropertyAnimatorListener; + import org.telegram.android.support.widget.RecyclerView.ViewHolder; import android.view.View; diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/GridLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/GridLayoutManager.java index 790bf06f8..37453d67c 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/GridLayoutManager.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/GridLayoutManager.java @@ -24,6 +24,8 @@ import android.util.SparseIntArray; import android.view.View; import android.view.ViewGroup; +import org.telegram.android.support.widget.RecyclerView; + import java.util.Arrays; /** diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/LayoutState.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/LayoutState.java index c431b6149..b91274a1e 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/LayoutState.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/LayoutState.java @@ -60,11 +60,14 @@ class LayoutState { int mLayoutDirection; /** - * Used if you want to pre-layout items that are not yet visible. - * The difference with {@link #mAvailable} is that, when recycling, distance rendered for - * {@link #mExtra} is not considered not to recycle visible children. + * This is the target pixel closest to the start of the layout that we are trying to fill */ - int mExtra = 0; + int mStartLine = 0; + + /** + * This is the target pixel closest to the end of the layout that we are trying to fill + */ + int mEndLine = 0; /** * @return true if there are more items in the data adapter @@ -84,4 +87,16 @@ class LayoutState { mCurrentPosition += mItemDirection; return view; } + + @Override + public String toString() { + return "LayoutState{" + + "mAvailable=" + mAvailable + + ", mCurrentPosition=" + mCurrentPosition + + ", mItemDirection=" + mItemDirection + + ", mLayoutDirection=" + mLayoutDirection + + ", mStartLine=" + mStartLine + + ", mEndLine=" + mEndLine + + '}'; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/LinearLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/LinearLayoutManager.java index a52bbffe5..a0508ad5f 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/LinearLayoutManager.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/LinearLayoutManager.java @@ -23,6 +23,12 @@ import android.os.Parcelable; import android.support.v4.view.ViewCompat; import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.support.v4.view.accessibility.AccessibilityRecordCompat; +import android.util.AttributeSet; + +import org.telegram.android.support.widget.OrientationHelper; +import org.telegram.android.support.widget.RecyclerView; +import org.telegram.android.support.widget.ScrollbarHelper; +import org.telegram.android.support.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -33,10 +39,11 @@ import java.util.List; import static org.telegram.android.support.widget.RecyclerView.NO_POSITION; /** - * A {@link android.support.v7.widget.RecyclerView.LayoutManager} implementation which provides + * A {@link RecyclerView.LayoutManager} implementation which provides * similar functionality to {@link android.widget.ListView}. */ -public class LinearLayoutManager extends RecyclerView.LayoutManager { +public class LinearLayoutManager extends RecyclerView.LayoutManager implements + ItemTouchHelper.ViewDropHandler { private static final String TAG = "LinearLayoutManager"; @@ -130,7 +137,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { * Re-used variable to keep anchor information on re-layout. * Anchor position and coordinate defines the reference point for LLM while doing a layout. * */ - final AnchorInfo mAnchorInfo; + final AnchorInfo mAnchorInfo = new AnchorInfo(); /** * Creates a vertical LinearLayoutManager @@ -148,7 +155,6 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { * @param reverseLayout When set to true, layouts from end to start. */ public LinearLayoutManager(Context context, int orientation, boolean reverseLayout) { - mAnchorInfo = new AnchorInfo(); setOrientation(orientation); setReverseLayout(reverseLayout); } @@ -342,8 +348,8 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { * laid out at the end of the UI, second item is laid out before it etc. * * For horizontal layouts, it depends on the layout direction. - * When set to true, If {@link android.support.v7.widget.RecyclerView} is LTR, than it will - * layout from RTL, if {@link android.support.v7.widget.RecyclerView}} is RTL, it will layout + * When set to true, If {@link RecyclerView} is LTR, than it will + * layout from RTL, if {@link RecyclerView}} is RTL, it will layout * from LTR. * * If you are looking for the exact same behavior of @@ -371,9 +377,13 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { final int firstChild = getPosition(getChildAt(0)); final int viewPosition = position - firstChild; if (viewPosition >= 0 && viewPosition < childCount) { - return getChildAt(viewPosition); + final View child = getChildAt(viewPosition); + if (getPosition(child) == position) { + return child; // in pre-layout, this may not match + } } - return null; + // fallback to traversal. This might be necessary in pre-layout. + return super.findViewByPosition(position); } /** @@ -796,6 +806,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { } // override layout from end values for consistency anchorInfo.mLayoutFromEnd = mShouldReverseLayout; + // if this changes, we should update prepareForDrop as well if (mShouldReverseLayout) { anchorInfo.mCoordinate = mOrientationHelper.getEndAfterPadding() - mPendingScrollPositionOffset; @@ -941,7 +952,6 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { * item[10]'s bottom is 20 pixels above the RecyclerView's bottom. *

* Note that scroll position change will not be reflected until the next layout call. - * *

* If you are just trying to make a position visible, use {@link #scrollToPosition(int)}. * @@ -1175,11 +1185,10 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { /** * Recycles views that went out of bounds after scrolling towards the end of the layout. * - * @param recycler Recycler instance of {@link android.support.v7.widget.RecyclerView} + * @param recycler Recycler instance of {@link RecyclerView} * @param dt This can be used to add additional padding to the visible area. This is used - * to - * detect children that will go out of bounds after scrolling, without actually - * moving them. + * to detect children that will go out of bounds after scrolling, without + * actually moving them. */ private void recycleViewsFromStart(RecyclerView.Recycler recycler, int dt) { if (dt < 0) { @@ -1215,7 +1224,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { /** * Recycles views that went out of bounds after scrolling towards the start of the layout. * - * @param recycler Recycler instance of {@link android.support.v7.widget.RecyclerView} + * @param recycler Recycler instance of {@link RecyclerView} * @param dt This can be used to add additional padding to the visible area. This is used * to detect children that will go out of bounds after scrolling, without * actually moving them. @@ -1257,8 +1266,8 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { * @param layoutState Current layout state. Right now, this object does not change but * we may consider moving it out of this view so passing around as a * parameter for now, rather than accessing {@link #mLayoutState} - * @see #recycleViewsFromStart(android.support.v7.widget.RecyclerView.Recycler, int) - * @see #recycleViewsFromEnd(android.support.v7.widget.RecyclerView.Recycler, int) + * @see #recycleViewsFromStart(RecyclerView.Recycler, int) + * @see #recycleViewsFromEnd(RecyclerView.Recycler, int) * @see android.support.v7.widget.LinearLayoutManager.LayoutState#mLayoutDirection */ private void recycleByLayoutState(RecyclerView.Recycler recycler, LayoutState layoutState) { @@ -1788,6 +1797,40 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager { return mPendingSavedState == null && mLastStackFromEnd == mStackFromEnd; } + /** + * @hide This method should be called by ItemTouchHelper only. + */ + @Override + public void prepareForDrop(View view, View target, int x, int y) { + assertNotInLayoutOrScroll("Cannot drop a view during a scroll or layout calculation"); + ensureLayoutState(); + resolveShouldLayoutReverse(); + final int myPos = getPosition(view); + final int targetPos = getPosition(target); + final int dropDirection = myPos < targetPos ? LayoutState.ITEM_DIRECTION_TAIL : + LayoutState.ITEM_DIRECTION_HEAD; + if (mShouldReverseLayout) { + if (dropDirection == LayoutState.ITEM_DIRECTION_TAIL) { + scrollToPositionWithOffset(targetPos, + mOrientationHelper.getEndAfterPadding() - + (mOrientationHelper.getDecoratedStart(target) + + mOrientationHelper.getDecoratedMeasurement(view))); + } else { + scrollToPositionWithOffset(targetPos, + mOrientationHelper.getEndAfterPadding() - + mOrientationHelper.getDecoratedEnd(target)); + } + } else { + if (dropDirection == LayoutState.ITEM_DIRECTION_HEAD) { + scrollToPositionWithOffset(targetPos, mOrientationHelper.getDecoratedStart(target)); + } else { + scrollToPositionWithOffset(targetPos, + mOrientationHelper.getDecoratedEnd(target) - + mOrientationHelper.getDecoratedMeasurement(view)); + } + } + } + /** * Helper class that keeps temporary state while {LayoutManager} is filling out the empty * space. diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/OpReorderer.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/OpReorderer.java index 3d56822f7..05d0e93a9 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/OpReorderer.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/OpReorderer.java @@ -16,14 +16,14 @@ package org.telegram.android.support.widget; -import java.util.List; - import org.telegram.android.support.widget.AdapterHelper.UpdateOp; import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.ADD; import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.MOVE; import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.REMOVE; import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.UPDATE; +import java.util.List; + class OpReorderer { final Callback mCallback; @@ -58,7 +58,7 @@ class OpReorderer { } void swapMoveRemove(List list, int movePos, UpdateOp moveOp, - int removePos, UpdateOp removeOp) { + int removePos, UpdateOp removeOp) { UpdateOp extraRm = null; // check if move is nulled out by remove boolean revertedMove = false; @@ -83,7 +83,7 @@ class OpReorderer { removeOp.positionStart--; } else if (moveOp.itemCount < removeOp.positionStart + removeOp.itemCount) { // move is removed. - removeOp.itemCount --; + removeOp.itemCount--; moveOp.cmd = REMOVE; moveOp.itemCount = 1; if (removeOp.itemCount == 0) { @@ -157,7 +157,7 @@ class OpReorderer { } private void swapMoveAdd(List list, int move, UpdateOp moveOp, int add, - UpdateOp addOp) { + UpdateOp addOp) { int offset = 0; // going in reverse, first revert the effect of add if (moveOp.itemCount < addOp.positionStart) { @@ -178,7 +178,7 @@ class OpReorderer { } void swapMoveUpdate(List list, int move, UpdateOp moveOp, int update, - UpdateOp updateOp) { + UpdateOp updateOp) { UpdateOp extraUp1 = null; UpdateOp extraUp2 = null; // going in reverse, first revert the effect of add @@ -228,7 +228,7 @@ class OpReorderer { return -1; } - static interface Callback { + interface Callback { UpdateOp obtainUpdateOp(int cmd, int startPosition, int itemCount); diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/PositionMap.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/PositionMap.java index b97bd5a65..15a41191d 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/PositionMap.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/PositionMap.java @@ -456,5 +456,4 @@ class PositionMap implements Cloneable { return ~lo; // value not present } } - } diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java index f6a17a1d8..4aa003c75 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java @@ -18,6 +18,7 @@ package org.telegram.android.support.widget; import android.content.Context; +import android.content.res.TypedArray; import android.database.Observable; import android.graphics.Canvas; import android.graphics.PointF; @@ -30,6 +31,8 @@ import android.support.annotation.Nullable; import android.support.v4.util.ArrayMap; import android.support.v4.view.InputDeviceCompat; import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.NestedScrollingChild; +import android.support.v4.view.NestedScrollingChildHelper; import android.support.v4.view.ScrollingView; import android.support.v4.view.VelocityTrackerCompat; import android.support.v4.view.ViewCompat; @@ -39,9 +42,6 @@ import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.support.v4.view.accessibility.AccessibilityRecordCompat; import android.support.v4.widget.EdgeEffectCompat; import android.support.v4.widget.ScrollerCompat; -import static org.telegram.android.support.widget.AdapterHelper.UpdateOp; -import static org.telegram.android.support.widget.AdapterHelper.Callback; - import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; @@ -58,12 +58,15 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.Interpolator; -import org.telegram.android.AndroidUtilities; - +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static org.telegram.android.support.widget.AdapterHelper.Callback; +import static org.telegram.android.support.widget.AdapterHelper.UpdateOp; + /** * A flexible view for providing a limited window into a large data set. * @@ -128,8 +131,10 @@ import java.util.List; *

* When writing a {@link LayoutManager} you almost always want to use layout positions whereas when * writing an {@link Adapter}, you probably want to use adapter positions. + * + * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_layoutManager */ -public class RecyclerView extends ViewGroup implements ScrollingView { +public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild { private static final String TAG = "RecyclerView"; @@ -221,6 +226,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView { * >Try increasing your pool size and item cache size. */ private static final String TRACE_CREATE_VIEW_TAG = "RV CreateView"; + private static final Class[] LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE = + new Class[]{Context.class, AttributeSet.class, int.class, int.class}; private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver(); @@ -283,6 +290,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { private boolean mAdapterUpdateDuringMeasure; private final boolean mPostUpdatesOnAnimation; private final AccessibilityManager mAccessibilityManager; + private List mOnChildAttachStateListeners; /** * Set to true when an adapter data set changed notification is received. @@ -354,11 +362,17 @@ public class RecyclerView extends ViewGroup implements ScrollingView { new ItemAnimatorRestoreListener(); private boolean mPostedAnimatorRunner = false; private RecyclerViewAccessibilityDelegate mAccessibilityDelegate; + private ChildDrawingOrderCallback mChildDrawingOrderCallback; // simple array to keep min and max child position during a layout calculation // preserved not to create a new one in each layout pass private final int[] mMinMaxLayoutPositions = new int[2]; + private final NestedScrollingChildHelper mScrollingChildHelper; + private final int[] mScrollOffset = new int[2]; + private final int[] mScrollConsumed = new int[2]; + private final int[] mNestedOffsets = new int[2]; + private Runnable mItemAnimatorRunner = new Runnable() { @Override public void run() { @@ -408,6 +422,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView { mAccessibilityManager = (AccessibilityManager) getContext() .getSystemService(Context.ACCESSIBILITY_SERVICE); setAccessibilityDelegateCompat(new RecyclerViewAccessibilityDelegate(this)); + // Create the layoutManager if specified. + + mScrollingChildHelper = new NestedScrollingChildHelper(this); + setNestedScrollingEnabled(true); } /** @@ -428,6 +446,72 @@ public class RecyclerView extends ViewGroup implements ScrollingView { ViewCompat.setAccessibilityDelegate(this, mAccessibilityDelegate); } + /** + * Instantiate and set a LayoutManager, if specified in the attributes. + */ + private void createLayoutManager(Context context, String className, AttributeSet attrs, + int defStyleAttr, int defStyleRes) { + if (className != null) { + className = className.trim(); + if (className.length() != 0) { // Can't use isEmpty since it was added in API 9. + className = getFullClassName(context, className); + try { + ClassLoader classLoader; + if (isInEditMode()) { + // Stupid layoutlib cannot handle simple class loaders. + classLoader = this.getClass().getClassLoader(); + } else { + classLoader = context.getClassLoader(); + } + Class layoutManagerClass = + classLoader.loadClass(className).asSubclass(LayoutManager.class); + Constructor constructor; + Object[] constructorArgs = null; + try { + constructor = layoutManagerClass + .getConstructor(LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE); + constructorArgs = new Object[]{context, attrs, defStyleAttr, defStyleRes}; + } catch (NoSuchMethodException e) { + try { + constructor = layoutManagerClass.getConstructor(); + } catch (NoSuchMethodException e1) { + e1.initCause(e); + throw new IllegalStateException(attrs.getPositionDescription() + + ": Error creating LayoutManager " + className, e1); + } + } + constructor.setAccessible(true); + setLayoutManager(constructor.newInstance(constructorArgs)); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(attrs.getPositionDescription() + + ": Unable to find LayoutManager " + className, e); + } catch (InvocationTargetException e) { + throw new IllegalStateException(attrs.getPositionDescription() + + ": Could not instantiate the LayoutManager: " + className, e); + } catch (InstantiationException e) { + throw new IllegalStateException(attrs.getPositionDescription() + + ": Could not instantiate the LayoutManager: " + className, e); + } catch (IllegalAccessException e) { + throw new IllegalStateException(attrs.getPositionDescription() + + ": Cannot access non-public constructor " + className, e); + } catch (ClassCastException e) { + throw new IllegalStateException(attrs.getPositionDescription() + + ": Class is not a LayoutManager " + className, e); + } + } + } + } + + private String getFullClassName(Context context, String className) { + if (className.charAt(0) == '.') { + return context.getPackageName() + className; + } + if (className.contains("")) { + return className; + } + return RecyclerView.class.getPackage().getName() + '.' + className; + } + private void initChildrenHelper() { mChildHelper = new ChildHelper(new ChildHelper.Callback() { @Override @@ -769,6 +853,46 @@ public class RecyclerView extends ViewGroup implements ScrollingView { } } + /** + * Register a listener that will be notified whenever a child view is attached to or detached + * from RecyclerView. + * + *

This listener will be called when a LayoutManager or the RecyclerView decides + * that a child view is no longer needed. If an application associates expensive + * or heavyweight data with item views, this may be a good place to release + * or free those resources.

+ * + * @param listener Listener to register + */ + public void addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) { + if (mOnChildAttachStateListeners == null) { + mOnChildAttachStateListeners = new ArrayList(); + } + mOnChildAttachStateListeners.add(listener); + } + + /** + * Removes the provided listener from child attached state listeners list. + * + * @param listener Listener to unregister + */ + public void removeOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) { + if (mOnChildAttachStateListeners == null) { + return; + } + mOnChildAttachStateListeners.remove(listener); + } + + /** + * Removes all listeners that were added via + * {@link #addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener)}. + */ + public void clearOnChildAttachStateChangeListeners() { + if (mOnChildAttachStateListeners != null) { + mOnChildAttachStateListeners.clear(); + } + } + /** * Set the {@link LayoutManager} that this RecyclerView will use. * @@ -993,7 +1117,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { public void addItemDecoration(ItemDecoration decor, int index) { if (mLayout != null) { mLayout.assertNotInLayoutOrScroll("Cannot add item decoration during a scroll or" - + " layout"); + + "layout"); } if (mItemDecorations.isEmpty()) { setWillNotDraw(false); @@ -1035,7 +1159,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { public void removeItemDecoration(ItemDecoration decor) { if (mLayout != null) { mLayout.assertNotInLayoutOrScroll("Cannot remove item decoration during a scroll or" - + " layout"); + + "layout"); } mItemDecorations.remove(decor); if (mItemDecorations.isEmpty()) { @@ -1045,6 +1169,26 @@ public class RecyclerView extends ViewGroup implements ScrollingView { requestLayout(); } + /** + * Sets the {@link ChildDrawingOrderCallback} to be used for drawing children. + *

+ * See {@link ViewGroup#getChildDrawingOrder(int, int)} for details. Calling this method will + * always call {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean)}. The parameter will be + * true if childDrawingOrderCallback is not null, false otherwise. + *

+ * Note that child drawing order may be overridden by View's elevation. + * + * @param childDrawingOrderCallback The ChildDrawingOrderCallback to be used by the drawing + * system. + */ + public void setChildDrawingOrderCallback(ChildDrawingOrderCallback childDrawingOrderCallback) { + if (childDrawingOrderCallback == mChildDrawingOrderCallback) { + return; + } + mChildDrawingOrderCallback = childDrawingOrderCallback; + setChildrenDrawingOrderEnabled(mChildDrawingOrderCallback != null); + } + /** * Set a listener that will be notified of any changes in scroll state or position. * @@ -1153,7 +1297,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { final boolean canScrollHorizontal = mLayout.canScrollHorizontally(); final boolean canScrollVertical = mLayout.canScrollVertically(); if (canScrollHorizontal || canScrollVertical) { - scrollByInternal(canScrollHorizontal ? x : 0, canScrollVertical ? y : 0, false, 0, 0); + scrollByInternal(canScrollHorizontal ? x : 0, canScrollVertical ? y : 0, null); } } @@ -1176,29 +1320,25 @@ public class RecyclerView extends ViewGroup implements ScrollingView { * * @param x The amount of horizontal scroll request * @param y The amount of vertical scroll request - * @param fromMotionEvent If request is originated from a MotionEvent, this should be set to - * true and motionX/motionY should be provided, false otherwise. - * @param motionX The x coordinate of the MotionEvent which triggered this scroll. Unused if - * fromMotionEvent is false. - * @param motionY The y coordinate of the MotionEvent which triggered this scroll. Unused if - * fromMotionEvent is false. + * @param ev The originating MotionEvent, or null if not from a touch event. * * @return Whether any scroll was consumed in either direction. */ - boolean scrollByInternal(int x, int y, boolean fromMotionEvent, int motionX, int motionY) { - int overscrollX = 0, overscrollY = 0; - int hresult = 0, vresult = 0; + boolean scrollByInternal(int x, int y, MotionEvent ev) { + int unconsumedX = 0, unconsumedY = 0; + int consumedX = 0, consumedY = 0; + consumePendingUpdateOperations(); if (mAdapter != null) { eatRequestLayout(); onEnterLayoutOrScroll(); if (x != 0) { - hresult = mLayout.scrollHorizontallyBy(x, mRecycler, mState); - overscrollX = x - hresult; + consumedX = mLayout.scrollHorizontallyBy(x, mRecycler, mState); + unconsumedX = x - consumedX; } if (y != 0) { - vresult = mLayout.scrollVerticallyBy(y, mRecycler, mState); - overscrollY = y - vresult; + consumedY = mLayout.scrollVerticallyBy(y, mRecycler, mState); + unconsumedY = y - consumedY; } if (supportsChangeAnimations()) { // Fix up shadow views used by changing animations @@ -1227,19 +1367,27 @@ public class RecyclerView extends ViewGroup implements ScrollingView { if (!mItemDecorations.isEmpty()) { invalidate(); } - if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) { - if (fromMotionEvent) { - pullGlows(motionX, overscrollX, motionY, overscrollY); + + if (dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset)) { + // Update the last touch co-ords, taking any scroll offset into account + mLastTouchX -= mScrollOffset[0]; + mLastTouchY -= mScrollOffset[1]; + ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]); + mNestedOffsets[0] += mScrollOffset[0]; + mNestedOffsets[1] += mScrollOffset[1]; + } else if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) { + if (ev != null) { + pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY); } considerReleasingGlowsOnScroll(x, y); } - if (hresult != 0 || vresult != 0) { - dispatchOnScrolled(hresult, vresult); + if (consumedX != 0 || consumedY != 0) { + dispatchOnScrolled(consumedX, consumedY); } if (!awakenScrollBars()) { invalidate(); } - return hresult != 0 || vresult != 0; + return consumedX != 0 || consumedY != 0; } /** @@ -1432,19 +1580,31 @@ public class RecyclerView extends ViewGroup implements ScrollingView { "Call setLayoutManager with a non-null argument."); return false; } + final boolean canScrollHorizontal = mLayout.canScrollHorizontally(); final boolean canScrollVertical = mLayout.canScrollVertically(); + if (!canScrollHorizontal || Math.abs(velocityX) < mMinFlingVelocity) { velocityX = 0; } if (!canScrollVertical || Math.abs(velocityY) < mMinFlingVelocity) { velocityY = 0; } - velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity)); - velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity)); - if (velocityX != 0 || velocityY != 0) { - mViewFlinger.fling(velocityX, velocityY); - return true; + if (velocityX == 0 && velocityY == 0) { + // If we don't have any velocity, return false + return false; + } + + if (!dispatchNestedPreFling(velocityX, velocityY)) { + final boolean canScroll = canScrollHorizontal || canScrollVertical; + dispatchNestedFling(velocityX, velocityY, canScroll); + + if (canScroll) { + velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity)); + velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity)); + mViewFlinger.fling(velocityX, velocityY); + return true; + } } return false; } @@ -1468,29 +1628,52 @@ public class RecyclerView extends ViewGroup implements ScrollingView { } } + /** + * Returns the minimum velocity to start a fling. + * + * @return The minimum velocity to start a fling + */ + public int getMinFlingVelocity() { + return mMinFlingVelocity; + } + + + /** + * Returns the maximum fling velocity used by this RecyclerView. + * + * @return The maximum fling velocity used by this RecyclerView. + */ + public int getMaxFlingVelocity() { + return mMaxFlingVelocity; + } + /** * Apply a pull to relevant overscroll glow effects */ - private void pullGlows(int x, int overscrollX, int y, int overscrollY) { + private void pullGlows(float x, float overscrollX, float y, float overscrollY) { boolean invalidate = false; if (overscrollX < 0) { ensureLeftGlow(); - invalidate = mLeftGlow.onPull(-overscrollX / (float) getWidth(), - 1f - y / (float) getHeight()) || invalidate; + if (mLeftGlow.onPull(-overscrollX / getWidth(), 1f - y / getHeight())) { + invalidate = true; + } } else if (overscrollX > 0) { ensureRightGlow(); - invalidate = mRightGlow.onPull(overscrollX / (float) getWidth(), - y / (float) getHeight()) || invalidate; + if (mRightGlow.onPull(overscrollX / getWidth(), y / getHeight())) { + invalidate = true; + } } if (overscrollY < 0) { ensureTopGlow(); - invalidate = mTopGlow.onPull(-overscrollY / (float) getHeight(), - x / (float) getWidth()) || invalidate; + if (mTopGlow.onPull(-overscrollY / getHeight(), x / getWidth())) { + invalidate = true; + } } else if (overscrollY > 0) { ensureBottomGlow(); - invalidate = mBottomGlow.onPull(overscrollY / (float) getHeight(), - 1f - x / (float) getWidth()) || invalidate; + if (mBottomGlow.onPull(overscrollY / getHeight(), 1f - x / getWidth())) { + invalidate = true; + } } if (invalidate || overscrollX != 0 || overscrollY != 0) { @@ -1693,6 +1876,14 @@ public class RecyclerView extends ViewGroup implements ScrollingView { removeCallbacks(mItemAnimatorRunner); } + /** + * Returns true if RecyclerView is attached to window. + */ + // @override + public boolean isAttachedToWindow() { + return mIsAttached; + } + /** * Checks if RecyclerView is in the middle of a layout or scroll and throws an * {@link IllegalStateException} if it is not. @@ -1739,6 +1930,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { * for each incoming MotionEvent until the end of the gesture.

* * @param listener Listener to add + * @see SimpleOnItemTouchListener */ public void addOnItemTouchListener(OnItemTouchListener listener) { mOnItemTouchListeners.add(listener); @@ -1832,6 +2024,15 @@ public class RecyclerView extends ViewGroup implements ScrollingView { getParent().requestDisallowInterceptTouchEvent(true); setScrollState(SCROLL_STATE_DRAGGING); } + + int nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE; + if (canScrollHorizontally) { + nestedScrollAxis |= ViewCompat.SCROLL_AXIS_HORIZONTAL; + } + if (canScrollVertically) { + nestedScrollAxis |= ViewCompat.SCROLL_AXIS_VERTICAL; + } + startNestedScroll(nestedScrollAxis); break; case MotionEventCompat.ACTION_POINTER_DOWN: @@ -1874,6 +2075,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { case MotionEvent.ACTION_UP: { mVelocityTracker.clear(); + stopNestedScroll(); } break; case MotionEvent.ACTION_CANCEL: { @@ -1883,6 +2085,16 @@ public class RecyclerView extends ViewGroup implements ScrollingView { return mScrollState == SCROLL_STATE_DRAGGING; } + @Override + public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { + final int listenerCount = mOnItemTouchListeners.size(); + for (int i = 0; i < listenerCount; i++) { + final OnItemTouchListener listener = mOnItemTouchListeners.get(i); + listener.onRequestDisallowInterceptTouchEvent(disallowIntercept); + } + super.requestDisallowInterceptTouchEvent(disallowIntercept); + } + @Override public boolean onTouchEvent(MotionEvent e) { if (dispatchOnItemTouch(e)) { @@ -1898,14 +2110,29 @@ public class RecyclerView extends ViewGroup implements ScrollingView { } mVelocityTracker.addMovement(e); + final MotionEvent vtev = MotionEvent.obtain(e); final int action = MotionEventCompat.getActionMasked(e); final int actionIndex = MotionEventCompat.getActionIndex(e); + if (action == MotionEvent.ACTION_DOWN) { + mNestedOffsets[0] = mNestedOffsets[1] = 0; + } + vtev.offsetLocation(mNestedOffsets[0], mNestedOffsets[1]); + switch (action) { case MotionEvent.ACTION_DOWN: { mScrollPointerId = MotionEventCompat.getPointerId(e, 0); mInitialTouchX = mLastTouchX = (int) (e.getX() + 0.5f); mInitialTouchY = mLastTouchY = (int) (e.getY() + 0.5f); + + int nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE; + if (canScrollHorizontally) { + nestedScrollAxis |= ViewCompat.SCROLL_AXIS_HORIZONTAL; + } + if (canScrollVertically) { + nestedScrollAxis |= ViewCompat.SCROLL_AXIS_VERTICAL; + } + startNestedScroll(nestedScrollAxis); } break; case MotionEventCompat.ACTION_POINTER_DOWN: { @@ -1924,32 +2151,52 @@ public class RecyclerView extends ViewGroup implements ScrollingView { final int x = (int) (MotionEventCompat.getX(e, index) + 0.5f); final int y = (int) (MotionEventCompat.getY(e, index) + 0.5f); + int dx = mLastTouchX - x; + int dy = mLastTouchY - y; + + if (dispatchNestedPreScroll(dx, dy, mScrollConsumed, mScrollOffset)) { + dx -= mScrollConsumed[0]; + dy -= mScrollConsumed[1]; + vtev.offsetLocation(mScrollOffset[0], mScrollOffset[1]); + // Updated the nested offsets + mNestedOffsets[0] += mScrollOffset[0]; + mNestedOffsets[1] += mScrollOffset[1]; + } + if (mScrollState != SCROLL_STATE_DRAGGING) { - final int dx = x - mInitialTouchX; - final int dy = y - mInitialTouchY; boolean startScroll = false; if (canScrollHorizontally && Math.abs(dx) > mTouchSlop) { - mLastTouchX = mInitialTouchX + mTouchSlop * (dx < 0 ? -1 : 1); + if (dx > 0) { + dx -= mTouchSlop; + } else { + dx += mTouchSlop; + } startScroll = true; } if (canScrollVertically && Math.abs(dy) > mTouchSlop) { - mLastTouchY = mInitialTouchY + mTouchSlop * (dy < 0 ? -1 : 1); + if (dy > 0) { + dy -= mTouchSlop; + } else { + dy += mTouchSlop; + } startScroll = true; } if (startScroll) { setScrollState(SCROLL_STATE_DRAGGING); } } + if (mScrollState == SCROLL_STATE_DRAGGING) { - final int dx = x - mLastTouchX; - final int dy = y - mLastTouchY; - if (scrollByInternal(canScrollHorizontally ? -dx : 0, - canScrollVertically ? -dy : 0, true, x, y)) { + mLastTouchX = x - mScrollOffset[0]; + mLastTouchY = y - mScrollOffset[1]; + + if (scrollByInternal( + canScrollHorizontally ? dx : 0, + canScrollVertically ? dy : 0, + vtev)) { getParent().requestDisallowInterceptTouchEvent(true); } } - mLastTouchX = x; - mLastTouchY = y; } break; case MotionEventCompat.ACTION_POINTER_UP: { @@ -1965,6 +2212,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) { setScrollState(SCROLL_STATE_IDLE); } + mVelocityTracker.clear(); releaseGlows(); } break; @@ -1974,6 +2222,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView { } break; } + vtev.recycle(); + return true; } @@ -1981,6 +2231,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { if (mVelocityTracker != null) { mVelocityTracker.clear(); } + stopNestedScroll(); releaseGlows(); setScrollState(SCROLL_STATE_IDLE); } @@ -2823,6 +3074,18 @@ public class RecyclerView extends ViewGroup implements ScrollingView { return mLayout.generateLayoutParams(p); } + /** + * Returns true if RecyclerView is currently running some animations. + *

+ * If you want to be notified when animations are finished, use + * {@link ItemAnimator#isRunning(ItemAnimator.ItemAnimatorFinishedListener)}. + * + * @return True if there are some item animations currently running or waiting to be started. + */ + public boolean isAnimating() { + return mItemAnimator != null && mItemAnimator.isRunning(); + } + void saveOldPositions() { final int childCount = mChildHelper.getUnfilteredChildCount(); for (int i = 0; i < childCount; i++) { @@ -3232,6 +3495,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView { return null; } + @Override + public boolean drawChild(Canvas canvas, View child, long drawingTime) { + return super.drawChild(canvas, child, drawingTime); + } + /** * Offset the bounds of all child views by dy pixels. * Useful for implementing simple scrolling in {@link LayoutManager LayoutManagers}. @@ -5153,17 +5421,32 @@ public class RecyclerView extends ViewGroup implements ScrollingView { } private void dispatchChildDetached(View child) { - if (mAdapter != null) { - mAdapter.onViewDetachedFromWindow(getChildViewHolderInt(child)); - } + final ViewHolder viewHolder = getChildViewHolderInt(child); onChildDetachedFromWindow(child); + if (mAdapter != null && viewHolder != null) { + mAdapter.onViewDetachedFromWindow(viewHolder); + } + if (mOnChildAttachStateListeners != null) { + final int cnt = mOnChildAttachStateListeners.size(); + for (int i = cnt - 1; i >= 0; i--) { + mOnChildAttachStateListeners.get(i).onChildViewDetachedFromWindow(child); + } + } } private void dispatchChildAttached(View child) { - if (mAdapter != null) { - mAdapter.onViewAttachedToWindow(getChildViewHolderInt(child)); - } + final ViewHolder viewHolder = getChildViewHolderInt(child); onChildAttachedToWindow(child); + if (mAdapter != null && viewHolder != null) { + mAdapter.onViewAttachedToWindow(viewHolder); + } + if (mOnChildAttachStateListeners != null) { + final int cnt = mOnChildAttachStateListeners.size(); + for (int i = cnt - 1; i >= 0; i--) { + mOnChildAttachStateListeners.get(i).onChildViewAttachedToWindow(child); + } + } + } /** @@ -5173,6 +5456,14 @@ public class RecyclerView extends ViewGroup implements ScrollingView { * a RecyclerView can be used to implement a standard vertically scrolling list, * a uniform grid, staggered grids, horizontally scrolling collections and more. Several stock * layout managers are provided for general use. + *

+ * If the LayoutManager specifies a default constructor or one with the signature + * ({@link Context}, {@link AttributeSet}, {@code int}, {@code int}), RecyclerView will + * instantiate and set the LayoutManager when being inflated. Most used properties can + * be then obtained from {@link #getProperties(Context, AttributeSet, int, int)}. In case + * a LayoutManager specifies both constructors, the non-default constructor will take + * precedence. + * */ public static abstract class LayoutManager { ChildHelper mChildHelper; @@ -7259,6 +7550,20 @@ public class RecyclerView extends ViewGroup implements ScrollingView { int action, Bundle args) { return false; } + + /** + * Some general properties that a LayoutManager may want to use. + */ + public static class Properties { + /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation */ + public int orientation; + /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_spanCount */ + public int spanCount; + /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout */ + public boolean reverseLayout; + /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd */ + public boolean stackFromEnd; + } } /** @@ -7359,8 +7664,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView { * manipulation of item views within the RecyclerView. OnItemTouchListeners may intercept * a touch interaction already in progress even if the RecyclerView is already handling that * gesture stream itself for the purposes of scrolling.

+ * + * @see SimpleOnItemTouchListener */ - public interface OnItemTouchListener { + public static interface OnItemTouchListener { /** * Silently observe and/or take over touch events sent to the RecyclerView * before they are handled by either the RecyclerView itself or its child views. @@ -7385,8 +7692,44 @@ public class RecyclerView extends ViewGroup implements ScrollingView { * the RecyclerView's coordinate system. */ public void onTouchEvent(RecyclerView rv, MotionEvent e); + + /** + * Called when a child of RecyclerView does not want RecyclerView and its ancestors to + * intercept touch events with + * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}. + * + * @param disallowIntercept True if the child does not want the parent to + * intercept touch events. + * @see ViewParent#requestDisallowInterceptTouchEvent(boolean) + */ + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept); } + /** + * An implementation of {@link RecyclerView.OnItemTouchListener} that has empty method bodies and + * default return values. + *

+ * You may prefer to extend this class if you don't need to override all methods. Another + * benefit of using this class is future compatibility. As the interface may change, we'll + * always provide a default implementation on this class so that your code won't break when + * you update to a new version of the support library. + */ + public class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener { + @Override + public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { + return false; + } + + @Override + public void onTouchEvent(RecyclerView rv, MotionEvent e) { + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + } + } + + /** * An OnScrollListener can be set on a RecyclerView to receive messages * when a scrolling event has occurred on that RecyclerView. @@ -7399,7 +7742,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView { * want your components to be able to easily replace the listener use * RecyclerView#setOnScrollListener. */ - abstract static public class OnScrollListener { + public abstract static class OnScrollListener { /** * Callback method to be invoked when RecyclerView's scroll state changes. * @@ -7444,6 +7787,27 @@ public class RecyclerView extends ViewGroup implements ScrollingView { public void onViewRecycled(ViewHolder holder); } + /** + * A Listener interface that can be attached to a RecylcerView to get notified + * whenever a ViewHolder is attached to or detached from RecyclerView. + */ + public interface OnChildAttachStateChangeListener { + + /** + * Called when a view is attached to the RecyclerView. + * + * @param view The View which is attached to the RecyclerView + */ + public void onChildViewAttachedToWindow(View view); + + /** + * Called when a view is detached from RecyclerView. + * + * @param view The View which is being detached from the RecyclerView + */ + public void onChildViewDetachedFromWindow(View view); + } + /** * A ViewHolder describes an item view and metadata about its place within the RecyclerView. * @@ -7862,6 +8226,55 @@ public class RecyclerView extends ViewGroup implements ScrollingView { return mAdapterHelper.applyPendingUpdatesToPosition(viewHolder.mPosition); } + // NestedScrollingChild + + @Override + public void setNestedScrollingEnabled(boolean enabled) { + mScrollingChildHelper.setNestedScrollingEnabled(enabled); + } + + @Override + public boolean isNestedScrollingEnabled() { + return mScrollingChildHelper.isNestedScrollingEnabled(); + } + + @Override + public boolean startNestedScroll(int axes) { + return mScrollingChildHelper.startNestedScroll(axes); + } + + @Override + public void stopNestedScroll() { + mScrollingChildHelper.stopNestedScroll(); + } + + @Override + public boolean hasNestedScrollingParent() { + return mScrollingChildHelper.hasNestedScrollingParent(); + } + + @Override + public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, + int dyUnconsumed, int[] offsetInWindow) { + return mScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, + dxUnconsumed, dyUnconsumed, offsetInWindow); + } + + @Override + public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) { + return mScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); + } + + @Override + public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { + return mScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); + } + + @Override + public boolean dispatchNestedPreFling(float velocityX, float velocityY) { + return mScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY); + } + /** * {@link android.view.ViewGroup.MarginLayoutParams LayoutParams} subclass for children of * {@link RecyclerView}. Custom {@link LayoutManager layout managers} are encouraged @@ -9318,4 +9731,35 @@ public class RecyclerView extends ViewGroup implements ScrollingView { this.bottom = bottom; } } + + @Override + protected int getChildDrawingOrder(int childCount, int i) { + if (mChildDrawingOrderCallback == null) { + return super.getChildDrawingOrder(childCount, i); + } else { + return mChildDrawingOrderCallback.onGetChildDrawingOrder(childCount, i); + } + } + + /** + * A callback interface that can be used to alter the drawing order of RecyclerView children. + *

+ * It works using the {@link ViewGroup#getChildDrawingOrder(int, int)} method, so any case + * that applies to that method also applies to this callback. For example, changing the drawing + * order of two views will not have any effect if their elevation values are different since + * elevation overrides the result of this callback. + */ + public static interface ChildDrawingOrderCallback { + /** + * Returns the index of the child to draw for this iteration. Override this + * if you want to change the drawing order of children. By default, it + * returns i. + * + * @param i The current iteration. + * @return The index of the child to draw this iteration. + * + * @see RecyclerView#setChildDrawingOrderCallback(RecyclerView.ChildDrawingOrderCallback) + */ + public int onGetChildDrawingOrder(int childCount, int i); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/StaggeredGridLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/StaggeredGridLayoutManager.java index d28434a60..166311dab 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/StaggeredGridLayoutManager.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/StaggeredGridLayoutManager.java @@ -537,7 +537,6 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { ensureOrientationHelper(); - final AnchorInfo anchorInfo = mAnchorInfo; anchorInfo.reset(); @@ -577,21 +576,22 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { detachAndScrapAttachedViews(recycler); mLaidOutInvalidFullSpan = false; updateMeasureSpecs(); + updateLayoutState(anchorInfo.mPosition, state); if (anchorInfo.mLayoutFromEnd) { // Layout start. - updateLayoutStateToFillStart(anchorInfo.mPosition, state); + setLayoutStateDirection(LAYOUT_START); fill(recycler, mLayoutState, state); // Layout end. - updateLayoutStateToFillEnd(anchorInfo.mPosition, state); - mLayoutState.mCurrentPosition += mLayoutState.mItemDirection; + setLayoutStateDirection(LAYOUT_END); + mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection; fill(recycler, mLayoutState, state); } else { // Layout end. - updateLayoutStateToFillEnd(anchorInfo.mPosition, state); + setLayoutStateDirection(LAYOUT_END); fill(recycler, mLayoutState, state); // Layout start. - updateLayoutStateToFillStart(anchorInfo.mPosition, state); - mLayoutState.mCurrentPosition += mLayoutState.mItemDirection; + setLayoutStateDirection(LAYOUT_START); + mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection; fill(recycler, mLayoutState, state); } @@ -1254,40 +1254,37 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { } } - private void updateLayoutStateToFillStart(int anchorPosition, RecyclerView.State state) { + private void updateLayoutState(int anchorPosition, RecyclerView.State state) { mLayoutState.mAvailable = 0; mLayoutState.mCurrentPosition = anchorPosition; + int startExtra = 0; + int endExtra = 0; if (isSmoothScrolling()) { final int targetPos = state.getTargetScrollPosition(); - if (mShouldReverseLayout == targetPos < anchorPosition) { - mLayoutState.mExtra = 0; - } else { - mLayoutState.mExtra = mPrimaryOrientation.getTotalSpace(); + if (targetPos != NO_POSITION) { + if (mShouldReverseLayout == targetPos < anchorPosition) { + endExtra = mPrimaryOrientation.getTotalSpace(); + } else { + startExtra = mPrimaryOrientation.getTotalSpace(); + } } - } else { - mLayoutState.mExtra = 0; } - mLayoutState.mLayoutDirection = LAYOUT_START; - mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_TAIL - : ITEM_DIRECTION_HEAD; + + // Line of the furthest row. + final boolean clipToPadding = getClipToPadding(); + if (clipToPadding) { + mLayoutState.mStartLine = mPrimaryOrientation.getStartAfterPadding() - startExtra; + mLayoutState.mEndLine = mPrimaryOrientation.getEndAfterPadding() + endExtra; + } else { + mLayoutState.mEndLine = mPrimaryOrientation.getEnd() + endExtra; + mLayoutState.mStartLine = -startExtra; + } } - private void updateLayoutStateToFillEnd(int anchorPosition, RecyclerView.State state) { - mLayoutState.mAvailable = 0; - mLayoutState.mCurrentPosition = anchorPosition; - if (isSmoothScrolling()) { - final int targetPos = state.getTargetScrollPosition(); - if (mShouldReverseLayout == targetPos > anchorPosition) { - mLayoutState.mExtra = 0; - } else { - mLayoutState.mExtra = mPrimaryOrientation.getTotalSpace(); - } - } else { - mLayoutState.mExtra = 0; - } - mLayoutState.mLayoutDirection = LAYOUT_END; - mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_HEAD - : ITEM_DIRECTION_TAIL; + private void setLayoutStateDirection(int direction) { + mLayoutState.mLayoutDirection = direction; + mLayoutState.mItemDirection = (mShouldReverseLayout == (direction == LAYOUT_START)) ? + ITEM_DIRECTION_TAIL : ITEM_DIRECTION_HEAD; } @Override @@ -1383,31 +1380,25 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { mRemainingSpans.set(0, mSpanCount, true); // The target position we are trying to reach. final int targetLine; - /* - * The line until which we can recycle, as long as we add views. - * Keep in mind, it is still the line in layout direction which means; to calculate the - * actual recycle line, we should subtract/add the size in orientation. - */ - final int recycleLine; + // Line of the furthest row. if (layoutState.mLayoutDirection == LAYOUT_END) { - // ignore padding for recycler - recycleLine = mPrimaryOrientation.getEndAfterPadding() + mLayoutState.mAvailable; - targetLine = recycleLine + mLayoutState.mExtra + mPrimaryOrientation.getEndPadding(); - + targetLine = layoutState.mEndLine + layoutState.mAvailable; } else { // LAYOUT_START - // ignore padding for recycler - recycleLine = mPrimaryOrientation.getStartAfterPadding() - mLayoutState.mAvailable; - targetLine = recycleLine - mLayoutState.mExtra - - mPrimaryOrientation.getStartAfterPadding(); + targetLine = layoutState.mStartLine - layoutState.mAvailable; } + updateAllRemainingSpans(layoutState.mLayoutDirection, targetLine); + if (DEBUG) { + Log.d(TAG, "FILLING targetLine: " + targetLine + "," + + "remaining spans:" + mRemainingSpans + ", state: " + layoutState); + } // the default coordinate to add new view. final int defaultNewViewLine = mShouldReverseLayout ? mPrimaryOrientation.getEndAfterPadding() : mPrimaryOrientation.getStartAfterPadding(); - + boolean added = false; while (layoutState.hasMore(state) && !mRemainingSpans.isEmpty()) { View view = layoutState.next(recycler); LayoutParams lp = ((LayoutParams) view.getLayoutParams()); @@ -1500,18 +1491,21 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { } else { updateRemainingSpans(currentSpan, mLayoutState.mLayoutDirection, targetLine); } - recycle(recycler, mLayoutState, currentSpan, recycleLine); + recycle(recycler, mLayoutState); + added = true; } - if (DEBUG) { - Log.d(TAG, "fill, " + getChildCount()); + if (!added) { + recycle(recycler, mLayoutState); } + final int diff; if (mLayoutState.mLayoutDirection == LAYOUT_START) { final int minStart = getMinStart(mPrimaryOrientation.getStartAfterPadding()); - return Math.max(0, mLayoutState.mAvailable + (recycleLine - minStart)); + diff = mPrimaryOrientation.getStartAfterPadding() - minStart; } else { - final int max = getMaxEnd(mPrimaryOrientation.getEndAfterPadding()); - return Math.max(0, mLayoutState.mAvailable + (max - recycleLine)); + final int maxEnd = getMaxEnd(mPrimaryOrientation.getEndAfterPadding()); + diff = maxEnd - mPrimaryOrientation.getEndAfterPadding(); } + return diff > 0 ? Math.min(layoutState.mAvailable, diff) : 0; } private LazySpanLookup.FullSpanItem createFullSpanItemFromEnd(int newItemTop) { @@ -1548,19 +1542,40 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { } } - private void recycle(RecyclerView.Recycler recycler, LayoutState layoutState, - Span updatedSpan, int recycleLine) { - if (layoutState.mLayoutDirection == LAYOUT_START) { - // calculate recycle line - int maxStart = getMaxStart(updatedSpan.getStartLine()); - recycleFromEnd(recycler, Math.max(recycleLine, maxStart) + - (mPrimaryOrientation.getEnd() - mPrimaryOrientation.getStartAfterPadding())); + private void recycle(RecyclerView.Recycler recycler, LayoutState layoutState) { + if (layoutState.mAvailable == 0) { + // easy, recycle line is still valid + if (layoutState.mLayoutDirection == LAYOUT_START) { + recycleFromEnd(recycler, layoutState.mEndLine); + } else { + recycleFromStart(recycler, layoutState.mStartLine); + } } else { - // calculate recycle line - int minEnd = getMinEnd(updatedSpan.getEndLine()); - recycleFromStart(recycler, Math.min(recycleLine, minEnd) - - (mPrimaryOrientation.getEnd() - mPrimaryOrientation.getStartAfterPadding())); + // scrolling case, recycle line can be shifted by how much space we could cover + // by adding new views + if (layoutState.mLayoutDirection == LAYOUT_START) { + // calculate recycle line + int scrolled = layoutState.mStartLine - getMaxStart(layoutState.mStartLine); + final int line; + if (scrolled < 0) { + line = layoutState.mEndLine; + } else { + line = layoutState.mEndLine - Math.min(scrolled, layoutState.mAvailable); + } + recycleFromEnd(recycler, line); + } else { + // calculate recycle line + int scrolled = getMinEnd(layoutState.mEndLine) - layoutState.mEndLine; + final int line; + if (scrolled < 0) { + line = layoutState.mStartLine; + } else { + line = layoutState.mStartLine + Math.min(scrolled, layoutState.mAvailable); + } + recycleFromStart(recycler, line); + } } + } private void appendViewToAllSpans(View view) { @@ -1602,12 +1617,12 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { final int deletedSize = span.getDeletedSize(); if (layoutDir == LAYOUT_START) { final int line = span.getStartLine(); - if (line + deletedSize < targetLine) { + if (line + deletedSize <= targetLine) { mRemainingSpans.set(span.mIndex, false); } } else { final int line = span.getEndLine(); - if (line - deletedSize > targetLine) { + if (line - deletedSize >= targetLine) { mRemainingSpans.set(span.mIndex, false); } } @@ -1678,18 +1693,24 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { } private void recycleFromStart(RecyclerView.Recycler recycler, int line) { - if (DEBUG) { - Log.d(TAG, "recycling from start for line " + line); - } while (getChildCount() > 0) { View child = getChildAt(0); - if (mPrimaryOrientation.getDecoratedEnd(child) < line) { + if (mPrimaryOrientation.getDecoratedEnd(child) <= line) { LayoutParams lp = (LayoutParams) child.getLayoutParams(); + // Don't recycle the last View in a span not to lose span's start/end lines if (lp.mFullSpan) { + for (int j = 0; j < mSpanCount; j++) { + if (mSpans[j].mViews.size() == 1) { + return; + } + } for (int j = 0; j < mSpanCount; j++) { mSpans[j].popStart(); } } else { + if (lp.mSpan.mViews.size() == 1) { + return; + } lp.mSpan.popStart(); } removeAndRecycleView(child, recycler); @@ -1704,13 +1725,22 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { int i; for (i = childCount - 1; i >= 0; i--) { View child = getChildAt(i); - if (mPrimaryOrientation.getDecoratedStart(child) > line) { + if (mPrimaryOrientation.getDecoratedStart(child) >= line) { LayoutParams lp = (LayoutParams) child.getLayoutParams(); + // Don't recycle the last View in a span not to lose span's start/end lines if (lp.mFullSpan) { + for (int j = 0; j < mSpanCount; j++) { + if (mSpans[j].mViews.size() == 1) { + return; + } + } for (int j = 0; j < mSpanCount; j++) { mSpans[j].popEnd(); } } else { + if (lp.mSpan.mViews.size() == 1) { + return; + } lp.mSpan.popEnd(); } removeAndRecycleView(child, recycler); @@ -1860,21 +1890,19 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager { int scrollBy(int dt, RecyclerView.Recycler recycler, RecyclerView.State state) { ensureOrientationHelper(); final int referenceChildPosition; + final int layoutDir; if (dt > 0) { // layout towards end - mLayoutState.mLayoutDirection = LAYOUT_END; - mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_HEAD - : ITEM_DIRECTION_TAIL; + layoutDir = LAYOUT_END; referenceChildPosition = getLastChildPosition(); } else { - mLayoutState.mLayoutDirection = LAYOUT_START; - mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_TAIL - : ITEM_DIRECTION_HEAD; + layoutDir = LAYOUT_START; referenceChildPosition = getFirstChildPosition(); } + updateLayoutState(referenceChildPosition, state); + setLayoutStateDirection(layoutDir); mLayoutState.mCurrentPosition = referenceChildPosition + mLayoutState.mItemDirection; final int absDt = Math.abs(dt); mLayoutState.mAvailable = absDt; - mLayoutState.mExtra = isSmoothScrolling() ? mPrimaryOrientation.getTotalSpace() : 0; int consumed = fill(recycler, mLayoutState, state); final int totalScroll; if (absDt < consumed) { diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchHelper.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchHelper.java new file mode 100644 index 000000000..c3ab9bd3c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchHelper.java @@ -0,0 +1,2331 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.telegram.android.support.widget.helper; + +import android.graphics.Canvas; +import android.graphics.Rect; +import android.os.Build; +import android.support.v4.animation.ValueAnimatorCompat; +import android.support.v4.animation.AnimatorCompatHelper; +import android.support.v4.animation.AnimatorListenerCompat; +import android.support.v4.animation.AnimatorUpdateListenerCompat; +import android.support.v4.view.GestureDetectorCompat; +import android.support.v4.view.MotionEventCompat; +import android.support.v4.view.VelocityTrackerCompat; +import android.support.v4.view.ViewCompat; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.support.widget.LinearLayoutManager; +import org.telegram.android.support.widget.RecyclerView; +import android.util.Log; +import android.util.TypedValue; +import android.view.GestureDetector; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewParent; + +import java.util.ArrayList; +import java.util.List; + +import org.telegram.android.support.widget.RecyclerView.OnItemTouchListener; +import org.telegram.android.support.widget.RecyclerView.ViewHolder; +import android.view.animation.Interpolator; + +/** + * This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView. + *

+ * It works with a RecyclerView and a Callback class, which configures what type of interactions + * are enabled and also receives events when user performs these actions. + *

+ * Depending on which functionality you support, you should override + * {@link Callback#onMove(RecyclerView, ViewHolder, ViewHolder)} and / or + * {@link Callback#onSwiped(ViewHolder, int)}. + *

+ * This class is designed to work with any LayoutManager but for certain situations, it can be + * optimized for your custom LayoutManager by extending methods in the + * {@link ItemTouchHelper.Callback} class or implementing {@link ItemTouchHelper.ViewDropHandler} + * interface in your LayoutManager. + *

+ * By default, ItemTouchHelper moves the items' translateX/Y properties to reposition them. On + * platforms older than Honeycomb, ItemTouchHelper uses canvas translations and View's visibility + * property to move items in response to touch events. You can customize these behaviors by + * overriding {@link Callback#onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int, + * boolean)} + * or {@link Callback#onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, + * boolean)}. + *

+ * Most of the time, you only need to override onChildDraw but due to limitations of + * platform prior to Honeycomb, you may need to implement onChildDrawOver as well. + */ +public class ItemTouchHelper extends RecyclerView.ItemDecoration + implements RecyclerView.OnChildAttachStateChangeListener { + + /** + * Up direction, used for swipe & drag control. + */ + public static final int UP = 1; + + /** + * Down direction, used for swipe & drag control. + */ + public static final int DOWN = 1 << 1; + + /** + * Left direction, used for swipe & drag control. + */ + public static final int LEFT = 1 << 2; + + /** + * Right direction, used for swipe & drag control. + */ + public static final int RIGHT = 1 << 3; + + // If you change these relative direction values, update Callback#convertToAbsoluteDirection, + // Callback#convertToRelativeDirection. + /** + * Horizontal start direction. Resolved to LEFT or RIGHT depending on RecyclerView's layout + * direction. Used for swipe & drag control. + */ + public static final int START = LEFT << 2; + + /** + * Horizontal end direction. Resolved to LEFT or RIGHT depending on RecyclerView's layout + * direction. Used for swipe & drag control. + */ + public static final int END = RIGHT << 2; + + /** + * ItemTouchHelper is in idle state. At this state, either there is no related motion event by + * the user or latest motion events have not yet triggered a swipe or drag. + */ + public static final int ACTION_STATE_IDLE = 0; + + /** + * A View is currently being swiped. + */ + public static final int ACTION_STATE_SWIPE = 1; + + /** + * A View is currently being dragged. + */ + public static final int ACTION_STATE_DRAG = 2; + + /** + * Animation type for views which are swiped successfully. + */ + public static final int ANIMATION_TYPE_SWIPE_SUCCESS = 1 << 1; + + /** + * Animation type for views which are not completely swiped thus will animate back to their + * original position. + */ + public static final int ANIMATION_TYPE_SWIPE_CANCEL = 1 << 2; + + /** + * Animation type for views that were dragged and now will animate to their final position. + */ + public static final int ANIMATION_TYPE_DRAG = 1 << 3; + + private static final String TAG = "ItemTouchHelper"; + + private static final boolean DEBUG = false; + + private static final int ACTIVE_POINTER_ID_NONE = -1; + + private static final int DIRECTION_FLAG_COUNT = 8; + + private static final int ACTION_MODE_IDLE_MASK = (1 << DIRECTION_FLAG_COUNT) - 1; + + private static final int ACTION_MODE_SWIPE_MASK = ACTION_MODE_IDLE_MASK << DIRECTION_FLAG_COUNT; + + private static final int ACTION_MODE_DRAG_MASK = ACTION_MODE_SWIPE_MASK << DIRECTION_FLAG_COUNT; + + /** + * Views, whose state should be cleared after they are detached from RecyclerView. + * This is necessary after swipe dismissing an item. We wait until animator finishes its job + * to clean these views. + */ + final List mPendingCleanup = new ArrayList(); + + /** + * Re-use array to calculate dx dy for a ViewHolder + */ + private final float[] mTmpPosition = new float[2]; + + /** + * Currently selected view holder + */ + ViewHolder mSelected = null; + + /** + * The reference coordinates for the action start. For drag & drop, this is the time long + * press is completed vs for swipe, this is the initial touch point. + */ + float mInitialTouchX; + + float mInitialTouchY; + + /** + * The diff between the last event and initial touch. + */ + float mDx; + + float mDy; + + /** + * The coordinates of the selected view at the time it is selected. We record these values + * when action starts so that we can consistently position it even if LayoutManager moves the + * View. + */ + float mSelectedStartX; + + float mSelectedStartY; + + /** + * The pointer we are tracking. + */ + int mActivePointerId = ACTIVE_POINTER_ID_NONE; + + /** + * Developer callback which controls the behavior of ItemTouchHelper. + */ + Callback mCallback; + + /** + * Current mode. + */ + int mActionState = ACTION_STATE_IDLE; + + /** + * The direction flags obtained from unmasking + * {@link Callback#getAbsoluteMovementFlags(RecyclerView, ViewHolder)} for the current + * action state. + */ + int mSelectedFlags; + + /** + * When a View is dragged or swiped and needs to go back to where it was, we create a Recover + * Animation and animate it to its location using this custom Animator, instead of using + * framework Animators. + * Using framework animators has the side effect of clashing with ItemAnimator, creating + * jumpy UIs. + */ + List mRecoverAnimations = new ArrayList(); + + private int mSlop; + + private RecyclerView mRecyclerView; + + /** + * When user drags a view to the edge, we start scrolling the LayoutManager as long as View + * is partially out of bounds. + */ + private final Runnable mScrollRunnable = new Runnable() { + @Override + public void run() { + if (mSelected != null && scrollIfNecessary()) { + if (mSelected != null) { //it might be lost during scrolling + moveIfNecessary(mSelected); + } + mRecyclerView.removeCallbacks(mScrollRunnable); + ViewCompat.postOnAnimation(mRecyclerView, this); + } + } + }; + + /** + * Used for detecting fling swipe + */ + private VelocityTracker mVelocityTracker; + + //re-used list for selecting a swap target + private List mSwapTargets; + + //re used for for sorting swap targets + private List mDistances; + + /** + * If drag & drop is supported, we use child drawing order to bring them to front. + */ + private RecyclerView.ChildDrawingOrderCallback mChildDrawingOrderCallback = null; + + /** + * This keeps a reference to the child dragged by the user. Even after user stops dragging, + * until view reaches its final position (end of recover animation), we keep a reference so + * that it can be drawn above other children. + */ + private View mOverdrawChild = null; + + /** + * We cache the position of the overdraw child to avoid recalculating it each time child + * position callback is called. This value is invalidated whenever a child is attached or + * detached. + */ + private int mOverdrawChildPosition = -1; + + /** + * Used to detect long press. + */ + private GestureDetectorCompat mGestureDetector; + + private final OnItemTouchListener mOnItemTouchListener + = new OnItemTouchListener() { + @Override + public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent event) { + mGestureDetector.onTouchEvent(event); + if (DEBUG) { + Log.d(TAG, "intercept: x:" + event.getX() + ",y:" + event.getY() + ", " + event); + } + final int action = MotionEventCompat.getActionMasked(event); + if (action == MotionEvent.ACTION_DOWN) { + mActivePointerId = MotionEventCompat.getPointerId(event, 0); + mInitialTouchX = event.getX(); + mInitialTouchY = event.getY(); + obtainVelocityTracker(); + if (mSelected == null) { + final RecoverAnimation animation = findAnimation(event); + if (animation != null) { + mInitialTouchX -= animation.mX; + mInitialTouchY -= animation.mY; + endRecoverAnimation(animation.mViewHolder, true); + if (mPendingCleanup.remove(animation.mViewHolder.itemView)) { + mCallback.clearView(mRecyclerView, animation.mViewHolder); + } + select(animation.mViewHolder, animation.mActionState); + updateDxDy(event, mSelectedFlags, 0); + } + } + } else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) { + mActivePointerId = ACTIVE_POINTER_ID_NONE; + select(null, ACTION_STATE_IDLE); + } else if (mActivePointerId != ACTIVE_POINTER_ID_NONE) { + // in a non scroll orientation, if distance change is above threshold, we + // can select the item + final int index = MotionEventCompat.findPointerIndex(event, mActivePointerId); + if (DEBUG) { + Log.d(TAG, "pointer index " + index); + } + if (index >= 0) { + checkSelectForSwipe(action, event, index); + } + } + if (mVelocityTracker != null) { + mVelocityTracker.addMovement(event); + } + return mSelected != null; + } + + @Override + public void onTouchEvent(RecyclerView recyclerView, MotionEvent event) { + mGestureDetector.onTouchEvent(event); + if (DEBUG) { + Log.d(TAG, + "on touch: x:" + mInitialTouchX + ",y:" + mInitialTouchY + ", :" + event); + } + if (mVelocityTracker != null) { + mVelocityTracker.addMovement(event); + } + if (mActivePointerId == ACTIVE_POINTER_ID_NONE) { + return; + } + final int action = MotionEventCompat.getActionMasked(event); + final int activePointerIndex = MotionEventCompat + .findPointerIndex(event, mActivePointerId); + if (activePointerIndex >= 0) { + checkSelectForSwipe(action, event, activePointerIndex); + } + ViewHolder viewHolder = mSelected; + if (viewHolder == null) { + return; + } + switch (action) { + case MotionEvent.ACTION_MOVE: { + // Find the index of the active pointer and fetch its position + if (activePointerIndex >= 0) { + updateDxDy(event, mSelectedFlags, activePointerIndex); + moveIfNecessary(viewHolder); + mRecyclerView.removeCallbacks(mScrollRunnable); + mScrollRunnable.run(); + mRecyclerView.invalidate(); + } + break; + } + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + if (mVelocityTracker != null) { + mVelocityTracker + .computeCurrentVelocity(1000, mRecyclerView.getMaxFlingVelocity()); + } + select(null, ACTION_STATE_IDLE); + mActivePointerId = ACTIVE_POINTER_ID_NONE; + break; + case MotionEvent.ACTION_POINTER_UP: { + final int pointerIndex = MotionEventCompat.getActionIndex(event); + final int pointerId = MotionEventCompat.getPointerId(event, pointerIndex); + if (pointerId == mActivePointerId) { + if (mVelocityTracker != null) { + mVelocityTracker + .computeCurrentVelocity(1000, + mRecyclerView.getMaxFlingVelocity()); + } + // This was our active pointer going up. Choose a new + // active pointer and adjust accordingly. + final int newPointerIndex = pointerIndex == 0 ? 1 : 0; + mActivePointerId = MotionEventCompat.getPointerId(event, newPointerIndex); + updateDxDy(event, mSelectedFlags, pointerIndex); + } + break; + } + } + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + if (!disallowIntercept) { + return; + } + select(null, ACTION_STATE_IDLE); + } + }; + + /** + * Temporary rect instance that is used when we need to lookup Item decorations. + */ + private Rect mTmpRect; + + /** + * When user started to drag scroll. Reset when we don't scroll + */ + private long mDragScrollStartTimeInMs; + + /** + * Creates an ItemTouchHelper that will work with the given Callback. + *

+ * You can attach ItemTouchHelper to a RecyclerView via + * {@link #attachToRecyclerView(RecyclerView)}. Upon attaching, it will add an item decoration, + * an onItemTouchListener and a Child attach / detach listener to the RecyclerView. + * + * @param callback The Callback which controls the behavior of this touch helper. + */ + public ItemTouchHelper(Callback callback) { + mCallback = callback; + } + + private static boolean hitTest(View child, float x, float y, float left, float top) { + return x >= left && + x <= left + child.getWidth() && + y >= top && + y <= top + child.getHeight(); + } + + /** + * Attaches the ItemTouchHelper to the provided RecyclerView. If TouchHelper is already + * attached + * to a RecyclerView, it will first detach from the previous one. + * + * @param recyclerView The RecyclerView instance to which you want to add this helper. + */ + public void attachToRecyclerView(RecyclerView recyclerView) { + if (mRecyclerView == recyclerView) { + return; // nothing to do + } + if (mRecyclerView != null) { + destroyCallbacks(); + } + mRecyclerView = recyclerView; + if (mRecyclerView != null) { + setupCallbacks(); + } + } + + private void setupCallbacks() { + ViewConfiguration vc = ViewConfiguration.get(mRecyclerView.getContext()); + mSlop = vc.getScaledTouchSlop(); + mRecyclerView.addItemDecoration(this); + mRecyclerView.addOnItemTouchListener(mOnItemTouchListener); + mRecyclerView.addOnChildAttachStateChangeListener(this); + initGestureDetector(); + } + + private void destroyCallbacks() { + mRecyclerView.removeItemDecoration(this); + mRecyclerView.removeOnItemTouchListener(mOnItemTouchListener); + mRecyclerView.removeOnChildAttachStateChangeListener(this); + // clean all attached + final int recoverAnimSize = mRecoverAnimations.size(); + for (int i = recoverAnimSize - 1; i >= 0; i--) { + final RecoverAnimation recoverAnimation = mRecoverAnimations.get(0); + mCallback.clearView(mRecyclerView, recoverAnimation.mViewHolder); + } + mRecoverAnimations.clear(); + mOverdrawChild = null; + mOverdrawChildPosition = -1; + releaseVelocityTracker(); + } + + private void initGestureDetector() { + if (mGestureDetector != null) { + return; + } + mGestureDetector = new GestureDetectorCompat(mRecyclerView.getContext(), + new ItemTouchHelperGestureListener()); + } + + private void getSelectedDxDy(float[] outPosition) { + if ((mSelectedFlags & (LEFT | RIGHT)) != 0) { + outPosition[0] = mSelectedStartX + mDx - mSelected.itemView.getLeft(); + } else { + outPosition[0] = ViewCompat.getTranslationX(mSelected.itemView); + } + if ((mSelectedFlags & (UP | DOWN)) != 0) { + outPosition[1] = mSelectedStartY + mDy - mSelected.itemView.getTop(); + } else { + outPosition[1] = ViewCompat.getTranslationY(mSelected.itemView); + } + } + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + float dx = 0, dy = 0; + if (mSelected != null) { + getSelectedDxDy(mTmpPosition); + dx = mTmpPosition[0]; + dy = mTmpPosition[1]; + } + mCallback.onDrawOver(c, parent, mSelected, + mRecoverAnimations, mActionState, dx, dy); + } + + @Override + public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { + // we don't know if RV changed something so we should invalidate this index. + mOverdrawChildPosition = -1; + float dx = 0, dy = 0; + if (mSelected != null) { + getSelectedDxDy(mTmpPosition); + dx = mTmpPosition[0]; + dy = mTmpPosition[1]; + } + mCallback.onDraw(c, parent, mSelected, + mRecoverAnimations, mActionState, dx, dy); + } + + /** + * Starts dragging or swiping the given View. Call with null if you want to clear it. + * + * @param selected The ViewHolder to drag or swipe. Can be null if you want to cancel the + * current action + * @param actionState The type of action + */ + private void select(ViewHolder selected, int actionState) { + if (selected == mSelected && actionState == mActionState) { + return; + } + mDragScrollStartTimeInMs = Long.MIN_VALUE; + final int prevActionState = mActionState; + // prevent duplicate animations + endRecoverAnimation(selected, true); + mActionState = actionState; + if (actionState == ACTION_STATE_DRAG) { + // we remove after animation is complete. this means we only elevate the last drag + // child but that should perform good enough as it is very hard to start dragging a + // new child before the previous one settles. + mOverdrawChild = selected.itemView; + addChildDrawingOrderCallback(); + } + int actionStateMask = (1 << (DIRECTION_FLAG_COUNT + DIRECTION_FLAG_COUNT * actionState)) + - 1; + boolean preventLayout = false; + + if (mSelected != null) { + final ViewHolder prevSelected = mSelected; + if (prevSelected.itemView.getParent() != null) { + final int swipeDir = prevActionState == ACTION_STATE_DRAG ? 0 + : swipeIfNecessary(prevSelected); + releaseVelocityTracker(); + // find where we should animate to + final float targetTranslateX, targetTranslateY; + int animationType; + switch (swipeDir) { + case LEFT: + case RIGHT: + case START: + case END: + targetTranslateY = 0; + targetTranslateX = Math.signum(mDx) * mRecyclerView.getWidth(); + break; + case UP: + case DOWN: + targetTranslateX = 0; + targetTranslateY = Math.signum(mDy) * mRecyclerView.getHeight(); + break; + default: + targetTranslateX = 0; + targetTranslateY = 0; + } + if (prevActionState == ACTION_STATE_DRAG) { + animationType = ANIMATION_TYPE_DRAG; + } else if (swipeDir > 0) { + animationType = ANIMATION_TYPE_SWIPE_SUCCESS; + } else { + animationType = ANIMATION_TYPE_SWIPE_CANCEL; + } + getSelectedDxDy(mTmpPosition); + final float currentTranslateX = mTmpPosition[0]; + final float currentTranslateY = mTmpPosition[1]; + final RecoverAnimation rv = new RecoverAnimation(prevSelected, animationType, + prevActionState, currentTranslateX, currentTranslateY, + targetTranslateX, targetTranslateY) { + @Override + public void onAnimationEnd(ValueAnimatorCompat animation) { + super.onAnimationEnd(animation); + if (this.mOverridden) { + return; + } + if (swipeDir <= 0) { + // this is a drag or failed swipe. recover immediately + mCallback.clearView(mRecyclerView, prevSelected); + // full cleanup will happen on onDrawOver + } else { + // wait until remove animation is complete. + mPendingCleanup.add(prevSelected.itemView); + mIsPendingCleanup = true; + if (swipeDir > 0) { + // Animation might be ended by other animators during a layout. + // We defer callback to avoid editing adapter during a layout. + postDispatchSwipe(this, swipeDir); + } + } + // removed from the list after it is drawn for the last time + if (mOverdrawChild == prevSelected.itemView) { + removeChildDrawingOrderCallbackIfNecessary(prevSelected.itemView); + } + } + }; + final long duration = mCallback.getAnimationDuration(mRecyclerView, animationType, + targetTranslateX - currentTranslateX, targetTranslateY - currentTranslateY); + rv.setDuration(duration); + mRecoverAnimations.add(rv); + rv.start(); + preventLayout = true; + } else { + removeChildDrawingOrderCallbackIfNecessary(prevSelected.itemView); + mCallback.clearView(mRecyclerView, prevSelected); + } + mSelected = null; + } + if (selected != null) { + mSelectedFlags = + (mCallback.getAbsoluteMovementFlags(mRecyclerView, selected) & actionStateMask) + >> (mActionState * DIRECTION_FLAG_COUNT); + mSelectedStartX = selected.itemView.getLeft(); + mSelectedStartY = selected.itemView.getTop(); + mSelected = selected; + + if (actionState == ACTION_STATE_DRAG) { + mSelected.itemView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } + } + final ViewParent rvParent = mRecyclerView.getParent(); + if (rvParent != null) { + rvParent.requestDisallowInterceptTouchEvent(mSelected != null); + } + if (!preventLayout) { + mRecyclerView.getLayoutManager().requestSimpleAnimationsInNextLayout(); + } + mCallback.onSelectedChanged(mSelected, mActionState); + mRecyclerView.invalidate(); + } + + private void postDispatchSwipe(final RecoverAnimation anim, final int swipeDir) { + // wait until animations are complete. + mRecyclerView.post(new Runnable() { + @Override + public void run() { + if (mRecyclerView != null && mRecyclerView.isAttachedToWindow() && + !anim.mOverridden && + anim.mViewHolder.getAdapterPosition() != RecyclerView.NO_POSITION) { + final RecyclerView.ItemAnimator animator = mRecyclerView.getItemAnimator(); + // if animator is running or we have other active recover animations, we try + // not to call onSwiped because DefaultItemAnimator is not good at merging + // animations. Instead, we wait and batch. + if ((animator == null || !animator.isRunning(null)) + && !hasRunningRecoverAnim()) { + mCallback.onSwiped(anim.mViewHolder, swipeDir); + } else { + mRecyclerView.post(this); + } + } + } + }); + } + + private boolean hasRunningRecoverAnim() { + final int size = mRecoverAnimations.size(); + for (int i = 0; i < size; i++) { + if (!mRecoverAnimations.get(i).mEnded) { + return true; + } + } + return false; + } + + /** + * If user drags the view to the edge, trigger a scroll if necessary. + */ + private boolean scrollIfNecessary() { + if (mSelected == null) { + mDragScrollStartTimeInMs = Long.MIN_VALUE; + return false; + } + final long now = System.currentTimeMillis(); + final long scrollDuration = mDragScrollStartTimeInMs + == Long.MIN_VALUE ? 0 : now - mDragScrollStartTimeInMs; + RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager(); + if (mTmpRect == null) { + mTmpRect = new Rect(); + } + int scrollX = 0; + int scrollY = 0; + lm.calculateItemDecorationsForChild(mSelected.itemView, mTmpRect); + if (lm.canScrollHorizontally()) { + int curX = (int) (mSelectedStartX + mDx); + final int leftDiff = curX - mTmpRect.left - mRecyclerView.getPaddingLeft(); + if (mDx < 0 && leftDiff < 0) { + scrollX = leftDiff; + } else if (mDx > 0) { + final int rightDiff = + curX + mSelected.itemView.getWidth() + mTmpRect.right + - (mRecyclerView.getWidth() - mRecyclerView.getPaddingRight()); + if (rightDiff > 0) { + scrollX = rightDiff; + } + } + } + if (lm.canScrollVertically()) { + int curY = (int) (mSelectedStartY + mDy); + final int topDiff = curY - mTmpRect.top - mRecyclerView.getPaddingTop(); + if (mDy < 0 && topDiff < 0) { + scrollY = topDiff; + } else if (mDy > 0) { + final int bottomDiff = curY + mSelected.itemView.getHeight() + mTmpRect.bottom - + (mRecyclerView.getHeight() - mRecyclerView.getPaddingBottom()); + if (bottomDiff > 0) { + scrollY = bottomDiff; + } + } + } + if (scrollX != 0) { + scrollX = mCallback.interpolateOutOfBoundsScroll(mRecyclerView, + mSelected.itemView.getWidth(), scrollX, + mRecyclerView.getWidth(), scrollDuration); + } + if (scrollY != 0) { + scrollY = mCallback.interpolateOutOfBoundsScroll(mRecyclerView, + mSelected.itemView.getHeight(), scrollY, + mRecyclerView.getHeight(), scrollDuration); + } + if (scrollX != 0 || scrollY != 0) { + if (mDragScrollStartTimeInMs == Long.MIN_VALUE) { + mDragScrollStartTimeInMs = now; + } + mRecyclerView.scrollBy(scrollX, scrollY); + return true; + } + mDragScrollStartTimeInMs = Long.MIN_VALUE; + return false; + } + + private List findSwapTargets(ViewHolder viewHolder) { + if (mSwapTargets == null) { + mSwapTargets = new ArrayList(); + mDistances = new ArrayList(); + } else { + mSwapTargets.clear(); + mDistances.clear(); + } + final int margin = mCallback.getBoundingBoxMargin(); + final int left = Math.round(mSelectedStartX + mDx) - margin; + final int top = Math.round(mSelectedStartY + mDy) - margin; + final int right = left + viewHolder.itemView.getWidth() + 2 * margin; + final int bottom = top + viewHolder.itemView.getHeight() + 2 * margin; + final int centerX = (left + right) / 2; + final int centerY = (top + bottom) / 2; + final RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager(); + final int childCount = lm.getChildCount(); + for (int i = 0; i < childCount; i++) { + View other = lm.getChildAt(i); + if (other == viewHolder.itemView) { + continue;//myself! + } + if (other.getBottom() < top || other.getTop() > bottom + || other.getRight() < left || other.getLeft() > right) { + continue; + } + final ViewHolder otherVh = mRecyclerView.getChildViewHolder(other); + if (mCallback.canDropOver(mRecyclerView, mSelected, otherVh)) { + // find the index to add + final int dx = Math.abs(centerX - (other.getLeft() + other.getRight()) / 2); + final int dy = Math.abs(centerY - (other.getTop() + other.getBottom()) / 2); + final int dist = dx * dx + dy * dy; + + int pos = 0; + final int cnt = mSwapTargets.size(); + for (int j = 0; j < cnt; j++) { + if (dist > mDistances.get(j)) { + pos++; + } else { + break; + } + } + mSwapTargets.add(pos, otherVh); + mDistances.add(pos, dist); + } + } + return mSwapTargets; + } + + /** + * Checks if we should swap w/ another view holder. + */ + private void moveIfNecessary(ViewHolder viewHolder) { + if (mRecyclerView.isLayoutRequested()) { + return; + } + if (mActionState != ACTION_STATE_DRAG) { + return; + } + + final float threshold = mCallback.getMoveThreshold(viewHolder); + final int x = (int) (mSelectedStartX + mDx); + final int y = (int) (mSelectedStartY + mDy); + if (Math.abs(y - viewHolder.itemView.getTop()) < viewHolder.itemView.getHeight() * threshold + && Math.abs(x - viewHolder.itemView.getLeft()) + < viewHolder.itemView.getWidth() * threshold) { + return; + } + List swapTargets = findSwapTargets(viewHolder); + if (swapTargets.size() == 0) { + return; + } + // may swap. + ViewHolder target = mCallback.chooseDropTarget(viewHolder, swapTargets, x, y); + if (target == null) { + mSwapTargets.clear(); + mDistances.clear(); + return; + } + final int toPosition = target.getAdapterPosition(); + final int fromPosition = viewHolder.getAdapterPosition(); + if (mCallback.onMove(mRecyclerView, viewHolder, target)) { + // keep target visible + mCallback.onMoved(mRecyclerView, viewHolder, fromPosition, + target, toPosition, x, y); + } + } + + @Override + public void onChildViewAttachedToWindow(View view) { + } + + @Override + public void onChildViewDetachedFromWindow(View view) { + removeChildDrawingOrderCallbackIfNecessary(view); + final ViewHolder holder = mRecyclerView.getChildViewHolder(view); + if (holder == null) { + return; + } + if (mSelected != null && holder == mSelected) { + select(null, ACTION_STATE_IDLE); + } else { + endRecoverAnimation(holder, false); // this may push it into pending cleanup list. + if (mPendingCleanup.remove(holder.itemView)) { + mCallback.clearView(mRecyclerView, holder); + } + } + } + + /** + * Returns the animation type or 0 if cannot be found. + */ + private int endRecoverAnimation(ViewHolder viewHolder, boolean override) { + final int recoverAnimSize = mRecoverAnimations.size(); + for (int i = recoverAnimSize - 1; i >= 0; i--) { + final RecoverAnimation anim = mRecoverAnimations.get(i); + if (anim.mViewHolder == viewHolder) { + anim.mOverridden |= override; + if (!anim.mEnded) { + anim.cancel(); + } + mRecoverAnimations.remove(i); + anim.mViewHolder.setIsRecyclable(true); + return anim.mAnimationType; + } + } + return 0; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, + RecyclerView.State state) { + outRect.setEmpty(); + } + + private void obtainVelocityTracker() { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + } + mVelocityTracker = VelocityTracker.obtain(); + } + + private void releaseVelocityTracker() { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + private ViewHolder findSwipedView(MotionEvent motionEvent) { + final RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager(); + if (mActivePointerId == ACTIVE_POINTER_ID_NONE) { + return null; + } + final int pointerIndex = MotionEventCompat.findPointerIndex(motionEvent, mActivePointerId); + final float dx = MotionEventCompat.getX(motionEvent, pointerIndex) - mInitialTouchX; + final float dy = MotionEventCompat.getY(motionEvent, pointerIndex) - mInitialTouchY; + final float absDx = Math.abs(dx); + final float absDy = Math.abs(dy); + + if (absDx < mSlop && absDy < mSlop) { + return null; + } + if (absDx > absDy && lm.canScrollHorizontally()) { + return null; + } else if (absDy > absDx && lm.canScrollVertically()) { + return null; + } + View child = findChildView(motionEvent); + if (child == null) { + return null; + } + return mRecyclerView.getChildViewHolder(child); + } + + /** + * Checks whether we should select a View for swiping. + */ + private boolean checkSelectForSwipe(int action, MotionEvent motionEvent, int pointerIndex) { + if (mSelected != null || action != MotionEvent.ACTION_MOVE + || mActionState == ACTION_STATE_DRAG || !mCallback.isItemViewSwipeEnabled()) { + return false; + } + if (mRecyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { + return false; + } + final ViewHolder vh = findSwipedView(motionEvent); + if (vh == null) { + return false; + } + final int movementFlags = mCallback.getAbsoluteMovementFlags(mRecyclerView, vh); + + final int swipeFlags = (movementFlags & ACTION_MODE_SWIPE_MASK) + >> (DIRECTION_FLAG_COUNT * ACTION_STATE_SWIPE); + + if (swipeFlags == 0) { + return false; + } + + // mDx and mDy are only set in allowed directions. We use custom x/y here instead of + // updateDxDy to avoid swiping if user moves more in the other direction + final float x = MotionEventCompat.getX(motionEvent, pointerIndex); + final float y = MotionEventCompat.getY(motionEvent, pointerIndex); + + // Calculate the distance moved + final float dx = x - mInitialTouchX; + final float dy = y - mInitialTouchY; + // swipe target is chose w/o applying flags so it does not really check if swiping in that + // direction is allowed. This why here, we use mDx mDy to check slope value again. + final float absDx = Math.abs(dx); + final float absDy = Math.abs(dy); + + if (absDx < mSlop && absDy < mSlop) { + return false; + } + if (absDx > absDy) { + if (dx < 0 && (swipeFlags & LEFT) == 0) { + return false; + } + if (dx > 0 && (swipeFlags & RIGHT) == 0) { + return false; + } + } else { + if (dy < 0 && (swipeFlags & UP) == 0) { + return false; + } + if (dy > 0 && (swipeFlags & DOWN) == 0) { + return false; + } + } + mDx = mDy = 0f; + mActivePointerId = MotionEventCompat.getPointerId(motionEvent, 0); + select(vh, ACTION_STATE_SWIPE); + return true; + } + + private View findChildView(MotionEvent event) { + // first check elevated views, if none, then call RV + final float x = event.getX(); + final float y = event.getY(); + if (mSelected != null) { + final View selectedView = mSelected.itemView; + if (hitTest(selectedView, x, y, mSelectedStartX + mDx, mSelectedStartY + mDy)) { + return selectedView; + } + } + for (int i = mRecoverAnimations.size() - 1; i >= 0; i--) { + final RecoverAnimation anim = mRecoverAnimations.get(i); + final View view = anim.mViewHolder.itemView; + if (hitTest(view, x, y, anim.mX, anim.mY)) { + return view; + } + } + return mRecyclerView.findChildViewUnder(x, y); + } + + /** + * Starts dragging the provided ViewHolder. By default, ItemTouchHelper starts a drag when a + * View is long pressed. You can disable that behavior via + * {@link ItemTouchHelper.Callback#isLongPressDragEnabled()}. + *

+ * For this method to work: + *

    + *
  • The provided ViewHolder must be a child of the RecyclerView to which this + * ItemTouchHelper + * is attached.
  • + *
  • {@link ItemTouchHelper.Callback} must have dragging enabled.
  • + *
  • There must be a previous touch event that was reported to the ItemTouchHelper + * through RecyclerView's ItemTouchListener mechanism. As long as no other ItemTouchListener + * grabs previous events, this should work as expected.
  • + *
+ * + * For example, if you would like to let your user to be able to drag an Item by touching one + * of its descendants, you may implement it as follows: + *
+     *     viewHolder.dragButton.setOnTouchListener(new View.OnTouchListener() {
+     *         public boolean onTouch(View v, MotionEvent event) {
+     *             if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
+     *                 mItemTouchHelper.startDrag(viewHolder);
+     *             }
+     *             return false;
+     *         }
+     *     });
+     * 
+ *

+ * + * @param viewHolder The ViewHolder to start dragging. It must be a direct child of + * RecyclerView. + * @see ItemTouchHelper.Callback#isItemViewSwipeEnabled() + */ + public void startDrag(ViewHolder viewHolder) { + if (!mCallback.hasDragFlag(mRecyclerView, viewHolder)) { + Log.e(TAG, "Start drag has been called but swiping is not enabled"); + return; + } + if (viewHolder.itemView.getParent() != mRecyclerView) { + Log.e(TAG, "Start drag has been called with a view holder which is not a child of " + + "the RecyclerView which is controlled by this ItemTouchHelper."); + return; + } + obtainVelocityTracker(); + mDx = mDy = 0f; + select(viewHolder, ACTION_STATE_DRAG); + } + + /** + * Starts swiping the provided ViewHolder. By default, ItemTouchHelper starts swiping a View + * when user swipes their finger (or mouse pointer) over the View. You can disable this + * behavior + * by overriding {@link ItemTouchHelper.Callback} + *

+ * For this method to work: + *

    + *
  • The provided ViewHolder must be a child of the RecyclerView to which this + * ItemTouchHelper is attached.
  • + *
  • {@link ItemTouchHelper.Callback} must have swiping enabled.
  • + *
  • There must be a previous touch event that was reported to the ItemTouchHelper + * through RecyclerView's ItemTouchListener mechanism. As long as no other ItemTouchListener + * grabs previous events, this should work as expected.
  • + *
+ * + * For example, if you would like to let your user to be able to swipe an Item by touching one + * of its descendants, you may implement it as follows: + *
+     *     viewHolder.dragButton.setOnTouchListener(new View.OnTouchListener() {
+     *         public boolean onTouch(View v, MotionEvent event) {
+     *             if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
+     *                 mItemTouchHelper.startSwipe(viewHolder);
+     *             }
+     *             return false;
+     *         }
+     *     });
+     * 
+ * + * @param viewHolder The ViewHolder to start swiping. It must be a direct child of + * RecyclerView. + */ + public void startSwipe(ViewHolder viewHolder) { + if (!mCallback.hasSwipeFlag(mRecyclerView, viewHolder)) { + Log.e(TAG, "Start swipe has been called but dragging is not enabled"); + return; + } + if (viewHolder.itemView.getParent() != mRecyclerView) { + Log.e(TAG, "Start swipe has been called with a view holder which is not a child of " + + "the RecyclerView controlled by this ItemTouchHelper."); + return; + } + obtainVelocityTracker(); + mDx = mDy = 0f; + select(viewHolder, ACTION_STATE_SWIPE); + } + + private RecoverAnimation findAnimation(MotionEvent event) { + if (mRecoverAnimations.isEmpty()) { + return null; + } + View target = findChildView(event); + for (int i = mRecoverAnimations.size() - 1; i >= 0; i--) { + final RecoverAnimation anim = mRecoverAnimations.get(i); + if (anim.mViewHolder.itemView == target) { + return anim; + } + } + return null; + } + + private void updateDxDy(MotionEvent ev, int directionFlags, int pointerIndex) { + final float x = MotionEventCompat.getX(ev, pointerIndex); + final float y = MotionEventCompat.getY(ev, pointerIndex); + + // Calculate the distance moved + mDx = x - mInitialTouchX; + mDy = y - mInitialTouchY; + if ((directionFlags & LEFT) == 0) { + mDx = Math.max(0, mDx); + } + if ((directionFlags & RIGHT) == 0) { + mDx = Math.min(0, mDx); + } + if ((directionFlags & UP) == 0) { + mDy = Math.max(0, mDy); + } + if ((directionFlags & DOWN) == 0) { + mDy = Math.min(0, mDy); + } + } + + private int swipeIfNecessary(ViewHolder viewHolder) { + if (mActionState == ACTION_STATE_DRAG) { + return 0; + } + final int originalMovementFlags = mCallback.getMovementFlags(mRecyclerView, viewHolder); + final int absoluteMovementFlags = mCallback.convertToAbsoluteDirection( + originalMovementFlags, + ViewCompat.getLayoutDirection(mRecyclerView)); + final int flags = (absoluteMovementFlags + & ACTION_MODE_SWIPE_MASK) >> (ACTION_STATE_SWIPE * DIRECTION_FLAG_COUNT); + if (flags == 0) { + return 0; + } + final int originalFlags = (originalMovementFlags + & ACTION_MODE_SWIPE_MASK) >> (ACTION_STATE_SWIPE * DIRECTION_FLAG_COUNT); + int swipeDir; + if (Math.abs(mDx) > Math.abs(mDy)) { + if ((swipeDir = checkHorizontalSwipe(viewHolder, flags)) > 0) { + // if swipe dir is not in original flags, it should be the relative direction + if ((originalFlags & swipeDir) == 0) { + // convert to relative + return Callback.convertToRelativeDirection(swipeDir, + ViewCompat.getLayoutDirection(mRecyclerView)); + } + return swipeDir; + } + if ((swipeDir = checkVerticalSwipe(viewHolder, flags)) > 0) { + return swipeDir; + } + } else { + if ((swipeDir = checkVerticalSwipe(viewHolder, flags)) > 0) { + return swipeDir; + } + if ((swipeDir = checkHorizontalSwipe(viewHolder, flags)) > 0) { + // if swipe dir is not in original flags, it should be the relative direction + if ((originalFlags & swipeDir) == 0) { + // convert to relative + return Callback.convertToRelativeDirection(swipeDir, + ViewCompat.getLayoutDirection(mRecyclerView)); + } + return swipeDir; + } + } + return 0; + } + + private int checkHorizontalSwipe(ViewHolder viewHolder, int flags) { + if ((flags & (LEFT | RIGHT)) != 0) { + final int dirFlag = mDx > 0 ? RIGHT : LEFT; + if (mVelocityTracker != null && mActivePointerId > -1) { + final float xVelocity = VelocityTrackerCompat + .getXVelocity(mVelocityTracker, mActivePointerId); + final int velDirFlag = xVelocity > 0f ? RIGHT : LEFT; + if ((velDirFlag & flags) != 0 && dirFlag == velDirFlag && + Math.abs(xVelocity) >= mRecyclerView.getMinFlingVelocity()) { + return velDirFlag; + } + } + + final float threshold = mRecyclerView.getWidth() * mCallback + .getSwipeThreshold(viewHolder); + + if ((flags & dirFlag) != 0 && Math.abs(mDx) > threshold) { + return dirFlag; + } + } + return 0; + } + + private int checkVerticalSwipe(ViewHolder viewHolder, int flags) { + if ((flags & (UP | DOWN)) != 0) { + final int dirFlag = mDy > 0 ? DOWN : UP; + if (mVelocityTracker != null && mActivePointerId > -1) { + final float yVelocity = VelocityTrackerCompat + .getYVelocity(mVelocityTracker, mActivePointerId); + final int velDirFlag = yVelocity > 0f ? DOWN : UP; + if ((velDirFlag & flags) != 0 && velDirFlag == dirFlag && + Math.abs(yVelocity) >= mRecyclerView.getMinFlingVelocity()) { + return velDirFlag; + } + } + + final float threshold = mRecyclerView.getHeight() * mCallback + .getSwipeThreshold(viewHolder); + if ((flags & dirFlag) != 0 && Math.abs(mDy) > threshold) { + return dirFlag; + } + } + return 0; + } + + private void addChildDrawingOrderCallback() { + if (Build.VERSION.SDK_INT >= 21) { + return;// we use elevation on Lollipop + } + if (mChildDrawingOrderCallback == null) { + mChildDrawingOrderCallback = new RecyclerView.ChildDrawingOrderCallback() { + @Override + public int onGetChildDrawingOrder(int childCount, int i) { + if (mOverdrawChild == null) { + return i; + } + int childPosition = mOverdrawChildPosition; + if (childPosition == -1) { + childPosition = mRecyclerView.indexOfChild(mOverdrawChild); + mOverdrawChildPosition = childPosition; + } + if (i == childCount - 1) { + return childPosition; + } + return i < childPosition ? i : i + 1; + } + }; + } + mRecyclerView.setChildDrawingOrderCallback(mChildDrawingOrderCallback); + } + + private void removeChildDrawingOrderCallbackIfNecessary(View view) { + if (view == mOverdrawChild) { + mOverdrawChild = null; + // only remove if we've added + if (mChildDrawingOrderCallback != null) { + mRecyclerView.setChildDrawingOrderCallback(null); + } + } + } + + /** + * An interface which can be implemented by LayoutManager for better integration with + * {@link ItemTouchHelper}. + */ + public static interface ViewDropHandler { + + /** + * Called by the {@link ItemTouchHelper} after a View is dropped over another View. + *

+ * A LayoutManager should implement this interface to get ready for the upcoming move + * operation. + *

+ * For example, LinearLayoutManager sets up a "scrollToPositionWithOffset" calls so that + * the View under drag will be used as an anchor View while calculating the next layout, + * making layout stay consistent. + * + * @param view The View which is being dragged. It is very likely that user is still + * dragging this View so there might be other + * {@link #prepareForDrop(View, View, int, int)} after this one. + * @param target The target view which is being dropped on. + * @param x The left offset of the View that is being dragged. This value + * includes the movement caused by the user. + * @param y The top offset of the View that is being dragged. This value + * includes the movement caused by the user. + */ + public void prepareForDrop(View view, View target, int x, int y); + } + + /** + * This class is the contract between ItemTouchHelper and your application. It lets you control + * which touch behaviors are enabled per each ViewHolder and also receive callbacks when user + * performs these actions. + *

+ * To control which actions user can take on each view, you should override + * {@link #getMovementFlags(RecyclerView, ViewHolder)} and return appropriate set + * of direction flags. ({@link #LEFT}, {@link #RIGHT}, {@link #START}, {@link #END}, + * {@link #UP}, {@link #DOWN}). You can use + * {@link #makeMovementFlags(int, int)} to easily construct it. Alternatively, you can use + * {@link SimpleCallback}. + *

+ * If user drags an item, ItemTouchHelper will call + * {@link Callback#onMove(RecyclerView, ViewHolder, ViewHolder) + * onMove(recyclerView, dragged, target)}. + * Upon receiving this callback, you should move the item from the old position + * ({@code dragged.getAdapterPosition()}) to new position ({@code target.getAdapterPosition()}) + * in your adapter and also call {@link RecyclerView.Adapter#notifyItemMoved(int, int)}. + * To control where a View can be dropped, you can override + * {@link #canDropOver(RecyclerView, ViewHolder, ViewHolder)}. When a + * dragging View overlaps multiple other views, Callback chooses the closest View with which + * dragged View might have changed positions. Although this approach works for many use cases, + * if you have a custom LayoutManager, you can override + * {@link #chooseDropTarget(ViewHolder, java.util.List, int, int)} to select a + * custom drop target. + *

+ * When a View is swiped, ItemTouchHelper animates it until it goes out of bounds, then calls + * {@link #onSwiped(ViewHolder, int)}. At this point, you should update your + * adapter (e.g. remove the item) and call related Adapter#notify event. + */ + @SuppressWarnings("UnusedParameters") + public abstract static class Callback { + + public static final int DEFAULT_DRAG_ANIMATION_DURATION = 200; + + public static final int DEFAULT_SWIPE_ANIMATION_DURATION = 250; + + static final int RELATIVE_DIR_FLAGS = START | END | + ((START | END) << DIRECTION_FLAG_COUNT) | + ((START | END) << (2 * DIRECTION_FLAG_COUNT)); + + private static final ItemTouchUIUtil sUICallback; + + private static final int ABS_HORIZONTAL_DIR_FLAGS = LEFT | RIGHT | + ((LEFT | RIGHT) << DIRECTION_FLAG_COUNT) | + ((LEFT | RIGHT) << (2 * DIRECTION_FLAG_COUNT)); + + private static final Interpolator sDragScrollInterpolator = new Interpolator() { + public float getInterpolation(float t) { + return t * t * t * t * t; + } + }; + + private static final Interpolator sDragViewScrollCapInterpolator = new Interpolator() { + public float getInterpolation(float t) { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + } + }; + + /** + * Drag scroll speed keeps accelerating until this many milliseconds before being capped. + */ + private static final long DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS = 2000; + + private int mCachedMaxScrollSpeed = -1; + + static { + if (Build.VERSION.SDK_INT >= 21) { + sUICallback = new ItemTouchUIUtilImpl.Lollipop(); + } else if (Build.VERSION.SDK_INT >= 11) { + sUICallback = new ItemTouchUIUtilImpl.Honeycomb(); + } else { + sUICallback = new ItemTouchUIUtilImpl.Gingerbread(); + } + } + + /** + * Returns the {@link ItemTouchUIUtil} that is used by the {@link Callback} class for visual + * changes on Views in response to user interactions. {@link ItemTouchUIUtil} has different + * implementations for different platform versions. + *

+ * By default, {@link Callback} applies these changes on + * {@link RecyclerView.ViewHolder#itemView}. + *

+ * For example, if you have a use case where you only want the text to move when user + * swipes over the view, you can do the following: + *

+         *     public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder){
+         *         getDefaultUIUtil().clearView(((ItemTouchViewHolder) viewHolder).textView);
+         *     }
+         *     public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
+         *         if (viewHolder != null){
+         *             getDefaultUIUtil().onSelected(((ItemTouchViewHolder) viewHolder).textView);
+         *         }
+         *     }
+         *     public void onChildDraw(Canvas c, RecyclerView recyclerView,
+         *             RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
+         *             boolean isCurrentlyActive) {
+         *         getDefaultUIUtil().onDraw(c, recyclerView,
+         *                 ((ItemTouchViewHolder) viewHolder).textView, dX, dY,
+         *                 actionState, isCurrentlyActive);
+         *         return true;
+         *     }
+         *     public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
+         *             RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
+         *             boolean isCurrentlyActive) {
+         *         getDefaultUIUtil().onDrawOver(c, recyclerView,
+         *                 ((ItemTouchViewHolder) viewHolder).textView, dX, dY,
+         *                 actionState, isCurrentlyActive);
+         *         return true;
+         *     }
+         * 
+ * + * @return The {@link ItemTouchUIUtil} instance that is used by the {@link Callback} + */ + public static ItemTouchUIUtil getDefaultUIUtil() { + return sUICallback; + } + + /** + * Replaces a movement direction with its relative version by taking layout direction into + * account. + * + * @param flags The flag value that include any number of movement flags. + * @param layoutDirection The layout direction of the View. Can be obtained from + * {@link ViewCompat#getLayoutDirection(android.view.View)}. + * @return Updated flags which uses relative flags ({@link #START}, {@link #END}) instead + * of {@link #LEFT}, {@link #RIGHT}. + * @see #convertToAbsoluteDirection(int, int) + */ + public static int convertToRelativeDirection(int flags, int layoutDirection) { + int masked = flags & ABS_HORIZONTAL_DIR_FLAGS; + if (masked == 0) { + return flags;// does not have any abs flags, good. + } + flags &= ~masked; //remove left / right. + if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) { + // no change. just OR with 2 bits shifted mask and return + flags |= masked << 2; // START is 2 bits after LEFT, END is 2 bits after RIGHT. + return flags; + } else { + // add RIGHT flag as START + flags |= ((masked << 1) & ~ABS_HORIZONTAL_DIR_FLAGS); + // first clean RIGHT bit then add LEFT flag as END + flags |= ((masked << 1) & ABS_HORIZONTAL_DIR_FLAGS) << 2; + } + return flags; + } + + /** + * Convenience method to create movement flags. + *

+ * For instance, if you want to let your items be drag & dropped vertically and swiped + * left to be dismissed, you can call this method with: + * makeMovementFlags(UP | DOWN, LEFT); + * + * @param dragFlags The directions in which the item can be dragged. + * @param swipeFlags The directions in which the item can be swiped. + * @return Returns an integer composed of the given drag and swipe flags. + */ + public static int makeMovementFlags(int dragFlags, int swipeFlags) { + return makeFlag(ACTION_STATE_IDLE, swipeFlags | dragFlags) | + makeFlag(ACTION_STATE_SWIPE, swipeFlags) | makeFlag(ACTION_STATE_DRAG, + dragFlags); + } + + /** + * Shifts the given direction flags to the offset of the given action state. + * + * @param actionState The action state you want to get flags in. Should be one of + * {@link #ACTION_STATE_IDLE}, {@link #ACTION_STATE_SWIPE} or + * {@link #ACTION_STATE_DRAG}. + * @param directions The direction flags. Can be composed from {@link #UP}, {@link #DOWN}, + * {@link #RIGHT}, {@link #LEFT} {@link #START} and {@link #END}. + * @return And integer that represents the given directions in the provided actionState. + */ + public static int makeFlag(int actionState, int directions) { + return directions << (actionState * DIRECTION_FLAG_COUNT); + } + + /** + * Should return a composite flag which defines the enabled move directions in each state + * (idle, swiping, dragging). + *

+ * Instead of composing this flag manually, you can use {@link #makeMovementFlags(int, + * int)} + * or {@link #makeFlag(int, int)}. + *

+ * This flag is composed of 3 sets of 8 bits, where first 8 bits are for IDLE state, next + * 8 bits are for SWIPE state and third 8 bits are for DRAG state. + * Each 8 bit sections can be constructed by simply OR'ing direction flags defined in + * {@link ItemTouchHelper}. + *

+ * For example, if you want it to allow swiping LEFT and RIGHT but only allow starting to + * swipe by swiping RIGHT, you can return: + *

+         *      makeFlag(ACTION_STATE_IDLE, RIGHT) | makeFlag(ACTION_STATE_SWIPE, LEFT | RIGHT);
+         * 
+ * This means, allow right movement while IDLE and allow right and left movement while + * swiping. + * + * @param recyclerView The RecyclerView to which ItemTouchHelper is attached. + * @param viewHolder The ViewHolder for which the movement information is necessary. + * @return flags specifying which movements are allowed on this ViewHolder. + * @see #makeMovementFlags(int, int) + * @see #makeFlag(int, int) + */ + public abstract int getMovementFlags(RecyclerView recyclerView, + ViewHolder viewHolder); + + /** + * Converts a given set of flags to absolution direction which means {@link #START} and + * {@link #END} are replaced with {@link #LEFT} and {@link #RIGHT} depending on the layout + * direction. + * + * @param flags The flag value that include any number of movement flags. + * @param layoutDirection The layout direction of the RecyclerView. + * @return Updated flags which includes only absolute direction values. + */ + public int convertToAbsoluteDirection(int flags, int layoutDirection) { + int masked = flags & RELATIVE_DIR_FLAGS; + if (masked == 0) { + return flags;// does not have any relative flags, good. + } + flags &= ~masked; //remove start / end + if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) { + // no change. just OR with 2 bits shifted mask and return + flags |= masked >> 2; // START is 2 bits after LEFT, END is 2 bits after RIGHT. + return flags; + } else { + // add START flag as RIGHT + flags |= ((masked >> 1) & ~RELATIVE_DIR_FLAGS); + // first clean start bit then add END flag as LEFT + flags |= ((masked >> 1) & RELATIVE_DIR_FLAGS) >> 2; + } + return flags; + } + + final int getAbsoluteMovementFlags(RecyclerView recyclerView, + ViewHolder viewHolder) { + final int flags = getMovementFlags(recyclerView, viewHolder); + return convertToAbsoluteDirection(flags, ViewCompat.getLayoutDirection(recyclerView)); + } + + private boolean hasDragFlag(RecyclerView recyclerView, ViewHolder viewHolder) { + final int flags = getAbsoluteMovementFlags(recyclerView, viewHolder); + return (flags & ACTION_MODE_DRAG_MASK) != 0; + } + + private boolean hasSwipeFlag(RecyclerView recyclerView, + ViewHolder viewHolder) { + final int flags = getAbsoluteMovementFlags(recyclerView, viewHolder); + return (flags & ACTION_MODE_SWIPE_MASK) != 0; + } + + /** + * Return true if the current ViewHolder can be dropped over the the target ViewHolder. + *

+ * This method is used when selecting drop target for the dragged View. After Views are + * eliminated either via bounds check or via this method, resulting set of views will be + * passed to {@link #chooseDropTarget(ViewHolder, java.util.List, int, int)}. + *

+ * Default implementation returns true. + * + * @param recyclerView The RecyclerView to which ItemTouchHelper is attached to. + * @param current The ViewHolder that user is dragging. + * @param target The ViewHolder which is below the dragged ViewHolder. + * @return True if the dragged ViewHolder can be replaced with the target ViewHolder, false + * otherwise. + */ + public boolean canDropOver(RecyclerView recyclerView, ViewHolder current, + ViewHolder target) { + return true; + } + + /** + * Called when ItemTouchHelper wants to move the dragged item from its old position to + * the new position. + *

+ * If this method returns true, ItemTouchHelper assumes {@code viewHolder} has been moved + * to the adapter position of {@code target} ViewHolder + * ({@link ViewHolder#getAdapterPosition() + * ViewHolder#getAdapterPosition()}). + *

+ * If you don't support drag & drop, this method will never be called. + * + * @param recyclerView The RecyclerView to which ItemTouchHelper is attached to. + * @param viewHolder The ViewHolder which is being dragged by the user. + * @param target The ViewHolder over which the currently active item is being + * dragged. + * @return True if the {@code viewHolder} has been moved to the adapter position of + * {@code target}. + * @see #onMoved(RecyclerView, ViewHolder, int, ViewHolder, int, int, int) + */ + public abstract boolean onMove(RecyclerView recyclerView, + ViewHolder viewHolder, ViewHolder target); + + /** + * Returns whether ItemTouchHelper should start a drag and drop operation if an item is + * long pressed. + *

+ * Default value returns true but you may want to disable this if you want to start + * dragging on a custom view touch using {@link #startDrag(ViewHolder)}. + * + * @return True if ItemTouchHelper should start dragging an item when it is long pressed, + * false otherwise. Default value is true. + * @see #startDrag(ViewHolder) + */ + public boolean isLongPressDragEnabled() { + return true; + } + + /** + * Returns whether ItemTouchHelper should start a swipe operation if a pointer is swiped + * over the View. + *

+ * Default value returns true but you may want to disable this if you want to start + * swiping on a custom view touch using {@link #startSwipe(ViewHolder)}. + * + * @return True if ItemTouchHelper should start swiping an item when user swipes a pointer + * over the View, false otherwise. Default value is true. + * @see #startSwipe(ViewHolder) + */ + public boolean isItemViewSwipeEnabled() { + return true; + } + + /** + * When finding views under a dragged view, by default, ItemTouchHelper searches for views + * that overlap with the dragged View. By overriding this method, you can extend or shrink + * the search box. + * + * @return The extra margin to be added to the hit box of the dragged View. + */ + public int getBoundingBoxMargin() { + return 0; + } + + /** + * Returns the fraction that the user should move the View to be considered as swiped. + * The fraction is calculated with respect to RecyclerView's bounds. + *

+ * Default value is .5f, which means, to swipe a View, user must move the View at least + * half of RecyclerView's width or height, depending on the swipe direction. + * + * @param viewHolder The ViewHolder that is being dragged. + * @return A float value that denotes the fraction of the View size. Default value + * is .5f . + */ + public float getSwipeThreshold(ViewHolder viewHolder) { + return .5f; + } + + /** + * Returns the fraction that the user should move the View to be considered as it is + * dragged. After a view is moved this amount, ItemTouchHelper starts checking for Views + * below it for a possible drop. + * + * @param viewHolder The ViewHolder that is being dragged. + * @return A float value that denotes the fraction of the View size. Default value is + * .5f . + */ + public float getMoveThreshold(ViewHolder viewHolder) { + return .5f; + } + + /** + * Called by ItemTouchHelper to select a drop target from the list of ViewHolders that + * are under the dragged View. + *

+ * Default implementation filters the View with which dragged item have changed position + * in the drag direction. For instance, if the view is dragged UP, it compares the + * view.getTop() of the two views before and after drag started. If that value + * is different, the target view passes the filter. + *

+ * Among these Views which pass the test, the one closest to the dragged view is chosen. + *

+ * This method is called on the main thread every time user moves the View. If you want to + * override it, make sure it does not do any expensive operations. + * + * @param selected The ViewHolder being dragged by the user. + * @param dropTargets The list of ViewHolder that are under the dragged View and + * candidate as a drop. + * @param curX The updated left value of the dragged View after drag translations + * are applied. This value does not include margins added by + * {@link RecyclerView.ItemDecoration}s. + * @param curY The updated top value of the dragged View after drag translations + * are applied. This value does not include margins added by + * {@link RecyclerView.ItemDecoration}s. + * @return A ViewHolder to whose position the dragged ViewHolder should be + * moved to. + */ + public ViewHolder chooseDropTarget(ViewHolder selected, + List dropTargets, int curX, int curY) { + int right = curX + selected.itemView.getWidth(); + int bottom = curY + selected.itemView.getHeight(); + ViewHolder winner = null; + int winnerScore = -1; + final int dx = curX - selected.itemView.getLeft(); + final int dy = curY - selected.itemView.getTop(); + final int targetsSize = dropTargets.size(); + for (int i = 0; i < targetsSize; i++) { + final ViewHolder target = dropTargets.get(i); + if (dx > 0) { + int diff = target.itemView.getRight() - right; + if (diff < 0 && target.itemView.getRight() > selected.itemView.getRight()) { + final int score = Math.abs(diff); + if (score > winnerScore) { + winnerScore = score; + winner = target; + } + } + } + if (dx < 0) { + int diff = target.itemView.getLeft() - curX; + if (diff > 0 && target.itemView.getLeft() < selected.itemView.getLeft()) { + final int score = Math.abs(diff); + if (score > winnerScore) { + winnerScore = score; + winner = target; + } + } + } + if (dy < 0) { + int diff = target.itemView.getTop() - curY; + if (diff > 0 && target.itemView.getTop() < selected.itemView.getTop()) { + final int score = Math.abs(diff); + if (score > winnerScore) { + winnerScore = score; + winner = target; + } + } + } + + if (dy > 0) { + int diff = target.itemView.getBottom() - bottom; + if (diff < 0 && target.itemView.getBottom() > selected.itemView.getBottom()) { + final int score = Math.abs(diff); + if (score > winnerScore) { + winnerScore = score; + winner = target; + } + } + } + } + return winner; + } + + /** + * Called when a ViewHolder is swiped by the user. + *

+ * If you are returning relative directions ({@link #START} , {@link #END}) from the + * {@link #getMovementFlags(RecyclerView, ViewHolder)} method, this method + * will also use relative directions. Otherwise, it will use absolute directions. + *

+ * If you don't support swiping, this method will never be called. + *

+ * ItemTouchHelper will keep a reference to the View until it is detached from + * RecyclerView. + * As soon as it is detached, ItemTouchHelper will call + * {@link #clearView(RecyclerView, ViewHolder)}. + * + * @param viewHolder The ViewHolder which has been swiped by the user. + * @param direction The direction to which the ViewHolder is swiped. It is one of + * {@link #UP}, {@link #DOWN}, + * {@link #LEFT} or {@link #RIGHT}. If your + * {@link #getMovementFlags(RecyclerView, ViewHolder)} + * method + * returned relative flags instead of {@link #LEFT} / {@link #RIGHT}; + * `direction` will be relative as well. ({@link #START} or {@link + * #END}). + */ + public abstract void onSwiped(ViewHolder viewHolder, int direction); + + /** + * Called when the ViewHolder swiped or dragged by the ItemTouchHelper is changed. + *

+ * If you override this method, you should call super. + * + * @param viewHolder The new ViewHolder that is being swiped or dragged. Might be null if + * it is cleared. + * @param actionState One of {@link ItemTouchHelper#ACTION_STATE_IDLE}, + * {@link ItemTouchHelper#ACTION_STATE_SWIPE} or + * {@link ItemTouchHelper#ACTION_STATE_DRAG}. + * + * @see #clearView(RecyclerView, RecyclerView.ViewHolder) + */ + public void onSelectedChanged(ViewHolder viewHolder, int actionState) { + if (viewHolder != null) { + sUICallback.onSelected(viewHolder.itemView); + } + } + + private int getMaxDragScroll(RecyclerView recyclerView) { + if (mCachedMaxScrollSpeed == -1) { + mCachedMaxScrollSpeed = AndroidUtilities.dp(20); + } + return mCachedMaxScrollSpeed; + } + + /** + * Called when {@link #onMove(RecyclerView, ViewHolder, ViewHolder)} returns true. + *

+ * ItemTouchHelper does not create an extra Bitmap or View while dragging, instead, it + * modifies the existing View. Because of this reason, it is important that the View is + * still part of the layout after it is moved. This may not work as intended when swapped + * Views are close to RecyclerView bounds or there are gaps between them (e.g. other Views + * which were not eligible for dropping over). + *

+ * This method is responsible to give necessary hint to the LayoutManager so that it will + * keep the View in visible area. For example, for LinearLayoutManager, this is as simple + * as calling {@link LinearLayoutManager#scrollToPositionWithOffset(int, int)}. + * + * Default implementation calls {@link RecyclerView#scrollToPosition(int)} if the View's + * new position is likely to be out of bounds. + *

+ * It is important to ensure the ViewHolder will stay visible as otherwise, it might be + * removed by the LayoutManager if the move causes the View to go out of bounds. In that + * case, drag will end prematurely. + * + * @param recyclerView The RecyclerView controlled by the ItemTouchHelper. + * @param viewHolder The ViewHolder under user's control. + * @param fromPos The previous adapter position of the dragged item (before it was + * moved). + * @param target The ViewHolder on which the currently active item has been dropped. + * @param toPos The new adapter position of the dragged item. + * @param x The updated left value of the dragged View after drag translations + * are applied. This value does not include margins added by + * {@link RecyclerView.ItemDecoration}s. + * @param y The updated top value of the dragged View after drag translations + * are applied. This value does not include margins added by + * {@link RecyclerView.ItemDecoration}s. + */ + public void onMoved(final RecyclerView recyclerView, + final ViewHolder viewHolder, int fromPos, final ViewHolder target, int toPos, int x, + int y) { + final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); + if (layoutManager instanceof ViewDropHandler) { + ((ViewDropHandler) layoutManager).prepareForDrop(viewHolder.itemView, + target.itemView, x, y); + return; + } + + // if layout manager cannot handle it, do some guesswork + if (layoutManager.canScrollHorizontally()) { + final int minLeft = layoutManager.getDecoratedLeft(target.itemView); + if (minLeft <= recyclerView.getPaddingLeft()) { + recyclerView.scrollToPosition(toPos); + } + final int maxRight = layoutManager.getDecoratedRight(target.itemView); + if (maxRight >= recyclerView.getWidth() - recyclerView.getPaddingRight()) { + recyclerView.scrollToPosition(toPos); + } + } + + if (layoutManager.canScrollVertically()) { + final int minTop = layoutManager.getDecoratedTop(target.itemView); + if (minTop <= recyclerView.getPaddingTop()) { + recyclerView.scrollToPosition(toPos); + } + final int maxBottom = layoutManager.getDecoratedBottom(target.itemView); + if (maxBottom >= recyclerView.getHeight() - recyclerView.getPaddingBottom()) { + recyclerView.scrollToPosition(toPos); + } + } + } + + private void onDraw(Canvas c, RecyclerView parent, ViewHolder selected, + List recoverAnimationList, + int actionState, float dX, float dY) { + final int recoverAnimSize = recoverAnimationList.size(); + for (int i = 0; i < recoverAnimSize; i++) { + final ItemTouchHelper.RecoverAnimation anim = recoverAnimationList.get(i); + anim.update(); + final int count = c.save(); + onChildDraw(c, parent, anim.mViewHolder, anim.mX, anim.mY, anim.mActionState, + false); + c.restoreToCount(count); + } + if (selected != null) { + final int count = c.save(); + onChildDraw(c, parent, selected, dX, dY, actionState, true); + c.restoreToCount(count); + } + } + + private void onDrawOver(Canvas c, RecyclerView parent, ViewHolder selected, + List recoverAnimationList, + int actionState, float dX, float dY) { + final int recoverAnimSize = recoverAnimationList.size(); + for (int i = 0; i < recoverAnimSize; i++) { + final ItemTouchHelper.RecoverAnimation anim = recoverAnimationList.get(i); + final int count = c.save(); + onChildDrawOver(c, parent, anim.mViewHolder, anim.mX, anim.mY, anim.mActionState, + false); + c.restoreToCount(count); + } + if (selected != null) { + final int count = c.save(); + onChildDrawOver(c, parent, selected, dX, dY, actionState, true); + c.restoreToCount(count); + } + boolean hasRunningAnimation = false; + for (int i = recoverAnimSize - 1; i >= 0; i--) { + final RecoverAnimation anim = recoverAnimationList.get(i); + if (anim.mEnded && !anim.mIsPendingCleanup) { + recoverAnimationList.remove(i); + anim.mViewHolder.setIsRecyclable(true); + } else if (!anim.mEnded) { + hasRunningAnimation = true; + } + } + if (hasRunningAnimation) { + parent.invalidate(); + } + } + + /** + * Called by the ItemTouchHelper when the user interaction with an element is over and it + * also completed its animation. + *

+ * This is a good place to clear all changes on the View that was done in + * {@link #onSelectedChanged(RecyclerView.ViewHolder, int)}, + * {@link #onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int, + * boolean)} or + * {@link #onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, boolean)}. + * + * @param recyclerView The RecyclerView which is controlled by the ItemTouchHelper. + * @param viewHolder The View that was interacted by the user. + */ + public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) { + sUICallback.clearView(viewHolder.itemView); + } + + /** + * Called by ItemTouchHelper on RecyclerView's onDraw callback. + *

+ * If you would like to customize how your View's respond to user interactions, this is + * a good place to override. + *

+ * Default implementation translates the child by the given dX, + * dY. + * ItemTouchHelper also takes care of drawing the child after other children if it is being + * dragged. This is done using child re-ordering mechanism. On platforms prior to L, this + * is + * achieved via {@link android.view.ViewGroup#getChildDrawingOrder(int, int)} and on L + * and after, it changes View's elevation value to be greater than all other children.) + * + * @param c The canvas which RecyclerView is drawing its children + * @param recyclerView The RecyclerView to which ItemTouchHelper is attached to + * @param viewHolder The ViewHolder which is being interacted by the User or it was + * interacted and simply animating to its original position + * @param dX The amount of horizontal displacement caused by user's action + * @param dY The amount of vertical displacement caused by user's action + * @param actionState The type of interaction on the View. Is either {@link + * #ACTION_STATE_DRAG} or {@link #ACTION_STATE_SWIPE}. + * @param isCurrentlyActive True if this view is currently being controlled by the user or + * false it is simply animating back to its original state. + * @see #onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, + * boolean) + */ + public void onChildDraw(Canvas c, RecyclerView recyclerView, + ViewHolder viewHolder, + float dX, float dY, int actionState, boolean isCurrentlyActive) { + sUICallback.onDraw(c, recyclerView, viewHolder.itemView, dX, dY, actionState, + isCurrentlyActive); + } + + /** + * Called by ItemTouchHelper on RecyclerView's onDraw callback. + *

+ * If you would like to customize how your View's respond to user interactions, this is + * a good place to override. + *

+ * Default implementation translates the child by the given dX, + * dY. + * ItemTouchHelper also takes care of drawing the child after other children if it is being + * dragged. This is done using child re-ordering mechanism. On platforms prior to L, this + * is + * achieved via {@link android.view.ViewGroup#getChildDrawingOrder(int, int)} and on L + * and after, it changes View's elevation value to be greater than all other children.) + * + * @param c The canvas which RecyclerView is drawing its children + * @param recyclerView The RecyclerView to which ItemTouchHelper is attached to + * @param viewHolder The ViewHolder which is being interacted by the User or it was + * interacted and simply animating to its original position + * @param dX The amount of horizontal displacement caused by user's action + * @param dY The amount of vertical displacement caused by user's action + * @param actionState The type of interaction on the View. Is either {@link + * #ACTION_STATE_DRAG} or {@link #ACTION_STATE_SWIPE}. + * @param isCurrentlyActive True if this view is currently being controlled by the user or + * false it is simply animating back to its original state. + * @see #onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, + * boolean) + */ + public void onChildDrawOver(Canvas c, RecyclerView recyclerView, + ViewHolder viewHolder, + float dX, float dY, int actionState, boolean isCurrentlyActive) { + sUICallback.onDrawOver(c, recyclerView, viewHolder.itemView, dX, dY, actionState, + isCurrentlyActive); + } + + /** + * Called by the ItemTouchHelper when user action finished on a ViewHolder and now the View + * will be animated to its final position. + *

+ * Default implementation uses ItemAnimator's duration values. If + * animationType is {@link #ANIMATION_TYPE_DRAG}, it returns + * {@link RecyclerView.ItemAnimator#getMoveDuration()}, otherwise, it returns + * {@link RecyclerView.ItemAnimator#getRemoveDuration()}. If RecyclerView does not have + * any {@link RecyclerView.ItemAnimator} attached, this method returns + * {@code DEFAULT_DRAG_ANIMATION_DURATION} or {@code DEFAULT_SWIPE_ANIMATION_DURATION} + * depending on the animation type. + * + * @param recyclerView The RecyclerView to which the ItemTouchHelper is attached to. + * @param animationType The type of animation. Is one of {@link #ANIMATION_TYPE_DRAG}, + * {@link #ANIMATION_TYPE_SWIPE_CANCEL} or + * {@link #ANIMATION_TYPE_SWIPE_SUCCESS}. + * @param animateDx The horizontal distance that the animation will offset + * @param animateDy The vertical distance that the animation will offset + * @return The duration for the animation + */ + public long getAnimationDuration(RecyclerView recyclerView, int animationType, + float animateDx, float animateDy) { + final RecyclerView.ItemAnimator itemAnimator = recyclerView.getItemAnimator(); + if (itemAnimator == null) { + return animationType == ANIMATION_TYPE_DRAG ? DEFAULT_DRAG_ANIMATION_DURATION + : DEFAULT_SWIPE_ANIMATION_DURATION; + } else { + return animationType == ANIMATION_TYPE_DRAG ? itemAnimator.getMoveDuration() + : itemAnimator.getRemoveDuration(); + } + } + + /** + * Called by the ItemTouchHelper when user is dragging a view out of bounds. + *

+ * You can override this method to decide how much RecyclerView should scroll in response + * to this action. Default implementation calculates a value based on the amount of View + * out of bounds and the time it spent there. The longer user keeps the View out of bounds, + * the faster the list will scroll. Similarly, the larger portion of the View is out of + * bounds, the faster the RecyclerView will scroll. + * + * @param recyclerView The RecyclerView instance to which ItemTouchHelper is attached + * to. + * @param viewSize The total size of the View in scroll direction, excluding + * item decorations. + * @param viewSizeOutOfBounds The total size of the View that is out of bounds. This value + * is negative if the View is dragged towards left or top edge. + * @param totalSize The total size of RecyclerView in the scroll direction. + * @param msSinceStartScroll The time passed since View is kept out of bounds. + * + * @return The amount that RecyclerView should scroll. Keep in mind that this value will + * be passed to {@link RecyclerView#scrollBy(int, int)} method. + */ + public int interpolateOutOfBoundsScroll(RecyclerView recyclerView, + int viewSize, int viewSizeOutOfBounds, + int totalSize, long msSinceStartScroll) { + final int maxScroll = getMaxDragScroll(recyclerView); + final int absOutOfBounds = Math.abs(viewSizeOutOfBounds); + final int direction = (int) Math.signum(viewSizeOutOfBounds); + // might be negative if other direction + float outOfBoundsRatio = Math.min(1f, 1f * absOutOfBounds / viewSize); + final int cappedScroll = (int) (direction * maxScroll * + sDragViewScrollCapInterpolator.getInterpolation(outOfBoundsRatio)); + final float timeRatio; + if (msSinceStartScroll > DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS) { + timeRatio = 1f; + } else { + timeRatio = (float) msSinceStartScroll / DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS; + } + final int value = (int) (cappedScroll * sDragScrollInterpolator + .getInterpolation(timeRatio)); + if (value == 0) { + return viewSizeOutOfBounds > 0 ? 1 : -1; + } + return value; + } + } + + /** + * A simple wrapper to the default Callback which you can construct with drag and swipe + * directions and this class will handle the flag callbacks. You should still override onMove + * or + * onSwiped depending on your use case. + * + *

+     * ItemTouchHelper mIth = new ItemTouchHelper(
+     *     new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
+     *         ItemTouchHelper.LEFT) {
+     *         public abstract boolean onMove(RecyclerView recyclerView,
+     *             ViewHolder viewHolder, ViewHolder target) {
+     *             final int fromPos = viewHolder.getAdapterPosition();
+     *             final int toPos = viewHolder.getAdapterPosition();
+     *             // move item in `fromPos` to `toPos` in adapter.
+     *             return true;// true if moved, false otherwise
+     *         }
+     *         public void onSwiped(ViewHolder viewHolder, int direction) {
+     *             // remove from adapter
+     *         }
+     * });
+     * 
+ */ + public abstract static class SimpleCallback extends Callback { + + private int mDefaultSwipeDirs; + + private int mDefaultDragDirs; + + /** + * Creates a Callback for the given drag and swipe allowance. These values serve as + * defaults + * and if you want to customize behavior per ViewHolder, you can override + * {@link #getSwipeDirs(RecyclerView, ViewHolder)} + * and / or {@link #getDragDirs(RecyclerView, ViewHolder)}. + * + * @param dragDirs Binary OR of direction flags in which the Views can be dragged. Must be + * composed of {@link #LEFT}, {@link #RIGHT}, {@link #START}, {@link + * #END}, + * {@link #UP} and {@link #DOWN}. + * @param swipeDirs Binary OR of direction flags in which the Views can be swiped. Must be + * composed of {@link #LEFT}, {@link #RIGHT}, {@link #START}, {@link + * #END}, + * {@link #UP} and {@link #DOWN}. + */ + public SimpleCallback(int dragDirs, int swipeDirs) { + mDefaultSwipeDirs = swipeDirs; + mDefaultDragDirs = dragDirs; + } + + /** + * Updates the default swipe directions. For example, you can use this method to toggle + * certain directions depending on your use case. + * + * @param defaultSwipeDirs Binary OR of directions in which the ViewHolders can be swiped. + */ + public void setDefaultSwipeDirs(int defaultSwipeDirs) { + mDefaultSwipeDirs = defaultSwipeDirs; + } + + /** + * Updates the default drag directions. For example, you can use this method to toggle + * certain directions depending on your use case. + * + * @param defaultDragDirs Binary OR of directions in which the ViewHolders can be dragged. + */ + public void setDefaultDragDirs(int defaultDragDirs) { + mDefaultDragDirs = defaultDragDirs; + } + + /** + * Returns the swipe directions for the provided ViewHolder. + * Default implementation returns the swipe directions that was set via constructor or + * {@link #setDefaultSwipeDirs(int)}. + * + * @param recyclerView The RecyclerView to which the ItemTouchHelper is attached to. + * @param viewHolder The RecyclerView for which the swipe drection is queried. + * @return A binary OR of direction flags. + */ + public int getSwipeDirs(RecyclerView recyclerView, ViewHolder viewHolder) { + return mDefaultSwipeDirs; + } + + /** + * Returns the drag directions for the provided ViewHolder. + * Default implementation returns the drag directions that was set via constructor or + * {@link #setDefaultDragDirs(int)}. + * + * @param recyclerView The RecyclerView to which the ItemTouchHelper is attached to. + * @param viewHolder The RecyclerView for which the swipe drection is queried. + * @return A binary OR of direction flags. + */ + public int getDragDirs(RecyclerView recyclerView, ViewHolder viewHolder) { + return mDefaultDragDirs; + } + + @Override + public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) { + return makeMovementFlags(getDragDirs(recyclerView, viewHolder), + getSwipeDirs(recyclerView, viewHolder)); + } + } + + private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener { + + @Override + public boolean onDown(MotionEvent e) { + return true; + } + + @Override + public void onLongPress(MotionEvent e) { + View child = findChildView(e); + if (child != null) { + ViewHolder vh = mRecyclerView.getChildViewHolder(child); + if (vh != null) { + if (!mCallback.hasDragFlag(mRecyclerView, vh)) { + return; + } + int pointerId = MotionEventCompat.getPointerId(e, 0); + // Long press is deferred. + // Check w/ active pointer id to avoid selecting after motion + // event is canceled. + if (pointerId == mActivePointerId) { + final int index = MotionEventCompat + .findPointerIndex(e, mActivePointerId); + final float x = MotionEventCompat.getX(e, index); + final float y = MotionEventCompat.getY(e, index); + mInitialTouchX = x; + mInitialTouchY = y; + mDx = mDy = 0f; + if (DEBUG) { + Log.d(TAG, + "onlong press: x:" + mInitialTouchX + ",y:" + mInitialTouchY); + } + if (mCallback.isLongPressDragEnabled()) { + select(vh, ACTION_STATE_DRAG); + } + } + } + } + } + } + + private class RecoverAnimation implements AnimatorListenerCompat { + + final float mStartDx; + + final float mStartDy; + + final float mTargetX; + + final float mTargetY; + + final ViewHolder mViewHolder; + + final int mActionState; + + private final ValueAnimatorCompat mValueAnimator; + + private final int mAnimationType; + + public boolean mIsPendingCleanup; + + float mX; + + float mY; + + // if user starts touching a recovering view, we put it into interaction mode again, + // instantly. + boolean mOverridden = false; + + private boolean mEnded = false; + + private float mFraction; + + public RecoverAnimation(ViewHolder viewHolder, int animationType, + int actionState, float startDx, float startDy, float targetX, float targetY) { + mActionState = actionState; + mAnimationType = animationType; + mViewHolder = viewHolder; + mStartDx = startDx; + mStartDy = startDy; + mTargetX = targetX; + mTargetY = targetY; + mValueAnimator = AnimatorCompatHelper.emptyValueAnimator(); + mValueAnimator.addUpdateListener( + new AnimatorUpdateListenerCompat() { + @Override + public void onAnimationUpdate(ValueAnimatorCompat animation) { + setFraction(animation.getAnimatedFraction()); + } + }); + mValueAnimator.setTarget(viewHolder.itemView); + mValueAnimator.addListener(this); + setFraction(0f); + } + + public void setDuration(long duration) { + mValueAnimator.setDuration(duration); + } + + public void start() { + mViewHolder.setIsRecyclable(false); + mValueAnimator.start(); + } + + public void cancel() { + mValueAnimator.cancel(); + } + + public void setFraction(float fraction) { + mFraction = fraction; + } + + /** + * We run updates on onDraw method but use the fraction from animator callback. + * This way, we can sync translate x/y values w/ the animators to avoid one-off frames. + */ + public void update() { + if (mStartDx == mTargetX) { + mX = ViewCompat.getTranslationX(mViewHolder.itemView); + } else { + mX = mStartDx + mFraction * (mTargetX - mStartDx); + } + if (mStartDy == mTargetY) { + mY = ViewCompat.getTranslationY(mViewHolder.itemView); + } else { + mY = mStartDy + mFraction * (mTargetY - mStartDy); + } + } + + @Override + public void onAnimationStart(ValueAnimatorCompat animation) { + + } + + @Override + public void onAnimationEnd(ValueAnimatorCompat animation) { + mEnded = true; + } + + @Override + public void onAnimationCancel(ValueAnimatorCompat animation) { + setFraction(1f); //make sure we recover the view's state. + } + + @Override + public void onAnimationRepeat(ValueAnimatorCompat animation) { + + } + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtil.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtil.java new file mode 100644 index 000000000..22cb8061b --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtil.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.telegram.android.support.widget.helper; + +import android.graphics.Canvas; +import android.view.View; + +import org.telegram.android.support.widget.RecyclerView; + +/** + * Utility class for {@link ItemTouchHelper} which handles item transformations for different + * API versions. + *

+ * This class has methods that map to {@link ItemTouchHelper.Callback}'s drawing methods. Default + * implementations in {@link ItemTouchHelper.Callback} call these methods with + * {@link RecyclerView.ViewHolder#itemView} and {@link ItemTouchUIUtil} makes necessary changes + * on the View depending on the API level. You can access the instance of {@link ItemTouchUIUtil} + * via {@link ItemTouchHelper.Callback#getDefaultUIUtil()} and call its methods with the children + * of ViewHolder that you want to apply default effects. + * + * @see ItemTouchHelper.Callback#getDefaultUIUtil() + */ +public interface ItemTouchUIUtil { + + /** + * The default implementation for {@link ItemTouchHelper.Callback#onChildDraw(Canvas, + * RecyclerView, RecyclerView.ViewHolder, float, float, int, boolean)} + */ + void onDraw(Canvas c, RecyclerView recyclerView, View view, + float dX, float dY, int actionState, boolean isCurrentlyActive); + + /** + * The default implementation for {@link ItemTouchHelper.Callback#onChildDrawOver(Canvas, + * RecyclerView, RecyclerView.ViewHolder, float, float, int, boolean)} + */ + void onDrawOver(Canvas c, RecyclerView recyclerView, View view, + float dX, float dY, int actionState, boolean isCurrentlyActive); + + /** + * The default implementation for {@link ItemTouchHelper.Callback#clearView(RecyclerView, + * RecyclerView.ViewHolder)} + */ + void clearView(View view); + + /** + * The default implementation for {@link ItemTouchHelper.Callback#onSelectedChanged( + * RecyclerView.ViewHolder, int)} + */ + void onSelected(View view); +} + diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtilImpl.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtilImpl.java new file mode 100644 index 000000000..63a492beb --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtilImpl.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.telegram.android.support.widget.helper; + +import android.graphics.Canvas; +import android.support.v4.view.ViewCompat; +import org.telegram.android.support.widget.RecyclerView; +import android.view.View; + + +/** + * Package private class to keep implementations. Putting them inside ItemTouchUIUtil makes them + * public API, which is not desired in this case. + */ +class ItemTouchUIUtilImpl { + final static int item_touch_helper_previous_elevation = 123; + static class Lollipop extends Honeycomb { + @Override + public void onDraw(Canvas c, RecyclerView recyclerView, View view, + float dX, float dY, int actionState, boolean isCurrentlyActive) { + if (isCurrentlyActive) { + Object originalElevation = view.getTag(item_touch_helper_previous_elevation); + if (originalElevation == null) { + originalElevation = ViewCompat.getElevation(view); + float newElevation = 1f + findMaxElevation(recyclerView, view); + ViewCompat.setElevation(view, newElevation); + view.setTag(item_touch_helper_previous_elevation, originalElevation); + } + } + super.onDraw(c, recyclerView, view, dX, dY, actionState, isCurrentlyActive); + } + + private float findMaxElevation(RecyclerView recyclerView, View itemView) { + final int childCount = recyclerView.getChildCount(); + float max = 0; + for (int i = 0; i < childCount; i++) { + final View child = recyclerView.getChildAt(i); + if (child == itemView) { + continue; + } + final float elevation = ViewCompat.getElevation(child); + if (elevation > max) { + max = elevation; + } + } + return max; + } + + @Override + public void clearView(View view) { + final Object tag = view.getTag(item_touch_helper_previous_elevation); + if (tag != null && tag instanceof Float) { + ViewCompat.setElevation(view, (Float) tag); + } + view.setTag(item_touch_helper_previous_elevation, null); + super.clearView(view); + } + } + + static class Honeycomb implements ItemTouchUIUtil { + + @Override + public void clearView(View view) { + ViewCompat.setTranslationX(view, 0f); + ViewCompat.setTranslationY(view, 0f); + } + + @Override + public void onSelected(View view) { + + } + + @Override + public void onDraw(Canvas c, RecyclerView recyclerView, View view, + float dX, float dY, int actionState, boolean isCurrentlyActive) { + ViewCompat.setTranslationX(view, dX); + ViewCompat.setTranslationY(view, dY); + } + + @Override + public void onDrawOver(Canvas c, RecyclerView recyclerView, + View view, float dX, float dY, int actionState, boolean isCurrentlyActive) { + + } + } + + static class Gingerbread implements ItemTouchUIUtil { + + private void draw(Canvas c, RecyclerView parent, View view, + float dX, float dY) { + c.save(); + c.translate(dX, dY); + parent.drawChild(c, view, 0); + c.restore(); + } + + @Override + public void clearView(View view) { + view.setVisibility(View.VISIBLE); + } + + @Override + public void onSelected(View view) { + view.setVisibility(View.INVISIBLE); + } + + @Override + public void onDraw(Canvas c, RecyclerView recyclerView, View view, + float dX, float dY, int actionState, boolean isCurrentlyActive) { + if (actionState != ItemTouchHelper.ACTION_STATE_DRAG) { + draw(c, recyclerView, view, dX, dY); + } + } + + @Override + public void onDrawOver(Canvas c, RecyclerView recyclerView, + View view, float dX, float dY, + int actionState, boolean isCurrentlyActive) { + if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { + draw(c, recyclerView, view, dX, dY); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/util/SortedListAdapterCallback.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/util/SortedListAdapterCallback.java index 44ddd667e..2457f4932 100644 --- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/util/SortedListAdapterCallback.java +++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/util/SortedListAdapterCallback.java @@ -16,7 +16,7 @@ package org.telegram.android.support.widget.util; -import android.support.v7.util.SortedList; +import org.telegram.android.support.util.SortedList; import org.telegram.android.support.widget.RecyclerView; /** diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index c7b0937a6..575d1e217 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -90,7 +90,6 @@ public class ApplicationLoader extends Application { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); int selectedBackground = preferences.getInt("selectedBackground", 1000001); selectedColor = preferences.getInt("selectedColor", 0); - int cacheColorHint = 0; if (selectedColor == 0) { if (selectedBackground == 1000001) { cachedWallpaper = applicationContext.getResources().getDrawable(R.drawable.background_hd); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java index 928d5e572..3f1dafe5b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java @@ -363,7 +363,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. try { SerializedData data = new SerializedData(configFile); isTestBackend = data.readInt32(false); - int version = data.readInt32(false); + data.readInt32(false); sessionsToDestroy.clear(); int count = data.readInt32(false); for (int a = 0; a < count; a++) { @@ -2700,7 +2700,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection. return; } - int messageLength = data.readInt32(false); + data.readInt32(false); TLObject message = deserialize(getRequestWithMessageId(messageId), data, true); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 2a006d37b..e7268e2ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -28,6 +28,7 @@ public class FileLoadOperation { private final static int stateFinished = 3; private final static int downloadChunkSize = 1024 * 32; + private final static int downloadChunkSizeBig = 1024 * 128; private final static int maxDownloadRequests = 3; private int datacenter_id; @@ -38,6 +39,7 @@ public class FileLoadOperation { private FileLoadOperationDelegate delegate; private byte[] key; private byte[] iv; + private int currentDownloadChunkSize; private int nextDownloadOffset = 0; private ArrayList requestInfos = new ArrayList<>(maxDownloadRequests); @@ -165,6 +167,7 @@ public class FileLoadOperation { if (state != stateIdle) { return; } + currentDownloadChunkSize = totalBytesCount >= 1024 * 1024 * 30 ? downloadChunkSizeBig : downloadChunkSize; state = stateDownloading; if (location == null) { Utilities.stageQueue.postRunnable(new Runnable() { @@ -175,7 +178,6 @@ public class FileLoadOperation { }); return; } - Long mediaId = null; String fileNameFinal; String fileNameTemp; String fileNameIv = null; @@ -223,7 +225,7 @@ public class FileLoadOperation { cacheFileTemp = new File(tempPath, fileNameTemp); if (cacheFileTemp.exists()) { downloadedBytes = (int)cacheFileTemp.length(); - nextDownloadOffset = downloadedBytes = downloadedBytes / 1024 * 1024; + nextDownloadOffset = downloadedBytes = downloadedBytes / currentDownloadChunkSize * currentDownloadChunkSize; } if (fileNameIv != null) { cacheIvTemp = new File(tempPath, fileNameIv); @@ -388,10 +390,10 @@ public class FileLoadOperation { } } - if (currentBytesSize != downloadChunkSize) { + if (currentBytesSize != currentDownloadChunkSize) { onFinishLoadingFile(); } else { - if (totalBytesCount != downloadedBytes && downloadedBytes % downloadChunkSize == 0 || totalBytesCount > 0 && totalBytesCount > downloadedBytes) { + if (totalBytesCount != downloadedBytes && downloadedBytes % currentDownloadChunkSize == 0 || totalBytesCount > 0 && totalBytesCount > downloadedBytes) { startDownloadRequest(); } else { onFinishLoadingFile(); @@ -422,7 +424,7 @@ public class FileLoadOperation { startDownloadRequest(); } } else if (error.text.contains("OFFSET_INVALID")) { - if (downloadedBytes % downloadChunkSize == 0) { + if (downloadedBytes % currentDownloadChunkSize == 0) { try { onFinishLoadingFile(); } catch (Exception e) { @@ -460,12 +462,12 @@ public class FileLoadOperation { if (totalBytesCount > 0 && nextDownloadOffset >= totalBytesCount) { break; } - boolean isLast = totalBytesCount <= 0 || a == count - 1 || totalBytesCount > 0 && nextDownloadOffset + downloadChunkSize >= totalBytesCount; + boolean isLast = totalBytesCount <= 0 || a == count - 1 || totalBytesCount > 0 && nextDownloadOffset + currentDownloadChunkSize >= totalBytesCount; TLRPC.TL_upload_getFile req = new TLRPC.TL_upload_getFile(); req.location = location; req.offset = nextDownloadOffset; - req.limit = downloadChunkSize; - nextDownloadOffset += downloadChunkSize; + req.limit = currentDownloadChunkSize; + nextDownloadOffset += currentDownloadChunkSize; final RequestInfo requestInfo = new RequestInfo(); requestInfos.add(requestInfo); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 2860c3cc9..19ebeba03 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -675,6 +675,15 @@ public class FileLoader { return closestObject; } + public static String getFileExtension(File file) { + String name = file.getName(); + try { + return name.substring(name.lastIndexOf(".") + 1); + } catch (Exception e) { + return ""; + } + } + public static String getDocumentFileName(TLRPC.Document document) { if (document != null) { if (document.file_name != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java b/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java index 7043dca59..b99706fe0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java @@ -637,7 +637,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti FileLog.d("tmessages", String.format("===== Duplicate message id %d received, ignoring", messageId)); return; } - int messageLength = data.readInt32(false); + data.readInt32(false); int constructor = data.readInt32(false); TLObject object = TLClassStore.Instance().TLdeserialize(data, constructor, false); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java index 5de616dc4..954025cc1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java @@ -11634,6 +11634,9 @@ public class TLRPC { case 0x9eddf188: result = new TL_inputMessagesFilterDocument(); break; + case 0x5afbf764: + result = new TL_inputMessagesFilterAudioDocuments(); + break; case 0x9fc00e65: result = new TL_inputMessagesFilterVideo(); break; @@ -11672,6 +11675,15 @@ public class TLRPC { } } + public static class TL_inputMessagesFilterAudioDocuments extends MessagesFilter { + public static int constructor = 0x5afbf764; + + + public void serializeToStream(AbsSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_inputMessagesFilterVideo extends MessagesFilter { public static int constructor = 0x9fc00e65; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java b/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java index 217e63fb1..417d5c4e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java @@ -143,7 +143,7 @@ public class TcpConnection extends ConnectionContext { FileLog.e("tmessages", e2); } - FileLog.d("tmessages", String.format(TcpConnection.this + " Connecting (%s:%d)", hostAddress, hostPort)); + FileLog.d("tmessages", String.format(TcpConnection.this + " Connecting (%s:%d), connection class %d", hostAddress, hostPort, transportRequestClass)); firstPacket = true; if (restOfTheData != null) { BuffersStorage.getInstance().reuseFreeBuffer(restOfTheData); 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 7ddad2ce3..358725c23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -15,7 +15,6 @@ import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; @@ -23,6 +22,7 @@ import android.widget.ImageView; import android.widget.TextView; import org.telegram.android.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; import org.telegram.ui.Components.LayoutHelper; @@ -38,7 +38,6 @@ public class ActionBar extends FrameLayout { } } - private FrameLayout titleFrameLayout; private ImageView backButtonImageView; private TextView titleTextView; private TextView subTitleTextView; @@ -60,116 +59,6 @@ public class ActionBar extends FrameLayout { public ActionBar(Context context) { super(context); - titleFrameLayout = new FrameLayout(context); - addView(titleFrameLayout); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)titleFrameLayout.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.gravity = Gravity.TOP | Gravity.LEFT; - titleFrameLayout.setLayoutParams(layoutParams); - titleFrameLayout.setPadding(0, 0, AndroidUtilities.dp(4), 0); - titleFrameLayout.setEnabled(false); - } - - private void positionBackImage(int height) { - if (backButtonImageView != null) { - LayoutParams layoutParams = (LayoutParams)backButtonImageView.getLayoutParams(); - layoutParams.width = AndroidUtilities.dp(54); - layoutParams.height = height; - layoutParams.gravity = Gravity.TOP | Gravity.LEFT; - backButtonImageView.setLayoutParams(layoutParams); - } - } - - private void positionTitle(int width, int height) { - int offset = AndroidUtilities.dp(2); - if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { - offset = AndroidUtilities.dp(1); - } - int maxTextWidth = 0; - - LayoutParams layoutParams; - - if (titleTextView != null && titleTextView.getVisibility() == VISIBLE) { - if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { - titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - } else { - titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - } - - layoutParams = (LayoutParams) titleTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.TOP | Gravity.LEFT; - titleTextView.setLayoutParams(layoutParams); - titleTextView.measure(width, height); - maxTextWidth = titleTextView.getMeasuredWidth(); - } - if (subTitleTextView != null && subTitleTextView.getVisibility() == VISIBLE) { - if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { - subTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - } else { - subTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - } - - layoutParams = (LayoutParams) subTitleTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.gravity = Gravity.TOP | Gravity.LEFT; - subTitleTextView.setLayoutParams(layoutParams); - subTitleTextView.measure(width, height); - maxTextWidth = Math.max(maxTextWidth, subTitleTextView.getMeasuredWidth()); - } - - int x; - if (backButtonImageView != null && backButtonImageView.getVisibility() == VISIBLE) { - x = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 80 : 72); - } else { - x = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 26 : 18); - } - - if (menu != null) { - maxTextWidth = Math.min(maxTextWidth, width - menu.getMeasuredWidth() - AndroidUtilities.dp(16) - x); - } - - if (titleTextView != null && titleTextView.getVisibility() == VISIBLE) { - layoutParams = (LayoutParams) titleTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = titleTextView.getMeasuredHeight(); - int y; - if (subTitleTextView != null && subTitleTextView.getVisibility() == VISIBLE) { - y = (height / 2 - titleTextView.getMeasuredHeight()) / 2 + offset; - } else { - y = (height - titleTextView.getMeasuredHeight()) / 2 - AndroidUtilities.dp(1); - } - layoutParams.setMargins(x, y, 0, 0); - titleTextView.setLayoutParams(layoutParams); - } - if (subTitleTextView != null && subTitleTextView.getVisibility() == VISIBLE) { - layoutParams = (LayoutParams) subTitleTextView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = subTitleTextView.getMeasuredHeight(); - layoutParams.setMargins(x, height / 2 + (height / 2 - subTitleTextView.getMeasuredHeight()) / 2 - offset, 0, 0); - subTitleTextView.setLayoutParams(layoutParams); - } - - MarginLayoutParams layoutParams1 = (MarginLayoutParams) titleFrameLayout.getLayoutParams(); - layoutParams1.width = x + maxTextWidth + (isSearchFieldVisible ? 0 : AndroidUtilities.dp(6)); - layoutParams1.topMargin = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0; - titleFrameLayout.setLayoutParams(layoutParams1); - } - - public void positionMenu(int width, int height) { - if (menu == null) { - return; - } - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)menu.getLayoutParams(); - layoutParams.width = isSearchFieldVisible ? LayoutHelper.MATCH_PARENT : LayoutHelper.WRAP_CONTENT; - layoutParams.height = height; - layoutParams.leftMargin = isSearchFieldVisible ? AndroidUtilities.dp(AndroidUtilities.isTablet() ? 74 : 66) : 0; - layoutParams.topMargin = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0; - menu.setLayoutParams(layoutParams); - menu.measure(width, height); } private void createBackButtonImage() { @@ -177,9 +66,10 @@ public class ActionBar extends FrameLayout { return; } backButtonImageView = new ImageView(getContext()); - titleFrameLayout.addView(backButtonImageView); backButtonImageView.setScaleType(ImageView.ScaleType.CENTER); backButtonImageView.setBackgroundResource(itemsBackgroundResourceId); + addView(backButtonImageView, LayoutHelper.createFrame(54, 54, Gravity.LEFT | Gravity.TOP)); + backButtonImageView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -195,31 +85,19 @@ public class ActionBar extends FrameLayout { } public void setBackButtonDrawable(Drawable drawable) { - boolean reposition = false; if (backButtonImageView == null) { createBackButtonImage(); - } else { - reposition = true; } backButtonImageView.setVisibility(drawable == null ? GONE : VISIBLE); backButtonImageView.setImageDrawable(drawable); - if (reposition) { - positionTitle(getMeasuredWidth(), getMeasuredHeight()); - } } public void setBackButtonImage(int resource) { - boolean reposition = false; if (backButtonImageView == null) { createBackButtonImage(); - } else { - reposition = true; } backButtonImageView.setVisibility(resource == 0 ? GONE : VISIBLE); backButtonImageView.setImageResource(resource); - if (reposition) { - positionTitle(getMeasuredWidth(), getMeasuredHeight()); - } } private void createSubtitleTextView() { @@ -227,13 +105,13 @@ public class ActionBar extends FrameLayout { return; } subTitleTextView = new TextView(getContext()); - titleFrameLayout.addView(subTitleTextView); subTitleTextView.setGravity(Gravity.LEFT); subTitleTextView.setTextColor(0xffd7e8f7); subTitleTextView.setSingleLine(true); subTitleTextView.setLines(1); subTitleTextView.setMaxLines(1); subTitleTextView.setEllipsize(TextUtils.TruncateAt.END); + addView(subTitleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); } public void setSubtitle(CharSequence value) { @@ -243,22 +121,6 @@ public class ActionBar extends FrameLayout { if (subTitleTextView != null) { subTitleTextView.setVisibility(value != null && !isSearchFieldVisible ? VISIBLE : INVISIBLE); subTitleTextView.setText(value); - positionTitle(getMeasuredWidth(), getMeasuredHeight()); - } - } - - public void setSubTitleIcon(int resourceId, Drawable drawable, int padding) { - if ((resourceId != 0 || drawable != null) && subTitleTextView == null) { - createSubtitleTextView(); - positionTitle(getMeasuredWidth(), getMeasuredHeight()); - } - if (subTitleTextView != null) { - if (drawable != null) { - subTitleTextView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); - } else { - subTitleTextView.setCompoundDrawablesWithIntrinsicBounds(resourceId, 0, 0, 0); - } - subTitleTextView.setCompoundDrawablePadding(padding); } } @@ -268,39 +130,32 @@ public class ActionBar extends FrameLayout { } titleTextView = new TextView(getContext()); titleTextView.setGravity(Gravity.LEFT); - titleTextView.setSingleLine(true); titleTextView.setLines(1); titleTextView.setMaxLines(1); + titleTextView.setSingleLine(true); titleTextView.setEllipsize(TextUtils.TruncateAt.END); - titleFrameLayout.addView(titleTextView); titleTextView.setTextColor(0xffffffff); titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP)); } public void setTitle(CharSequence value) { - boolean created = false; if (value != null && titleTextView == null) { createTitleTextView(); - created = true; } if (titleTextView != null) { lastTitle = value; titleTextView.setVisibility(value != null && !isSearchFieldVisible ? VISIBLE : INVISIBLE); titleTextView.setText(value); - positionTitle(getMeasuredWidth(), getMeasuredHeight()); - if (!created) { - titleTextView.setText(value); - } } } - public void setTitleIcon(int resourceId, int padding) { - if (resourceId != 0 && titleTextView == null) { - createTitleTextView(); - positionTitle(getMeasuredWidth(), getMeasuredHeight()); - } - titleTextView.setCompoundDrawablesWithIntrinsicBounds(resourceId, 0, 0, 0); - titleTextView.setCompoundDrawablePadding(padding); + public TextView getSubTitleTextView() { + return subTitleTextView; + } + + public TextView getTitleTextView() { + return titleTextView; } public Drawable getSubTitleIcon() { @@ -332,17 +187,6 @@ public class ActionBar extends FrameLayout { actionBarMenuOnItemClick = listener; } - public void setCustomView(int resourceId) { - LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = li.inflate(resourceId, null); - addView(view); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)view.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.topMargin = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0; - view.setLayoutParams(layoutParams); - } - public ActionBarMenu createActionMode() { if (actionMode != null) { return actionMode; @@ -358,7 +202,7 @@ public class ActionBar extends FrameLayout { actionMode.setLayoutParams(layoutParams); actionMode.setVisibility(INVISIBLE); - if (occupyStatusBar) { + if (occupyStatusBar && actionModeTop == null) { actionModeTop = new View(getContext()); actionModeTop.setBackgroundColor(0x99000000); addView(actionModeTop); @@ -381,8 +225,14 @@ public class ActionBar extends FrameLayout { if (occupyStatusBar && actionModeTop != null) { actionModeTop.setVisibility(VISIBLE); } - if (titleFrameLayout != null) { - titleFrameLayout.setVisibility(INVISIBLE); + if (titleTextView != null) { + titleTextView.setVisibility(INVISIBLE); + } + if (subTitleTextView != null) { + subTitleTextView.setVisibility(INVISIBLE); + } + if (backButtonImageView != null) { + backButtonImageView.setVisibility(INVISIBLE); } if (menu != null) { menu.setVisibility(INVISIBLE); @@ -397,14 +247,33 @@ public class ActionBar extends FrameLayout { if (occupyStatusBar && actionModeTop != null) { actionModeTop.setVisibility(INVISIBLE); } - if (titleFrameLayout != null) { - titleFrameLayout.setVisibility(VISIBLE); + if (titleTextView != null) { + titleTextView.setVisibility(VISIBLE); + } + if (subTitleTextView != null) { + subTitleTextView.setVisibility(VISIBLE); + } + if (backButtonImageView != null) { + backButtonImageView.setVisibility(VISIBLE); } if (menu != null) { menu.setVisibility(VISIBLE); } } + public void showActionModeTop() { + if (occupyStatusBar && actionModeTop == null) { + actionModeTop = new View(getContext()); + actionModeTop.setBackgroundColor(0x99000000); + addView(actionModeTop); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) actionModeTop.getLayoutParams(); + layoutParams.height = AndroidUtilities.statusBarHeight; + layoutParams.width = LayoutHelper.MATCH_PARENT; + layoutParams.gravity = Gravity.TOP | Gravity.LEFT; + actionModeTop.setLayoutParams(layoutParams); + } + } + public boolean isActionModeShowed() { return actionMode != null && actionMode.getVisibility() == VISIBLE; } @@ -439,12 +308,136 @@ public class ActionBar extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int actionBarHeight = AndroidUtilities.getCurrentActionBarHeight(); - positionBackImage(actionBarHeight); - positionMenu(MeasureSpec.getSize(widthMeasureSpec), actionBarHeight); - positionTitle(MeasureSpec.getSize(widthMeasureSpec), actionBarHeight); - actionBarHeight += occupyStatusBar ? AndroidUtilities.statusBarHeight : 0; - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(actionBarHeight + extraHeight, MeasureSpec.EXACTLY)); + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + int actionBarHeight = getCurrentActionBarHeight(); + int actionBarHeightSpec = MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.EXACTLY); + + setMeasuredDimension(width, actionBarHeight + extraHeight + (occupyStatusBar ? AndroidUtilities.statusBarHeight : 0)); + + int textLeft; + if (backButtonImageView != null && backButtonImageView.getVisibility() != GONE) { + backButtonImageView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(54), MeasureSpec.EXACTLY), actionBarHeightSpec); + textLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 80 : 72); + } else { + textLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 26 : 18); + } + + if (menu != null && menu.getVisibility() != GONE) { + int menuWidth; + if (isSearchFieldVisible) { + menuWidth = MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(AndroidUtilities.isTablet() ? 74 : 66), MeasureSpec.EXACTLY); + } else { + menuWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST); + } + menu.measure(menuWidth, actionBarHeightSpec); + } + + if (titleTextView != null && titleTextView.getVisibility() != GONE || subTitleTextView != null && subTitleTextView.getVisibility() != GONE) { + int availableWidth = width - (menu != null ? menu.getMeasuredWidth() : 0) - AndroidUtilities.dp(16) - textLeft; + + if (titleTextView != null && titleTextView.getVisibility() != GONE) { + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, !AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 18 : 20); + titleTextView.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.AT_MOST)); + + } + if (subTitleTextView != null && subTitleTextView.getVisibility() != GONE) { + subTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, !AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 14 : 16); + subTitleTextView.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.AT_MOST)); + } + } + + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child.getVisibility() == GONE || child == titleTextView || child == subTitleTextView || child == menu || child == backButtonImageView) { + continue; + } + measureChildWithMargins(child, widthMeasureSpec, 0, MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY), 0); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + int additionalTop = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0; + + int textLeft; + if (backButtonImageView != null && backButtonImageView.getVisibility() != GONE) { + backButtonImageView.layout(0, additionalTop, backButtonImageView.getMeasuredWidth(), additionalTop + backButtonImageView.getMeasuredHeight()); + textLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 80 : 72); + } else { + textLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 26 : 18); + } + + if (menu != null && menu.getVisibility() != GONE) { + int menuLeft = isSearchFieldVisible ? AndroidUtilities.dp(AndroidUtilities.isTablet() ? 74 : 66) : (right - left) - menu.getMeasuredWidth(); + menu.layout(menuLeft, additionalTop, menuLeft + menu.getMeasuredWidth(), additionalTop + menu.getMeasuredHeight()); + } + + int offset = AndroidUtilities.dp(!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 1 : 2); + if (titleTextView != null && titleTextView.getVisibility() != GONE) { + int textTop; + if (subTitleTextView != null && subTitleTextView.getVisibility() != GONE) { + textTop = (getCurrentActionBarHeight() / 2 - titleTextView.getMeasuredHeight()) / 2 + offset; + } else { + textTop = (getCurrentActionBarHeight() - titleTextView.getMeasuredHeight()) / 2 - AndroidUtilities.dp(1); + } + titleTextView.layout(textLeft, additionalTop + textTop, textLeft + titleTextView.getMeasuredWidth(), additionalTop + textTop + titleTextView.getMeasuredHeight()); + } + if (subTitleTextView != null && subTitleTextView.getVisibility() != GONE) { + int textTop = getCurrentActionBarHeight() / 2 + (getCurrentActionBarHeight() / 2 - subTitleTextView.getMeasuredHeight()) / 2 - offset; + subTitleTextView.layout(textLeft, additionalTop + textTop, textLeft + subTitleTextView.getMeasuredWidth(), additionalTop + textTop + subTitleTextView.getMeasuredHeight()); + } + + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + if (child.getVisibility() == GONE || child == titleTextView || child == subTitleTextView || child == menu || child == backButtonImageView) { + continue; + } + + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + + int width = child.getMeasuredWidth(); + int height = child.getMeasuredHeight(); + int childLeft; + int childTop; + + int gravity = lp.gravity; + if (gravity == -1) { + gravity = Gravity.TOP | Gravity.LEFT; + } + + final int absoluteGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK; + final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK; + + switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { + case Gravity.CENTER_HORIZONTAL: + childLeft = (right - left - width) / 2 + lp.leftMargin - lp.rightMargin; + break; + case Gravity.RIGHT: + childLeft = right - width - lp.rightMargin; + break; + case Gravity.LEFT: + default: + childLeft = lp.leftMargin; + } + + switch (verticalGravity) { + case Gravity.TOP: + childTop = lp.topMargin; + break; + case Gravity.CENTER_VERTICAL: + childTop = (bottom - top - height) / 2 + lp.topMargin - lp.bottomMargin; + break; + case Gravity.BOTTOM: + childTop = (bottom - top) - height - lp.bottomMargin; + break; + default: + childTop = lp.topMargin; + } + child.layout(childLeft, childTop, childLeft + width, childTop + height); + } } public void onMenuButtonPressed() { @@ -474,10 +467,13 @@ public class ActionBar extends FrameLayout { if (titleTextView != null) { titleTextView.setVisibility(textToSet != null && !isSearchFieldVisible ? VISIBLE : INVISIBLE); titleTextView.setText(textToSet); - positionTitle(getMeasuredWidth(), getMeasuredHeight()); } } + public boolean isSearchFieldVisible() { + return isSearchFieldVisible; + } + public void setExtraHeight(int value, boolean layout) { extraHeight = value; if (layout) { @@ -520,4 +516,14 @@ public class ActionBar extends FrameLayout { super.onTouchEvent(event); return true; } + + public static int getCurrentActionBarHeight() { + if (AndroidUtilities.isTablet()) { + return AndroidUtilities.dp(64); + } else if (ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { + return AndroidUtilities.dp(48); + } else { + return AndroidUtilities.dp(56); + } + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index 68b3b28be..f74d7c4d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -59,7 +59,7 @@ public class ActionBarLayout extends FrameLayout { if (child instanceof ActionBar) { return super.drawChild(canvas, child, drawingTime); } else { - boolean wasActionBar = false; + //boolean wasActionBar = false; int actionBarHeight = 0; int childCount = getChildCount(); for (int a = 0; a < childCount; a++) { @@ -339,7 +339,7 @@ public class ActionBarLayout extends FrameLayout { BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 2); View fragmentView = lastFragment.fragmentView; if (fragmentView == null) { - fragmentView = lastFragment.createView(parentActivity, parentActivity.getLayoutInflater()); + fragmentView = lastFragment.createView(parentActivity); } else { ViewGroup parent = (ViewGroup) fragmentView.getParent(); if (parent != null) { @@ -625,7 +625,7 @@ public class ActionBarLayout extends FrameLayout { fragment.setParentLayout(this); View fragmentView = fragment.fragmentView; if (fragmentView == null) { - fragmentView = fragment.createView(parentActivity, parentActivity.getLayoutInflater()); + fragmentView = fragment.createView(parentActivity); } else { ViewGroup parent = (ViewGroup) fragmentView.getParent(); if (parent != null) { @@ -829,7 +829,7 @@ public class ActionBarLayout extends FrameLayout { previousFragment.setParentLayout(this); View fragmentView = previousFragment.fragmentView; if (fragmentView == null) { - fragmentView = previousFragment.createView(parentActivity, parentActivity.getLayoutInflater()); + fragmentView = previousFragment.createView(parentActivity); } else { ViewGroup parent = (ViewGroup) fragmentView.getParent(); if (parent != null) { @@ -972,7 +972,7 @@ public class ActionBarLayout extends FrameLayout { previousFragment.setParentLayout(this); View fragmentView = previousFragment.fragmentView; if (fragmentView == null) { - fragmentView = previousFragment.createView(parentActivity, parentActivity.getLayoutInflater()); + fragmentView = previousFragment.createView(parentActivity); } else { ViewGroup parent = (ViewGroup) fragmentView.getParent(); if (parent != null) { 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 18ce670aa..2604eb466 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -36,7 +36,7 @@ public class ActionBarMenu extends LinearLayout { View view = li.inflate(resourceId, null); view.setTag(id); addView(view); - LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)view.getLayoutParams(); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view.getLayoutParams(); layoutParams.height = LayoutHelper.MATCH_PARENT; view.setBackgroundResource(parentActionBar.itemsBackgroundResourceId); view.setLayoutParams(layoutParams); @@ -74,14 +74,14 @@ public class ActionBarMenu extends LinearLayout { menuItem.iconView.setImageResource(icon); } addView(menuItem); - LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)menuItem.getLayoutParams(); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) menuItem.getLayoutParams(); layoutParams.height = LayoutHelper.MATCH_PARENT; layoutParams.width = width; menuItem.setLayoutParams(layoutParams); menuItem.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { - ActionBarMenuItem item = (ActionBarMenuItem)view; + ActionBarMenuItem item = (ActionBarMenuItem) view; if (item.hasSubMenu()) { if (parentActionBar.actionBarMenuOnItemClick.canOpenMenu()) { item.toggleSubMenu(); @@ -89,7 +89,7 @@ public class ActionBarMenu extends LinearLayout { } else if (item.isSearchField()) { parentActionBar.onSearchFieldVisibilityChanged(item.toggleSearch()); } else { - onItemClick((Integer)view.getTag()); + onItemClick((Integer) view.getTag()); } } }); @@ -100,7 +100,7 @@ public class ActionBarMenu extends LinearLayout { for (int a = 0; a < getChildCount(); a++) { View view = getChildAt(a); if (view instanceof ActionBarMenuItem) { - ((ActionBarMenuItem)view).closeSubMenu(); + ((ActionBarMenuItem) view).closeSubMenu(); } } } @@ -122,10 +122,16 @@ public class ActionBarMenu extends LinearLayout { for (int a = 0; a < getChildCount(); a++) { View view = getChildAt(a); if (view instanceof ActionBarMenuItem) { - ActionBarMenuItem item = (ActionBarMenuItem)view; - if (item.hasSubMenu() && item.getVisibility() == VISIBLE) { + ActionBarMenuItem item = (ActionBarMenuItem) view; + if (item.getVisibility() != VISIBLE) { + continue; + } + if (item.hasSubMenu()) { item.toggleSubMenu(); break; + } else if (item.overrideMenuClick) { + onItemClick((Integer) item.getTag()); + break; } } } @@ -135,7 +141,7 @@ public class ActionBarMenu extends LinearLayout { for (int a = 0; a < getChildCount(); a++) { View view = getChildAt(a); if (view instanceof ActionBarMenuItem) { - ActionBarMenuItem item = (ActionBarMenuItem)view; + ActionBarMenuItem item = (ActionBarMenuItem) view; if (item.isSearchField()) { parentActionBar.onSearchFieldVisibilityChanged(item.toggleSearch()); break; @@ -148,7 +154,7 @@ public class ActionBarMenu extends LinearLayout { for (int a = 0; a < getChildCount(); a++) { View view = getChildAt(a); if (view instanceof ActionBarMenuItem) { - ActionBarMenuItem item = (ActionBarMenuItem)view; + ActionBarMenuItem item = (ActionBarMenuItem) view; if (item.isSearchField()) { if (toggle) { parentActionBar.onSearchFieldVisibilityChanged(item.toggleSearch()); @@ -164,7 +170,7 @@ public class ActionBarMenu extends LinearLayout { public ActionBarMenuItem getItem(int id) { View v = findViewWithTag(id); if (v instanceof ActionBarMenuItem) { - return (ActionBarMenuItem)v; + return (ActionBarMenuItem) v; } return null; } 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 ad5fc1d9b..aa357e762 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java @@ -82,6 +82,8 @@ public class ActionBarMenuItem extends FrameLayoutFixed { private int subMenuOpenSide = 0; private ActionBarMenuItemDelegate delegate; private boolean allowCloseAnimation = true; + protected boolean overrideMenuClick; + private boolean processedPopupClick; public ActionBarMenuItem(Context context, ActionBarMenu menu, int background) { super(context); @@ -129,21 +131,23 @@ public class ActionBarMenuItem extends FrameLayoutFixed { x -= location[0]; y -= location[1]; selectedMenuView = null; - for (int a = 0; a < popupLayout.getChildCount(); a++) { - View child = popupLayout.getChildAt(a); + for (int a = 0; a < popupLayout.getItemsCount(); a++) { + View child = popupLayout.getItemAt(a); child.getHitRect(rect); if ((Integer) child.getTag() < 100) { if (!rect.contains((int) x, (int) y)) { child.setPressed(false); child.setSelected(false); - if (Build.VERSION.SDK_INT >= 21) { + if (Build.VERSION.SDK_INT == 21) { child.getBackground().setVisible(false, false); } } else { child.setPressed(true); child.setSelected(true); if (Build.VERSION.SDK_INT >= 21) { - child.getBackground().setVisible(true, false); + if (Build.VERSION.SDK_INT == 21) { + child.getBackground().setVisible(true, false); + } child.drawableHotspotChanged(x, y - child.getTop()); } selectedMenuView = child; @@ -192,9 +196,6 @@ public class ActionBarMenuItem extends FrameLayoutFixed { rect = new Rect(); location = new int[2]; popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext()); - popupLayout.setOrientation(LinearLayout.VERTICAL); - popupLayout.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); - //popupLayout.setBackgroundResource(R.drawable.popup_fixed); popupLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -252,6 +253,10 @@ public class ActionBarMenuItem extends FrameLayoutFixed { @Override public void onClick(View view) { if (popupWindow != null && popupWindow.isShowing()) { + if (processedPopupClick) { + return; + } + processedPopupClick = true; popupWindow.dismiss(allowCloseAnimation); } if (parentMenu != null) { @@ -306,6 +311,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed { } }); } + processedPopupClick = false; popupWindow.setFocusable(true); if (popupLayout.getMeasuredWidth() == 0) { updateOrShowPopup(true, true); @@ -367,6 +373,11 @@ public class ActionBarMenuItem extends FrameLayoutFixed { return setIsSearchField(value, true); } + public ActionBarMenuItem setOverrideMenuClick(boolean value) { + overrideMenuClick = value; + return this; + } + public ActionBarMenuItem setIsSearchField(boolean value, boolean needClearButton) { if (parentMenu == null) { return this; @@ -389,7 +400,8 @@ public class ActionBarMenuItem extends FrameLayoutFixed { searchField.setSingleLine(true); searchField.setBackgroundResource(0); searchField.setPadding(0, 0, 0, 0); - searchField.setInputType(EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + int inputType = searchField.getInputType() | EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS; + searchField.setInputType(inputType); if (android.os.Build.VERSION.SDK_INT < 11) { searchField.setOnCreateContextMenuListener(new OnCreateContextMenuListener() { public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { @@ -467,7 +479,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed { layoutParams2.width = LayoutHelper.MATCH_PARENT; layoutParams2.gravity = Gravity.CENTER_VERTICAL; layoutParams2.height = AndroidUtilities.dp(36); - layoutParams2.rightMargin = AndroidUtilities.dp(48); + layoutParams2.rightMargin = needClearButton ? AndroidUtilities.dp(48) : 0; searchField.setLayoutParams(layoutParams2); if (needClearButton) { @@ -532,6 +544,10 @@ public class ActionBarMenuItem extends FrameLayoutFixed { } } + if (show) { + popupLayout.scrollToTop(); + } + if (subMenuOpenSide == 0) { if (showFromBottom) { if (show) { @@ -574,10 +590,6 @@ public class ActionBarMenuItem extends FrameLayoutFixed { if (view != null) { view.setVisibility(GONE); } - view = popupLayout.findViewWithTag(100 + id); - if (view != null) { - view.setVisibility(GONE); - } } public void showSubItem(int id) { @@ -585,9 +597,5 @@ public class ActionBarMenuItem extends FrameLayoutFixed { if (view != null) { view.setVisibility(VISIBLE); } - view = popupLayout.findViewWithTag(100 + id); - if (view != null) { - view.setVisibility(VISIBLE); - } } } 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 7d6816f25..ee42b1eb9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -19,14 +19,18 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.view.KeyEvent; import android.view.View; +import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.animation.DecelerateInterpolator; +import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.PopupWindow; +import android.widget.ScrollView; import org.telegram.android.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.R; +import org.telegram.ui.Components.LayoutHelper; import java.lang.reflect.Field; import java.util.HashMap; @@ -62,7 +66,7 @@ public class ActionBarPopupWindow extends PopupWindow { void onDispatchKeyEvent(KeyEvent keyEvent); } - public static class ActionBarPopupWindowLayout extends LinearLayout { + public static class ActionBarPopupWindowLayout extends FrameLayout { private OnDispatchKeyEventListener mOnDispatchKeyEventListener; protected static Drawable backgroundDrawable; @@ -73,13 +77,26 @@ public class ActionBarPopupWindow extends PopupWindow { private boolean showedFromBotton; private HashMap positions = new HashMap<>(); + private ScrollView scrollView; + private LinearLayout linearLayout; + public ActionBarPopupWindowLayout(Context context) { super(context); - setWillNotDraw(false); if (backgroundDrawable == null) { backgroundDrawable = getResources().getDrawable(R.drawable.popup_fixed); } + + setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + setWillNotDraw(false); + + scrollView = new ScrollView(context); + scrollView.setVerticalScrollBarEnabled(false); + addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + scrollView.addView(linearLayout, new ScrollView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } public void setShowedFromBotton(boolean value) { @@ -106,15 +123,15 @@ public class ActionBarPopupWindow extends PopupWindow { public void setBackScaleY(float value) { backScaleY = value; if (animationEnabled) { - int count = getChildCount(); + int count = getItemsCount(); int visibleCount = 0; for (int a = 0; a < count; a++) { - visibleCount += getChildAt(a).getVisibility() == VISIBLE ? 1 : 0; + visibleCount += getItemAt(a).getVisibility() == VISIBLE ? 1 : 0; } int height = getMeasuredHeight() - AndroidUtilities.dp(16); if (showedFromBotton) { for (int a = lastStartedChild; a >= 0; a--) { - View child = getChildAt(a); + View child = getItemAt(a); if (child.getVisibility() != VISIBLE) { continue; } @@ -127,7 +144,7 @@ public class ActionBarPopupWindow extends PopupWindow { } } else { for (int a = lastStartedChild; a < count; a++) { - View child = getChildAt(a); + View child = getItemAt(a); if (child.getVisibility() != VISIBLE) { continue; } @@ -155,6 +172,11 @@ public class ActionBarPopupWindow extends PopupWindow { } } + @Override + public void addView(View child) { + linearLayout.addView(child); + } + public float getBackScaleX() { return backScaleX; } @@ -183,6 +205,18 @@ public class ActionBarPopupWindow extends PopupWindow { backgroundDrawable.draw(canvas); } } + + public int getItemsCount() { + return linearLayout.getChildCount(); + } + + public View getItemAt(int index) { + return linearLayout.getChildAt(index); + } + + public void scrollToTop() { + scrollView.scrollTo(0, 0); + } } public ActionBarPopupWindow() { @@ -269,11 +303,11 @@ public class ActionBarPopupWindow extends PopupWindow { content.setAlpha(1.0f); content.setPivotX(content.getMeasuredWidth()); content.setPivotY(0); - int count = content.getChildCount(); + int count = content.getItemsCount(); content.positions.clear(); int visibleCount = 0; for (int a = 0; a < count; a++) { - View child = content.getChildAt(a); + View child = content.getItemAt(a); if (child.getVisibility() != View.VISIBLE) { continue; } 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 dad03f246..1138a158b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -14,7 +14,6 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -44,7 +43,7 @@ public class BaseFragment { classGuid = ConnectionsManager.getInstance().generateClassGuid(); } - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java index dd00b928b..87ac403ba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -9,10 +9,18 @@ package org.telegram.ui.ActionBar; import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.text.TextUtils; @@ -45,7 +53,7 @@ import java.util.ArrayList; public class BottomSheet extends Dialog { - private LinearLayout linearLayout; + private LinearLayout containerView; private FrameLayout container; private boolean dismissed; @@ -57,24 +65,73 @@ public class BottomSheet extends Dialog { private int[] itemIcons; private View customView; private CharSequence title; - private boolean overrideTabletWidth = true; + private boolean fullWidth; private boolean isGrid; private ColorDrawable backgroundDrawable = new ColorDrawable(0xff000000); + private static Drawable shadowDrawable; + private Paint ciclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private static int backgroundPaddingTop; + private static int backgroundPaddingLeft; + + private boolean useRevealAnimation; + private float revealRadius; private int revealX; private int revealY; - private boolean useRevealAnimation; + private boolean applyTopPaddings = true; private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); private AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator(); private ArrayList itemViews = new ArrayList<>(); - private BottomSheetDelegate delegate; + private BottomSheetDelegateInterface delegate; - public interface BottomSheetDelegate { + public interface BottomSheetDelegateInterface { void onOpenAnimationStart(); + void onOpenAnimationEnd(); + + void onRevealAnimationStart(boolean open); + + void onRevealAnimationEnd(boolean open); + + void onRevealAnimationProgress(boolean open, float radius, int x, int y); + + View getRevealView(); + } + + public static class BottomSheetDelegate implements BottomSheetDelegateInterface { + @Override + public void onOpenAnimationStart() { + + } + + @Override + public void onOpenAnimationEnd() { + + } + + @Override + public void onRevealAnimationStart(boolean open) { + + } + + @Override + public void onRevealAnimationEnd(boolean open) { + + } + + @Override + public void onRevealAnimationProgress(boolean open, float radius, int x, int y) { + + } + + @Override + public View getRevealView() { + return null; + } } private static class BottomSheetCell extends FrameLayout { @@ -139,7 +196,40 @@ public class BottomSheet extends Dialog { public BottomSheet(Context context) { super(context); - container = new FrameLayout(getContext()); + container = new FrameLayout(getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + + setMeasuredDimension(width, height); + boolean isPortrait = width < height; + + if (containerView != null) { + int left = useRevealAnimation && Build.VERSION.SDK_INT <= 19 ? 0 : backgroundPaddingLeft; + if (!fullWidth) { + if (AndroidUtilities.isTablet()) { + int side = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f); + containerView.measure(MeasureSpec.makeMeasureSpec(side + left * 2, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); + } else { + int maxWidth = Math.min(AndroidUtilities.dp(480), width); + containerView.measure(isPortrait ? MeasureSpec.makeMeasureSpec(width + left * 2, MeasureSpec.EXACTLY) : MeasureSpec.makeMeasureSpec((int) Math.max(width * 0.8f, maxWidth) + left * 2, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); + } + } else { + containerView.measure(MeasureSpec.makeMeasureSpec(width + left * 2, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); + } + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (containerView != null) { + int l = ((right - left) - containerView.getMeasuredWidth()) / 2; + int t = (bottom - top) - containerView.getMeasuredHeight(); + containerView.layout(l, t, l + containerView.getMeasuredWidth(), t + getMeasuredHeight()); + } + } + }; container.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -159,25 +249,37 @@ public class BottomSheet extends Dialog { window.requestFeature(Window.FEATURE_NO_TITLE); window.setWindowAnimations(R.style.DialogNoAnimation); - setContentView(container); - - linearLayout = new LinearLayout(getContext()); - linearLayout.setOrientation(LinearLayout.VERTICAL); - if (AndroidUtilities.isTablet() && !overrideTabletWidth) { - container.addView(linearLayout, 0, LayoutHelper.createFrame(320, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL)); - } else { - container.addView(linearLayout, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); + if (shadowDrawable == null) { + Rect padding = new Rect(); + shadowDrawable = getContext().getResources().getDrawable(R.drawable.sheet_shadow); + shadowDrawable.getPadding(padding); + backgroundPaddingLeft = padding.left; + backgroundPaddingTop = padding.top; } - View shadow = new View(getContext()); - shadow.setBackgroundResource(R.drawable.header_shadow_reverse); - linearLayout.addView(shadow, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 3)); + setContentView(container, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - LinearLayout containerView = new LinearLayout(getContext()); - containerView.setBackgroundColor(0xffffffff); + ciclePaint.setColor(0xffffffff); + + containerView = new LinearLayout(getContext()) { + + @Override + protected void onDraw(Canvas canvas) { + if (useRevealAnimation && Build.VERSION.SDK_INT <= 19) { + canvas.drawCircle(revealX, revealY, revealRadius, ciclePaint); + //shadowDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); + //shadowDrawable.draw(canvas); + } + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + return super.drawChild(canvas, child, drawingTime); + } + }; + containerView.setWillNotDraw(false); containerView.setOrientation(LinearLayout.VERTICAL); - containerView.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(isGrid ? 16 : 8)); - linearLayout.addView(containerView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + container.addView(containerView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); if (title != null) { TextView titleView = new TextView(getContext()); @@ -273,104 +375,179 @@ public class BottomSheet extends Dialog { setOnShowListener(new OnShowListener() { @Override public void onShow(DialogInterface dialog) { - if (useRevealAnimation) { - int finalRadius = Math.max(AndroidUtilities.displaySize.x, container.getHeight()); - Animator anim = ViewAnimationUtils.createCircularReveal(container, revealX, revealY, 0, finalRadius); - anim.setDuration(400); - anim.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - if (delegate != null) { - delegate.onOpenAnimationStart(); - } - } - - @Override - public void onAnimationEnd(Animator animation) { - if (delegate != null) { - delegate.onOpenAnimationEnd(); - } - } - - @Override - public void onAnimationCancel(Animator animation) { - - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - anim.start(); - } else { - //startLayoutAnimation(true, true); - ViewProxy.setTranslationY(linearLayout, linearLayout.getHeight()); - backgroundDrawable.setAlpha(0); - AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); - animatorSetProxy.playTogether( - ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", 0), - ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 51)); - animatorSetProxy.setDuration(200); - animatorSetProxy.setStartDelay(20); - animatorSetProxy.setInterpolator(new DecelerateInterpolator()); - animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { - @Override - public void onAnimationEnd(Object animation) { - if (delegate != null) { - delegate.onOpenAnimationEnd(); - } - } - }); - animatorSetProxy.start(); + if (Build.VERSION.SDK_INT >= 21) { + startOpenAnimation(); } } }); } - private float animationProgress; - private long lastFrameTime; - private void startLayoutAnimation(final boolean open, final boolean first) { - if (first) { - animationProgress = 0.0f; - lastFrameTime = System.nanoTime() / 1000000; - if (Build.VERSION.SDK_INT >= 11) { - container.setLayerType(View.LAYER_TYPE_HARDWARE, null); + @Override + public void show() { + super.show(); + dismissed = false; + if (Build.VERSION.SDK_INT >= 21 || !useRevealAnimation) { + containerView.setBackgroundDrawable(shadowDrawable); + } else { + containerView.setBackgroundDrawable(null); + } + int left = useRevealAnimation && Build.VERSION.SDK_INT <= 19 ? 0 : backgroundPaddingLeft; + int top = useRevealAnimation && Build.VERSION.SDK_INT <= 19 ? 0 : backgroundPaddingTop; + containerView.setPadding(left, (applyTopPaddings ? AndroidUtilities.dp(8) : 0) + top, left, (applyTopPaddings ? AndroidUtilities.dp(isGrid ? 16 : 8) : 0)); + if (Build.VERSION.SDK_INT < 21) { + startOpenAnimation(); + } + } + + protected void setRevealRadius(float radius) { + revealRadius = radius; + delegate.onRevealAnimationProgress(!dismissed, radius, revealX, revealY); + if (Build.VERSION.SDK_INT <= 19) { + containerView.invalidate(); + } + } + + protected float getRevealRadius() { + return revealRadius; + } + + @SuppressLint("NewApi") + private void startRevealAnimation(final boolean open) { + + if (open) { + backgroundDrawable.setAlpha(0); + containerView.setVisibility(View.VISIBLE); + } else { + backgroundDrawable.setAlpha(51); + } + ViewProxy.setTranslationY(containerView, 0); + + AnimatorSet animatorSet = new AnimatorSet(); + + View view = delegate.getRevealView(); + if (view.getVisibility() == View.VISIBLE && ((ViewGroup) view.getParent()).getVisibility() == View.VISIBLE) { + final int coords[] = new int[2]; + view.getLocationInWindow(coords); + float top; + if (Build.VERSION.SDK_INT <= 19) { + top = AndroidUtilities.displaySize.y - containerView.getMeasuredHeight() - AndroidUtilities.statusBarHeight; + } else { + top = containerView.getY(); + } + revealX = coords[0] + view.getMeasuredWidth() / 2; + revealY = (int) (coords[1] + view.getMeasuredHeight() / 2 - top); + if (Build.VERSION.SDK_INT <= 19) { + revealY -= AndroidUtilities.statusBarHeight; + } + } else { + revealX = AndroidUtilities.displaySize.x / 2 + backgroundPaddingLeft; + revealY = (int) (AndroidUtilities.displaySize.y - containerView.getY()); + } + + int corners[][] = new int[][]{ + {0, 0}, + {0, containerView.getMeasuredHeight()}, + {containerView.getMeasuredWidth(), 0}, + {containerView.getMeasuredWidth(), containerView.getMeasuredHeight()} + }; + int finalRevealRadius = 0; + for (int a = 0; a < 4; a++) { + finalRevealRadius = Math.max(finalRevealRadius, (int) Math.ceil(Math.sqrt((revealX - corners[a][0]) * (revealX - corners[a][0]) + (revealY - corners[a][1]) * (revealY - corners[a][1])))); + } + + ArrayList animators = new ArrayList<>(3); + animators.add(ObjectAnimator.ofFloat(this, "revealRadius", open ? 0 : finalRevealRadius, open ? finalRevealRadius : 0)); + animators.add(ObjectAnimator.ofInt(backgroundDrawable, "alpha", open ? 51 : 0)); + if (Build.VERSION.SDK_INT >= 21) { + containerView.setElevation(AndroidUtilities.dp(10)); + animators.add(ViewAnimationUtils.createCircularReveal(containerView, revealX <= containerView.getMeasuredWidth() ? revealX : containerView.getMeasuredWidth(), revealY, open ? 0 : finalRevealRadius, open ? finalRevealRadius : 0)); + animatorSet.setDuration(300); + } else { + if (!open) { + animatorSet.setDuration(200); + containerView.setPivotX(revealX <= containerView.getMeasuredWidth() ? revealX : containerView.getMeasuredWidth()); + containerView.setPivotY(revealY); + animators.add(ObjectAnimator.ofFloat(containerView, "scaleX", 0.0f)); + animators.add(ObjectAnimator.ofFloat(containerView, "scaleY", 0.0f)); + animators.add(ObjectAnimator.ofFloat(containerView, "alpha", 0.0f)); + } else { + animatorSet.setDuration(250); + containerView.setScaleX(1); + containerView.setScaleY(1); + containerView.setAlpha(1); + if (Build.VERSION.SDK_INT <= 19) { + animatorSet.setStartDelay(20); + } } } - AndroidUtilities.runOnUIThread(new Runnable() { + animatorSet.playTogether(animators); + animatorSet.addListener(new AnimatorListenerAdapter() { @Override - public void run() { - long newTime = System.nanoTime() / 1000000; - long dt = newTime - lastFrameTime; - FileLog.e("tmessages", "dt = " + dt); - if (dt > 16) { - dt = 16; - } - lastFrameTime = newTime; - animationProgress += dt / 200.0f; - if (animationProgress > 1.0f) { - animationProgress = 1.0f; + public void onAnimationStart(Animator animation) { + if (delegate != null) { + delegate.onRevealAnimationStart(open); } + } - if (open) { - float interpolated = decelerateInterpolator.getInterpolation(animationProgress); - ViewProxy.setTranslationY(linearLayout, linearLayout.getHeight() * (1.0f - interpolated)); - backgroundDrawable.setAlpha((int) (51 * interpolated)); - } else { - float interpolated = accelerateInterpolator.getInterpolation(animationProgress); - ViewProxy.setTranslationY(linearLayout, linearLayout.getHeight() * interpolated); - backgroundDrawable.setAlpha((int) (51 * (1.0f - interpolated))); + @Override + public void onAnimationEnd(Animator animation) { + if (delegate != null) { + delegate.onRevealAnimationEnd(open); } - if (animationProgress < 1) { - startLayoutAnimation(open, false); - } else { - if (open && delegate != null) { - delegate.onOpenAnimationEnd(); + containerView.invalidate(); + if (Build.VERSION.SDK_INT >= 11) { + container.setLayerType(View.LAYER_TYPE_NONE, null); + } + if (!open) { + containerView.setVisibility(View.INVISIBLE); + try { + BottomSheet.super.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); } } } + + @Override + public void onAnimationCancel(Animator animation) { + onAnimationEnd(animation); + } }); + animatorSet.start(); + } + + private void startOpenAnimation() { + if (Build.VERSION.SDK_INT >= 20) { + container.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + if (containerView.getMeasuredHeight() == 0) { + containerView.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, View.MeasureSpec.AT_MOST)); + } + if (useRevealAnimation) { + startRevealAnimation(true); + } else { + ViewProxy.setTranslationY(containerView, containerView.getMeasuredHeight()); + backgroundDrawable.setAlpha(0); + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(containerView, "translationY", 0), + ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 51)); + animatorSetProxy.setDuration(200); + animatorSetProxy.setStartDelay(20); + animatorSetProxy.setInterpolator(new DecelerateInterpolator()); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + if (delegate != null) { + delegate.onOpenAnimationEnd(); + } + if (Build.VERSION.SDK_INT >= 11) { + container.setLayerType(View.LAYER_TYPE_NONE, null); + } + } + }); + animatorSetProxy.start(); + } } public void setDelegate(BottomSheetDelegate delegate) { @@ -382,7 +559,7 @@ public class BottomSheet extends Dialog { } public LinearLayout getSheetContainer() { - return linearLayout; + return containerView; } public int getTag() { @@ -397,13 +574,14 @@ public class BottomSheet extends Dialog { cell.textView.setText(text); } - private void dismissWithButtonClick(final int item) { + public void dismissWithButtonClick(final int item) { if (dismissed) { return; } + dismissed = true; AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); animatorSetProxy.playTogether( - ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", linearLayout.getHeight() + AndroidUtilities.dp(10)), + ObjectAnimatorProxy.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)), ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 0) ); animatorSetProxy.setDuration(180); @@ -440,34 +618,38 @@ public class BottomSheet extends Dialog { return; } dismissed = true; - AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); - animatorSetProxy.playTogether( - ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", linearLayout.getHeight() + AndroidUtilities.dp(10)), - ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 0) - ); - animatorSetProxy.setDuration(180); - animatorSetProxy.setInterpolator(new AccelerateInterpolator()); - animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { - @Override - public void onAnimationEnd(Object animation) { - AndroidUtilities.runOnUIThread(new Runnable() { - @Override - public void run() { - try { - BottomSheet.super.dismiss(); - } catch (Exception e) { - FileLog.e("tmessages", e); + if (useRevealAnimation) { + startRevealAnimation(false); + } else { + AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy(); + animatorSetProxy.playTogether( + ObjectAnimatorProxy.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)), + ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 0) + ); + animatorSetProxy.setDuration(180); + animatorSetProxy.setInterpolator(new AccelerateInterpolator()); + animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() { + @Override + public void onAnimationEnd(Object animation) { + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + try { + BottomSheet.super.dismiss(); + } catch (Exception e) { + FileLog.e("tmessages", e); + } } - } - }); - } + }); + } - @Override - public void onAnimationCancel(Object animation) { - onAnimationEnd(animation); - } - }); - animatorSetProxy.start(); + @Override + public void onAnimationCancel(Object animation) { + onAnimationEnd(animation); + } + }); + animatorSetProxy.start(); + } } public static class Builder { @@ -515,10 +697,10 @@ public class BottomSheet extends Dialog { return this; } - public Builder setRevealAnimation(int x, int y) { - bottomSheet.revealX = x; - bottomSheet.revealY = y; - bottomSheet.useRevealAnimation = true; + public Builder setUseRevealAnimation() { + if (Build.VERSION.SDK_INT >= 18 && !AndroidUtilities.isTablet()) { + bottomSheet.useRevealAnimation = true; + } return this; } @@ -532,8 +714,13 @@ public class BottomSheet extends Dialog { return this; } - public BottomSheet setOverrideTabletWidth(boolean value) { - bottomSheet.overrideTabletWidth = value; + public Builder setApplyTopPaddings(boolean value) { + bottomSheet.applyTopPaddings = value; + return this; + } + + public BottomSheet setUseFullWidth(boolean value) { + bottomSheet.fullWidth = value; return bottomSheet; } } 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 ce43585cc..d9c26a0a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java @@ -383,7 +383,6 @@ public class DrawerLayoutContainer extends FrameLayout { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { inLayout = true; - final int width = r - l; final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); @@ -416,8 +415,6 @@ public class DrawerLayoutContainer extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java index 8c39b844a..8efc34296 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java @@ -72,7 +72,6 @@ public class CountrySearchAdapter extends BaseFragmentAdapter { updateSearchResults(new ArrayList()); return; } - long time = System.currentTimeMillis(); ArrayList resultArray = new ArrayList<>(); String n = query.substring(0, 1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java index d1f497b7b..102a170fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java @@ -19,7 +19,7 @@ import org.telegram.ui.Cells.PhotoAttachPhotoCell; import java.util.HashMap; -public class PhotoAttachAdapter extends RecyclerView.Adapter implements NotificationCenter.NotificationCenterDelegate { +public class PhotoAttachAdapter extends RecyclerView.Adapter { private Context mContext; private PhotoAttachAdapterDelegate delegate; @@ -38,14 +38,6 @@ public class PhotoAttachAdapter extends RecyclerView.Adapter implements Notifica public PhotoAttachAdapter(Context context) { mContext = context; - NotificationCenter.getInstance().addObserver(this, NotificationCenter.albumsDidLoaded); - if (MediaController.allPhotosAlbumEntry == null) { - MediaController.loadGalleryPhotosAlbums(0); - } - } - - public void onDestroy() { - NotificationCenter.getInstance().removeObserver(this, NotificationCenter.albumsDidLoaded); } public void clearSelectedPhotos() { @@ -64,13 +56,6 @@ public class PhotoAttachAdapter extends RecyclerView.Adapter implements Notifica delegate = photoAttachAdapterDelegate; } - @Override - public void didReceivedNotification(int id, Object... args) { - if (id == NotificationCenter.albumsDidLoaded) { - notifyDataSetChanged(); - } - } - @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //if (position != 0) { 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 00206cf9b..28864d911 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -87,7 +87,7 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio } public void loadStikersForEmoji(CharSequence emoji) { - boolean search = emoji != null && emoji.length() != 0 && emoji.length() <= 2; + boolean search = emoji != null && emoji.length() > 0 && emoji.length() <= 4; if (search) { lastSticker = emoji.toString(); HashMap> allStickers = StickersQuery.getAllStickers(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java new file mode 100644 index 000000000..99ff51b60 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java @@ -0,0 +1,464 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.ImageLoader; +import org.telegram.android.MediaController; +import org.telegram.android.MessageObject; +import org.telegram.android.NotificationCenter; +import org.telegram.android.audioinfo.AudioInfo; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.R; +import org.telegram.messenger.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LineProgressView; + +import java.io.File; + +public class AudioPlayerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, MediaController.FileDownloadProgressListener { + + private MessageObject lastMessageObject; + private ImageView placeholder; + private ImageView playButton; + private ImageView nextButton; + private ImageView prevButton; + private ImageView shuffleButton; + private LineProgressView progressView; + private ImageView repeatButton; + private ImageView[] buttons = new ImageView[5]; + private TextView durationTextView; + private TextView timeTextView; + private SeekBarView seekBarView; + + private int TAG; + + private String lastTimeString; + + private class SeekBarView extends FrameLayout { + + private Paint innerPaint1; + private Paint outerPaint1; + private int thumbWidth; + private int thumbHeight; + public int thumbX = 0; + public int thumbDX = 0; + private boolean pressed = false; + + public SeekBarView(Context context) { + super(context); + setWillNotDraw(false); + innerPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + innerPaint1.setColor(0x19000000); + + outerPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + outerPaint1.setColor(0xff23afef); + + thumbWidth = AndroidUtilities.dp(24); + thumbHeight = AndroidUtilities.dp(24); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return onTouch(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return onTouch(event); + } + + boolean onTouch(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + getParent().requestDisallowInterceptTouchEvent(true); + int additionWidth = (getMeasuredHeight() - thumbWidth) / 2; + if (thumbX - additionWidth <= ev.getX() && ev.getX() <= thumbX + thumbWidth + additionWidth && ev.getY() >= 0 && ev.getY() <= getMeasuredHeight()) { + pressed = true; + thumbDX = (int)(ev.getX() - thumbX); + invalidate(); + return true; + } + } else if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + if (pressed) { + if (ev.getAction() == MotionEvent.ACTION_UP) { + onSeekBarDrag((float) thumbX / (float) (getMeasuredWidth() - thumbWidth)); + } + pressed = false; + invalidate(); + return true; + } + } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { + if (pressed) { + thumbX = (int)(ev.getX() - thumbDX); + if (thumbX < 0) { + thumbX = 0; + } else if (thumbX > getMeasuredWidth() - thumbWidth) { + thumbX = getMeasuredWidth() - thumbWidth; + } + invalidate(); + return true; + } + } + return false; + } + + public void setProgress(float progress) { + int newThumbX = (int)Math.ceil((getMeasuredWidth() - thumbWidth) * progress); + if (thumbX != newThumbX) { + thumbX = newThumbX; + if (thumbX < 0) { + thumbX = 0; + } else if (thumbX > getMeasuredWidth() - thumbWidth) { + thumbX = getMeasuredWidth() - thumbWidth; + } + invalidate(); + } + } + + public boolean isDragging() { + return pressed; + } + + @Override + protected void onDraw(Canvas canvas) { + int y = (getMeasuredHeight() - thumbHeight) / 2; + canvas.drawRect(thumbWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), getMeasuredWidth() - thumbWidth / 2, getMeasuredHeight() / 2 + AndroidUtilities.dp(1), innerPaint1); + canvas.drawRect(thumbWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), thumbWidth / 2 + thumbX, getMeasuredHeight() / 2 + AndroidUtilities.dp(1), outerPaint1); + canvas.drawCircle(thumbX + thumbWidth / 2, y + thumbHeight / 2, AndroidUtilities.dp(pressed ? 8 : 6), outerPaint1); + } + } + + @Override + public boolean onFragmentCreate() { + TAG = MediaController.getInstance().generateObserverTag(); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidStarted); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioProgressDidChanged); + return super.onFragmentCreate(); + } + + @Override + public void onFragmentDestroy() { + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidStarted); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioProgressDidChanged); + MediaController.getInstance().removeLoadingFileObserver(this); + super.onFragmentDestroy(); + } + + @Override + public View createView(Context context) { + FrameLayout frameLayout = new FrameLayout(context); + frameLayout.setBackgroundColor(0xfff0f0f0); + frameLayout.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return true; + } + }); + fragmentView = frameLayout; + + actionBar.setBackgroundColor(0xffffffff); + actionBar.setBackButtonImage(R.drawable.pl_back); + actionBar.setItemsBackground(R.drawable.bar_selector_audio); + if (!AndroidUtilities.isTablet()) { + actionBar.showActionModeTop(); + } + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + + placeholder = new ImageView(context); + frameLayout.addView(placeholder, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 66)); + + View shadow = new View(context); + shadow.setBackgroundResource(R.drawable.header_shadow_reverse); + frameLayout.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 96)); + + FrameLayout seekBarContainer = new FrameLayout(context); + seekBarContainer.setBackgroundColor(0xe5ffffff); + frameLayout.addView(seekBarContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 66)); + + timeTextView = new TextView(context); + timeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + timeTextView.setTextColor(0xff19a7e8); + timeTextView.setGravity(Gravity.CENTER); + timeTextView.setText("0:00"); + seekBarContainer.addView(timeTextView, LayoutHelper.createFrame(44, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); + + durationTextView = new TextView(context); + durationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12); + durationTextView.setTextColor(0xff8a8a8a); + durationTextView.setGravity(Gravity.CENTER); + durationTextView.setText("3:00"); + seekBarContainer.addView(durationTextView, LayoutHelper.createFrame(44, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); + + seekBarView = new SeekBarView(context); + seekBarContainer.addView(seekBarView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 32, 0, 32, 0)); + + progressView = new LineProgressView(context); + progressView.setVisibility(View.INVISIBLE); + progressView.setBackgroundColor(0x19000000); + progressView.setProgressColor(0xff23afef); + seekBarContainer.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.CENTER_VERTICAL | Gravity.LEFT, 44, 0, 44, 0)); + + FrameLayout bottomView = new FrameLayout(context) { + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + int dist = ((right - left) - AndroidUtilities.dp(30 + 48 * 5)) / 4; + for (int a = 0; a < 5; a++) { + int l = AndroidUtilities.dp(15 + 48 * a) + dist * a; + int t = AndroidUtilities.dp(9); + buttons[a].layout(l, t, l + buttons[a].getMeasuredWidth(), t + buttons[a].getMeasuredHeight()); + } + } + }; + bottomView.setBackgroundColor(0xffffffff); + frameLayout.addView(bottomView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 66, Gravity.BOTTOM | Gravity.LEFT)); + + buttons[0] = repeatButton = new ImageView(context); + repeatButton.setScaleType(ImageView.ScaleType.CENTER); + bottomView.addView(repeatButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); + repeatButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MediaController.getInstance().toggleRepeatMode(); + updateRepeatButton(); + } + }); + + buttons[1] = prevButton = new ImageView(context); + prevButton.setScaleType(ImageView.ScaleType.CENTER); + prevButton.setImageResource(R.drawable.player_prev_states); + bottomView.addView(prevButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); + prevButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MediaController.getInstance().playPreviousMessage(); + } + }); + + buttons[2] = playButton = new ImageView(context); + playButton.setScaleType(ImageView.ScaleType.CENTER); + playButton.setImageResource(R.drawable.player_play_states); + bottomView.addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); + playButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (MediaController.getInstance().isDownloadingCurrentMessage()) { + return; + } + if (MediaController.getInstance().isAudioPaused()) { + MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject()); + } else { + MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); + } + } + }); + + buttons[3] = nextButton = new ImageView(context); + nextButton.setScaleType(ImageView.ScaleType.CENTER); + nextButton.setImageResource(R.drawable.player_next_states); + bottomView.addView(nextButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); + nextButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MediaController.getInstance().playNextMessage(); + } + }); + + buttons[4] = shuffleButton = new ImageView(context); + shuffleButton.setScaleType(ImageView.ScaleType.CENTER); + bottomView.addView(shuffleButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP)); + shuffleButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + MediaController.getInstance().toggleShuffleMusic(); + updateShuffleButton(); + } + }); + + updateTitle(false); + updateRepeatButton(); + updateShuffleButton(); + + return frameLayout; + } + + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.audioDidStarted || id == NotificationCenter.audioPlayStateChanged || id == NotificationCenter.audioDidReset) { + updateTitle(id == NotificationCenter.audioDidReset && (Boolean) args[1]); + } else if (id == NotificationCenter.audioProgressDidChanged) { + MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + + if (messageObject.isMusic()) { + updateProgress(messageObject); + } + } + } + + @Override + public void onFailedDownload(String fileName) { + + } + + @Override + public void onSuccessDownload(String fileName) { + + } + + @Override + public void onProgressDownload(String fileName, float progress) { + progressView.setProgress(progress, true); + } + + @Override + public void onProgressUpload(String fileName, float progress, boolean isEncrypted) { + + } + + @Override + public int getObserverTag() { + return TAG; + } + + private void onSeekBarDrag(float progress) { + MediaController.getInstance().seekToProgress(MediaController.getInstance().getPlayingMessageObject(), progress); + } + + private void updateShuffleButton() { + if (MediaController.getInstance().isShuffleMusic()) { + shuffleButton.setImageResource(R.drawable.pl_shuffle_active); + } else { + shuffleButton.setImageResource(R.drawable.pl_shuffle); + } + } + + private void updateRepeatButton() { + int mode = MediaController.getInstance().getRepeatMode(); + if (mode == 0) { + repeatButton.setImageResource(R.drawable.pl_repeat); + } else if (mode == 1) { + repeatButton.setImageResource(R.drawable.pl_repeat_active); + } else if (mode == 2) { + repeatButton.setImageResource(R.drawable.pl_repeat1_active); + } + } + + private void updateProgress(MessageObject messageObject) { + if (seekBarView != null) { + if (!seekBarView.isDragging()) { + seekBarView.setProgress(messageObject.audioProgress); + } + String timeString = String.format("%d:%02d", messageObject.audioProgressSec / 60, messageObject.audioProgressSec % 60); + if (lastTimeString == null || lastTimeString != null && !lastTimeString.equals(timeString)) { + lastTimeString = timeString; + timeTextView.setText(timeString); + } + } + } + + private void checkIfMusicDownloaded(MessageObject messageObject) { + File cacheFile = null; + if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() > 0) { + cacheFile = new File(messageObject.messageOwner.attachPath); + if(!cacheFile.exists()) { + cacheFile = null; + } + } + if (cacheFile == null) { + cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); + } + if (!cacheFile.exists()) { + String fileName = messageObject.getFileName(); + MediaController.getInstance().addLoadingFileObserver(fileName, this); + Float progress = ImageLoader.getInstance().getFileProgress(fileName); + progressView.setProgress(progress != null ? progress : 0, false); + progressView.setVisibility(View.VISIBLE); + seekBarView.setVisibility(View.INVISIBLE); + playButton.setEnabled(false); + } else { + MediaController.getInstance().removeLoadingFileObserver(this); + progressView.setVisibility(View.INVISIBLE); + seekBarView.setVisibility(View.VISIBLE); + playButton.setEnabled(true); + } + } + + private void updateTitle(boolean shutdown) { + MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + if (messageObject == null && shutdown || messageObject != null && !messageObject.isMusic()) { + if (!parentLayout.fragmentsStack.isEmpty() && parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1) == this) { + finishFragment(); + } else { + removeSelfFromStack(); + } + } else { + if (messageObject == null) { + return; + } + checkIfMusicDownloaded(messageObject); + updateProgress(messageObject); + + if (MediaController.getInstance().isAudioPaused()) { + playButton.setImageResource(R.drawable.player_play_states); + } else { + playButton.setImageResource(R.drawable.player_pause_states); + } + if (actionBar != null) { + actionBar.setTitle(messageObject.getMusicTitle()); + actionBar.getTitleTextView().setTextColor(0xff212121); + actionBar.setSubtitle(messageObject.getMusicAuthor()); + actionBar.getSubTitleTextView().setTextColor(0xff8a8a8a); + } + AudioInfo audioInfo = MediaController.getInstance().getAudioInfo(); + if (audioInfo != null && audioInfo.getCover() != null) { + placeholder.setImageBitmap(audioInfo.getCover()); + placeholder.setPadding(0, 0, 0, 0); + placeholder.setScaleType(ImageView.ScaleType.CENTER_CROP); + } else { + placeholder.setImageResource(R.drawable.nocover); + placeholder.setPadding(0, 0, 0, AndroidUtilities.dp(30)); + placeholder.setScaleType(ImageView.ScaleType.CENTER); + } + + if (durationTextView != null) { + int duration = 0; + for (TLRPC.DocumentAttribute attribute : messageObject.messageOwner.media.document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeAudio) { + duration = attribute.duration; + break; + } + } + durationTextView.setText(duration != 0 ? String.format("%d:%02d", duration / 60, duration % 60) : "-:--"); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java new file mode 100644 index 000000000..a663665bb --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java @@ -0,0 +1,344 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui; + +import android.content.Context; +import android.database.Cursor; +import android.os.Build; +import android.provider.MediaStore; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.FrameLayout; +import android.widget.ListView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.LocaleController; +import org.telegram.android.MediaController; +import org.telegram.android.MessageObject; +import org.telegram.android.NotificationCenter; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.R; +import org.telegram.messenger.TLRPC; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.Adapters.BaseFragmentAdapter; +import org.telegram.ui.Cells.AudioCell; +import org.telegram.ui.Components.EmptyTextProgressView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.PickerBottomLayout; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; + +public class AudioSelectActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + + private ListAdapter listViewAdapter; + private EmptyTextProgressView progressView; + private PickerBottomLayout bottomLayout; + + private boolean loadingAudio; + + private ArrayList audioEntries = new ArrayList<>(); + private HashMap selectedAudios = new HashMap<>(); + + private AudioSelectActivityDelegate delegate; + + private MessageObject playingAudio; + + public interface AudioSelectActivityDelegate { + void didSelectAudio(ArrayList audios); + } + + @Override + public boolean onFragmentCreate() { + super.onFragmentCreate(); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.closeChats); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset); + loadAudio(); + return true; + } + + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeChats); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset); + if (playingAudio != null && MediaController.getInstance().isPlayingAudio(playingAudio)) { + MediaController.getInstance().clenupPlayer(true, true); + } + } + + @Override + public View createView(Context context) { + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setAllowOverlayTitle(true); + actionBar.setTitle(LocaleController.getString("AttachAudio", R.string.AttachAudio)); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + + fragmentView = new FrameLayout(context); + FrameLayout frameLayout = (FrameLayout) fragmentView; + + progressView = new EmptyTextProgressView(context); + progressView.setText(LocaleController.getString("NoAudio", R.string.NoAudio)); + frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + ListView listView = new ListView(context); + listView.setEmptyView(progressView); + listView.setVerticalScrollBarEnabled(false); + listView.setDivider(null); + listView.setDividerHeight(0); + listView.setAdapter(listViewAdapter = new ListAdapter(context)); + if (Build.VERSION.SDK_INT >= 11) { + listView.setVerticalScrollbarPosition(LocaleController.isRTL ? ListView.SCROLLBAR_POSITION_LEFT : ListView.SCROLLBAR_POSITION_RIGHT); + } + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48)); + + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + AudioCell audioCell = (AudioCell) view; + MediaController.AudioEntry audioEntry = audioCell.getAudioEntry(); + if (selectedAudios.containsKey(audioEntry.id)) { + selectedAudios.remove(audioEntry.id); + audioCell.setChecked(false); + } else { + selectedAudios.put(audioEntry.id, audioEntry); + audioCell.setChecked(true); + } + updateBottomLayoutCount(); + } + }); + + bottomLayout = new PickerBottomLayout(context, false); + frameLayout.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM)); + bottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + finishFragment(); + } + }); + bottomLayout.doneButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (delegate != null) { + ArrayList audios = new ArrayList<>(); + for (HashMap.Entry entry : selectedAudios.entrySet()) { + audios.add(entry.getValue().messageObject); + } + delegate.didSelectAudio(audios); + } + finishFragment(); + } + }); + + View shadow = new View(context); + shadow.setBackgroundResource(R.drawable.header_shadow_reverse); + frameLayout.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 48)); + + if (loadingAudio) { + progressView.showProgress(); + } else { + progressView.showTextView(); + } + updateBottomLayoutCount(); + return fragmentView; + } + + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.closeChats) { + removeSelfFromStack(); + } else if (id == NotificationCenter.audioDidReset) { + if (listViewAdapter != null) { + listViewAdapter.notifyDataSetChanged(); + } + } + } + + private void updateBottomLayoutCount() { + bottomLayout.updateSelectedCount(selectedAudios.size(), true); + } + + public void setDelegate(AudioSelectActivityDelegate audioSelectActivityDelegate) { + delegate = audioSelectActivityDelegate; + } + + private void loadAudio() { + loadingAudio = true; + if (progressView != null) { + progressView.showProgress(); + } + Utilities.globalQueue.postRunnable(new Runnable() { + @Override + public void run() { + String[] projection = { + MediaStore.Audio.Media._ID, + MediaStore.Audio.Media.ARTIST, + MediaStore.Audio.Media.TITLE, + MediaStore.Audio.Media.DATA, + MediaStore.Audio.Media.DURATION, + MediaStore.Audio.Media.ALBUM + }; + + final ArrayList newAudioEntries = new ArrayList<>(); + Cursor cursor = null; + try { + cursor = ApplicationLoader.applicationContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, MediaStore.Audio.Media.IS_MUSIC + " != 0", null, null); + int id = -2000000000; + while (cursor.moveToNext()) { + MediaController.AudioEntry audioEntry = new MediaController.AudioEntry(); + audioEntry.id = cursor.getInt(0); + audioEntry.author = cursor.getString(1); + audioEntry.title = cursor.getString(2); + audioEntry.path = cursor.getString(3); + audioEntry.duration = (int) (cursor.getLong(4) / 1000); + audioEntry.genre = cursor.getString(5); + + File file = new File(audioEntry.path); + + TLRPC.TL_message message = new TLRPC.TL_message(); + message.flags = TLRPC.MESSAGE_FLAG_OUT; + message.id = id; + message.to_id = new TLRPC.TL_peerUser(); + message.to_id.user_id = message.from_id = UserConfig.getClientUserId(); + message.date = (int) (System.currentTimeMillis() / 1000); + message.message = "-1"; + message.attachPath = audioEntry.path; + message.media = new TLRPC.TL_messageMediaDocument(); + message.media.document = new TLRPC.TL_document(); + + String ext = FileLoader.getFileExtension(file); + + message.media.document.id = 0; + message.media.document.access_hash = 0; + message.media.document.date = message.date; + message.media.document.mime_type = "audio/" + (ext.length() > 0 ? ext : "mp3"); + message.media.document.size = (int) file.length(); + message.media.document.thumb = new TLRPC.TL_photoSizeEmpty(); + message.media.document.thumb.type = "s"; + message.media.document.dc_id = 0; + + TLRPC.TL_documentAttributeAudio attributeAudio = new TLRPC.TL_documentAttributeAudio(); + attributeAudio.duration = audioEntry.duration; + attributeAudio.title = audioEntry.title; + attributeAudio.performer = audioEntry.author; + message.media.document.attributes.add(attributeAudio); + + TLRPC.TL_documentAttributeFilename fileName = new TLRPC.TL_documentAttributeFilename(); + fileName.file_name = file.getName(); + message.media.document.attributes.add(fileName); + + audioEntry.messageObject = new MessageObject(message, null, false); + + newAudioEntries.add(audioEntry); + id--; + } + } catch (Exception e) { + FileLog.e("tmessages", e); + } finally { + if (cursor != null) { + cursor.close(); + } + } + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + audioEntries = newAudioEntries; + progressView.showTextView(); + listViewAdapter.notifyDataSetChanged(); + } + }); + } + }); + } + + private class ListAdapter extends BaseFragmentAdapter { + private Context mContext; + + public ListAdapter(Context context) { + mContext = context; + } + + @Override + public boolean areAllItemsEnabled() { + return true; + } + + @Override + public boolean isEnabled(int i) { + return true; + } + + @Override + public int getCount() { + return audioEntries.size(); + } + + @Override + public Object getItem(int i) { + return audioEntries.get(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + public View getView(int i, View view, ViewGroup viewGroup) { + int type = getItemViewType(i); + if (view == null) { + view = new AudioCell(mContext); + ((AudioCell) view).setDelegate(new AudioCell.AudioCellDelegate() { + @Override + public void startedPlayingAudio(MessageObject messageObject) { + playingAudio = messageObject; + } + }); + } + MediaController.AudioEntry audioEntry = audioEntries.get(i); + ((AudioCell) view).setAudio(audioEntries.get(i), i != audioEntries.size() - 1, selectedAudios.containsKey(audioEntry.id)); + return view; + } + + @Override + public int getItemViewType(int i) { + return 0; + } + + @Override + public int getViewTypeCount() { + return 1; + } + + @Override + public boolean isEmpty() { + return audioEntries.isEmpty(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java index 1c1699d13..990286990 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java @@ -14,7 +14,6 @@ import android.content.DialogInterface; import android.os.Build; import android.os.Bundle; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -65,7 +64,7 @@ public class BlockedUsersActivity extends BaseFragment implements NotificationCe } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("BlockedUsers", R.string.BlockedUsers)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java new file mode 100644 index 000000000..d2e9b0c1f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java @@ -0,0 +1,169 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.LocaleController; +import org.telegram.android.MediaController; +import org.telegram.android.MessageObject; +import org.telegram.messenger.R; +import org.telegram.ui.Components.CheckBox; +import org.telegram.ui.Components.LayoutHelper; + +import java.util.ArrayList; + +public class AudioCell extends FrameLayout { + + private ImageView playButton; + private TextView titleTextView; + private TextView authorTextView; + private TextView genreTextView; + private TextView timeTextView; + private CheckBox checkBox; + + private MediaController.AudioEntry audioEntry; + private boolean needDivider; + private static Paint paint; + + private AudioCellDelegate delegate; + + public interface AudioCellDelegate { + void startedPlayingAudio(MessageObject messageObject); + } + + public AudioCell(Context context) { + super(context); + + if (paint == null) { + paint = new Paint(); + paint.setColor(0xffd9d9d9); + paint.setStrokeWidth(1); + } + + playButton = new ImageView(context); + playButton.setScaleType(ImageView.ScaleType.CENTER); + addView(playButton, LayoutHelper.createFrame(46, 46, ((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP), LocaleController.isRTL ? 0 : 13, 13, LocaleController.isRTL ? 13 : 0, 0)); + playButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (audioEntry != null) { + if (MediaController.getInstance().isPlayingAudio(audioEntry.messageObject) && !MediaController.getInstance().isAudioPaused()) { + MediaController.getInstance().pauseAudio(audioEntry.messageObject); + playButton.setImageResource(R.drawable.audiosend_play); + } else { + ArrayList arrayList = new ArrayList<>(); + arrayList.add(audioEntry.messageObject); + if (MediaController.getInstance().setPlaylist(arrayList, audioEntry.messageObject)) { + playButton.setImageResource(R.drawable.audiosend_pause); + if (delegate != null) { + delegate.startedPlayingAudio(audioEntry.messageObject); + } + } + } + } + } + }); + + titleTextView = new TextView(context); + titleTextView.setTextColor(0xff212121); + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextView.setLines(1); + titleTextView.setMaxLines(1); + titleTextView.setSingleLine(true); + titleTextView.setEllipsize(TextUtils.TruncateAt.END); + titleTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); + addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 50 : 72, 7, LocaleController.isRTL ? 72 : 50, 0)); + + genreTextView = new TextView(context); + genreTextView.setTextColor(0xff8a8a8a); + genreTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + genreTextView.setLines(1); + genreTextView.setMaxLines(1); + genreTextView.setSingleLine(true); + genreTextView.setEllipsize(TextUtils.TruncateAt.END); + genreTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); + addView(genreTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 50 : 72, 28, LocaleController.isRTL ? 72 : 50, 0)); + + authorTextView = new TextView(context); + authorTextView.setTextColor(0xff8a8a8a); + authorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + authorTextView.setLines(1); + authorTextView.setMaxLines(1); + authorTextView.setSingleLine(true); + authorTextView.setEllipsize(TextUtils.TruncateAt.END); + authorTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); + addView(authorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 50 : 72, 44, LocaleController.isRTL ? 72 : 50, 0)); + + timeTextView = new TextView(context); + timeTextView.setTextColor(0xff999999); + timeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + timeTextView.setLines(1); + timeTextView.setMaxLines(1); + timeTextView.setSingleLine(true); + timeTextView.setEllipsize(TextUtils.TruncateAt.END); + timeTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP); + addView(timeTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 18 : 0, 11, LocaleController.isRTL ? 0 : 18, 0)); + + checkBox = new CheckBox(context, R.drawable.round_check2); + checkBox.setVisibility(VISIBLE); + checkBox.setColor(0xff29b6f7); + addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 18 : 0, 39, LocaleController.isRTL ? 0 : 18, 0)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(72) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); + } + + public void setAudio(MediaController.AudioEntry entry, boolean divider, boolean checked) { + audioEntry = entry; + + titleTextView.setText(audioEntry.title); + genreTextView.setText(audioEntry.genre); + authorTextView.setText(audioEntry.author); + timeTextView.setText(String.format("%d:%02d", audioEntry.duration / 60, audioEntry.duration % 60)); + playButton.setImageResource(MediaController.getInstance().isPlayingAudio(audioEntry.messageObject) && !MediaController.getInstance().isAudioPaused() ? R.drawable.audiosend_pause : R.drawable.audiosend_play); + + needDivider = divider; + setWillNotDraw(!divider); + + checkBox.setChecked(checked, false); + } + + public void setChecked(boolean value) { + checkBox.setChecked(value, true); + } + + public void setDelegate(AudioCellDelegate audioCellDelegate) { + delegate = audioCellDelegate; + } + + public MediaController.AudioEntry getAudioEntry() { + return audioEntry; + } + + @Override + protected void onDraw(Canvas canvas) { + if (needDivider) { + canvas.drawLine(AndroidUtilities.dp(72), getHeight() - 1, getWidth(), getHeight() - 1, paint); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java index 6c05ae107..32d9c6baa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java @@ -42,6 +42,7 @@ public class BotHelpCell extends View { private int height; private int textX; private int textY; + private int textXOffset; private ClickableSpan pressedLink; private LinkPath urlPath = new LinkPath(); @@ -101,7 +102,9 @@ public class BotHelpCell extends View { width = 0; height = textLayout.getHeight() + AndroidUtilities.dp(4 + 18); int count = textLayout.getLineCount(); + textXOffset = Integer.MAX_VALUE; for (int a = 0; a < count; a++) { + textXOffset = (int) Math.ceil(Math.min(textXOffset, textLayout.getLineLeft(a))); width = (int) Math.ceil(Math.max(width, textLayout.getLineWidth(a) - textLayout.getLineLeft(a))); } width += AndroidUtilities.dp(4 + 18); @@ -113,7 +116,6 @@ public class BotHelpCell extends View { float y = event.getY(); boolean result = false; - int side = AndroidUtilities.dp(48); if (textLayout != null) { if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) { if (event.getAction() == MotionEvent.ACTION_DOWN) { @@ -186,7 +188,7 @@ public class BotHelpCell extends View { ResourceLoader.backgroundMediaDrawableIn.setBounds(x, y, width + x, height + y); ResourceLoader.backgroundMediaDrawableIn.draw(canvas); canvas.save(); - canvas.translate(textX = AndroidUtilities.dp(2 + 9) + x, textY = AndroidUtilities.dp(2 + 9) + y); + canvas.translate(textX = AndroidUtilities.dp(2 + 9) + x - textXOffset, textY = AndroidUtilities.dp(2 + 9) + y); if (pressedLink != null) { canvas.drawPath(urlPath, urlPaint); } 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 12c749222..82ab4b730 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -174,8 +174,8 @@ public class ChatActionCell extends BaseCell { final int line = textLayout.getLineForVertical((int)y); final int off = textLayout.getOffsetForHorizontal(line, x); final float left = textLayout.getLineLeft(line); - if (left <= x && left + textLayout.getLineWidth(line) >= x) { - Spannable buffer = (Spannable)currentMessageObject.messageText; + if (left <= x && left + textLayout.getLineWidth(line) >= x && currentMessageObject.messageText instanceof Spannable) { + Spannable buffer = (Spannable) currentMessageObject.messageText; URLSpan[] link = buffer.getSpans(off, off, URLSpan.class); if (link.length != 0) { @@ -226,7 +226,6 @@ public class ChatActionCell extends BaseCell { int linesCount = textLayout.getLineCount(); for (int a = 0; a < linesCount; a++) { float lineWidth; - float lineLeft = 0; try { lineWidth = textLayout.getLineWidth(a); textHeight = (int)Math.max(textHeight, Math.ceil(textLayout.getLineBottom(a))); 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 1b7a9db99..77f5069e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java @@ -21,10 +21,11 @@ import android.view.SoundEffectConstants; import org.telegram.android.AndroidUtilities; import org.telegram.android.ImageLoader; import org.telegram.android.MessagesController; +import org.telegram.android.SendMessagesHelper; import org.telegram.messenger.FileLoader; import org.telegram.android.MediaController; import org.telegram.android.MessageObject; -import org.telegram.ui.Components.ProgressView; +import org.telegram.ui.Components.RadialProgress; import org.telegram.ui.Components.ResourceLoader; import org.telegram.ui.Components.SeekBar; @@ -36,10 +37,10 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega private static Paint circlePaint; private SeekBar seekBar; - private ProgressView progressView; private int seekBarX; private int seekBarY; + private RadialProgress radialProgress; private int buttonState = 0; private int buttonX; private int buttonY; @@ -58,7 +59,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega seekBar = new SeekBar(context); seekBar.delegate = this; - progressView = new ProgressView(); + radialProgress = new RadialProgress(this); drawForwardedName = true; if (timePaint == null) { @@ -78,7 +79,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - updateButtonState(); + updateButtonState(false); } @Override @@ -131,21 +132,25 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega } if (result) { buttonState = 1; + radialProgress.setBackground(getDrawableForCurrentState(), false, false); invalidate(); } } else if (buttonState == 1) { boolean result = MediaController.getInstance().pauseAudio(currentMessageObject); if (result) { buttonState = 0; + radialProgress.setBackground(getDrawableForCurrentState(), false, false); invalidate(); } } else if (buttonState == 2) { FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.audio, true); buttonState = 3; + radialProgress.setBackground(getDrawableForCurrentState(), true, false); invalidate(); } else if (buttonState == 3) { FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.audio); buttonState = 2; + radialProgress.setBackground(getDrawableForCurrentState(), false, false); invalidate(); } else if (buttonState == 4) { if (currentMessageObject.isOut() && currentMessageObject.isSending()) { @@ -173,6 +178,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega } String timeString = String.format("%02d:%02d", duration / 60, duration % 60); if (lastTimeString == null || lastTimeString != null && !lastTimeString.equals(timeString)) { + lastTimeString = timeString; timeWidth = (int)Math.ceil(timePaint.measureText(timeString)); timeLayout = new StaticLayout(timeString, timePaint, timeWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } @@ -183,16 +189,23 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega if (buttonState == 2) { FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.audio, true); buttonState = 3; - invalidate(); + radialProgress.setBackground(getDrawableForCurrentState(), false, false); } } - public void updateButtonState() { + public void updateButtonState(boolean animated) { if (currentMessageObject == null) { return; } if (currentMessageObject.isOut() && currentMessageObject.isSending()) { + MediaController.getInstance().addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this); buttonState = 4; + radialProgress.setBackground(getDrawableForCurrentState(), true, animated); + Float progress = ImageLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath); + if (progress == null && SendMessagesHelper.getInstance().isSendingMessage(currentMessageObject.getId())) { + progress = 1.0f; + } + radialProgress.setProgress(progress != null ? progress : 0, false); } else { File cacheFile = null; if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() > 0) { @@ -212,21 +225,24 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega } else { buttonState = 1; } - progressView.setProgress(0); + radialProgress.setProgress(0, animated); + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); } else { String fileName = currentMessageObject.getFileName(); MediaController.getInstance().addLoadingFileObserver(fileName, this); if (!FileLoader.getInstance().isLoadingFile(fileName)) { buttonState = 2; - progressView.setProgress(0); + radialProgress.setProgress(0, animated); + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); } else { buttonState = 3; Float progress = ImageLoader.getInstance().getFileProgress(fileName); if (progress != null) { - progressView.setProgress(progress); + radialProgress.setProgress(progress, animated); } else { - progressView.setProgress(0); + radialProgress.setProgress(0, animated); } + radialProgress.setBackground(getDrawableForCurrentState(), true, animated); } } } @@ -235,26 +251,25 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega @Override public void onFailedDownload(String fileName) { - updateButtonState(); + updateButtonState(true); } @Override public void onSuccessDownload(String fileName) { - updateButtonState(); + updateButtonState(true); } @Override public void onProgressDownload(String fileName, float progress) { - progressView.setProgress(progress); + radialProgress.setProgress(progress, true); if (buttonState != 3) { - updateButtonState(); + updateButtonState(false); } - invalidate(); } @Override public void onProgressUpload(String fileName, float progress, boolean isEncrypted) { - + radialProgress.setProgress(progress, true); } @Override @@ -299,17 +314,17 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega seekBar.width = backgroundWidth - AndroidUtilities.dp(70); seekBar.height = AndroidUtilities.dp(30); - progressView.width = backgroundWidth - AndroidUtilities.dp(94); - progressView.height = AndroidUtilities.dp(30); seekBarY = AndroidUtilities.dp(11) + namesOffset; buttonY = AndroidUtilities.dp(13) + namesOffset; + radialProgress.setProgressRect(buttonX, buttonY, buttonX + AndroidUtilities.dp(40), buttonY + AndroidUtilities.dp(40)); updateProgress(); } @Override public void setMessageObject(MessageObject messageObject) { - if (currentMessageObject != messageObject || isUserDataChanged()) { + boolean dataChanged = currentMessageObject == messageObject && isUserDataChanged(); + if (currentMessageObject != messageObject || dataChanged) { if (AndroidUtilities.isTablet()) { backgroundWidth = Math.min(AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(isChat ? 102 : 50), AndroidUtilities.dp(300)); } else { @@ -318,15 +333,20 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega if (messageObject.isOut()) { seekBar.type = 0; - progressView.setProgressColors(0xffb4e396, 0xff6ac453); + radialProgress.setProgressColor(0xff87bf78); } else { seekBar.type = 1; - progressView.setProgressColors(0xffd9e2eb, 0xff86c5f8); + radialProgress.setProgressColor(0xffa2b5c7); } super.setMessageObject(messageObject); } - updateButtonState(); + updateButtonState(dataChanged); + } + + private Drawable getDrawableForCurrentState() { + return ResourceLoader.audioStatesDrawable[currentMessageObject.isOut() ? buttonState : buttonState + 5][0]; + //buttonPressed ? 1 : } @Override @@ -338,27 +358,18 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega } canvas.save(); - if (buttonState == 0 || buttonState == 1) { - canvas.translate(seekBarX, seekBarY); - seekBar.draw(canvas); - } else { - canvas.translate(seekBarX + AndroidUtilities.dp(12), seekBarY); - progressView.draw(canvas); - } + canvas.translate(seekBarX, seekBarY); + seekBar.draw(canvas); canvas.restore(); - int state = buttonState; if (currentMessageObject.isOut()) { timePaint.setColor(0xff70b15c); circlePaint.setColor(0xff87bf78); } else { - state += 5; timePaint.setColor(0xffa1aab3); circlePaint.setColor(0xff4195e5); } - Drawable buttonDrawable = ResourceLoader.audioStatesDrawable[state][buttonPressed ? 1 : 0]; - setDrawableBounds(buttonDrawable, buttonX, buttonY); - buttonDrawable.draw(canvas); + radialProgress.onDraw(canvas); canvas.save(); canvas.translate(timeX, AndroidUtilities.dp(42) + namesOffset); 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 8e28d5163..dda180c9a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java @@ -445,7 +445,7 @@ public class ChatBaseCell extends BaseCell { mess = mess.substring(0, 150); } mess = mess.replace("\n", " "); - stringFinalText = Emoji.replaceEmoji(mess, replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14)); + stringFinalText = Emoji.replaceEmoji(mess, replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); stringFinalText = TextUtils.ellipsize(stringFinalText, replyTextPaint, maxWidth - AndroidUtilities.dp(8), TextUtils.TruncateAt.END); } } 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 129348b60..92c337c27 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java @@ -108,7 +108,6 @@ public class ChatContactCell extends ChatBaseCell { float y = event.getY(); boolean result = false; - int side = AndroidUtilities.dp(36); if (event.getAction() == MotionEvent.ACTION_DOWN) { if (x >= avatarImage.getImageX() && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(42) && y >= avatarImage.getImageY() && y <= avatarImage.getImageY() + avatarImage.getImageHeight()) { avatarPressed = true; 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 23f72ec76..0c704b956 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java @@ -379,7 +379,6 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD private Drawable getDrawableForCurrentState() { if (buttonState >= 0 && buttonState < 4) { - Drawable currentButtonDrawable = null; if (currentMessageObject.type == 9 && gifDrawable == null) { if (buttonState == 1 && !currentMessageObject.isSending()) { return ResourceLoader.buttonStatesDrawablesDoc[2][currentMessageObject.isOut() ? 1 : 0]; 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 aac1b324d..14159564f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -193,7 +193,7 @@ public class ChatMessageCell extends ChatBaseCell { pressedLink.onClick(this); } else { TLRPC.WebPage webPage = currentMessageObject.messageOwner.media.webpage; - if (Build.VERSION.SDK_INT >= 16 && webPage.embed_url != null && webPage.embed_url.length() != 0) { + if (Build.VERSION.SDK_INT >= 19 && webPage.embed_url != null && webPage.embed_url.length() != 0) { delegate.needOpenWebView(webPage.embed_url, webPage.site_name, webPage.url, webPage.embed_width, webPage.embed_height); } else { Uri uri = Uri.parse(webPage.url); @@ -536,7 +536,7 @@ public class ChatMessageCell extends ChatBaseCell { if (webPage.photo != null) { boolean smallImage = webPage.type != null && (webPage.type.equals("app") || webPage.type.equals("profile") || webPage.type.equals("article")); - if (smallImage && descriptionLayout != null && descriptionLayout.getLineCount() == 1) { + if (smallImage && (descriptionLayout == null || descriptionLayout != null && descriptionLayout.getLineCount() == 1)) { smallImage = false; isSmallImage = false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java new file mode 100644 index 000000000..d85fe7747 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java @@ -0,0 +1,428 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.text.TextUtils; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.ImageLoader; +import org.telegram.android.MediaController; +import org.telegram.android.MessageObject; +import org.telegram.android.SendMessagesHelper; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.TLRPC; +import org.telegram.ui.Components.RadialProgress; +import org.telegram.ui.Components.ResourceLoader; +import org.telegram.ui.Components.SeekBar; + +import java.io.File; + +public class ChatMusicCell extends ChatBaseCell implements SeekBar.SeekBarDelegate, MediaController.FileDownloadProgressListener { + + public interface ChatMusicCellDelegate { + boolean needPlayMusic(MessageObject messageObject); + } + + private static TextPaint timePaint; + private static TextPaint titlePaint; + private static TextPaint authorPaint; + + private SeekBar seekBar; + private int seekBarX; + private int seekBarY; + + private RadialProgress radialProgress; + private int buttonState = 0; + private int buttonX; + private int buttonY; + private boolean buttonPressed = false; + + private StaticLayout timeLayout; + private int timeX; + private String lastTimeString = null; + + private StaticLayout titleLayout; + private int titleX; + + private StaticLayout authorLayout; + private int authorX; + + private int TAG; + + private ChatMusicCellDelegate musicDelegate; + + public ChatMusicCell(Context context) { + super(context); + TAG = MediaController.getInstance().generateObserverTag(); + + seekBar = new SeekBar(context); + seekBar.delegate = this; + radialProgress = new RadialProgress(this); + drawForwardedName = false; + + if (timePaint == null) { + timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + timePaint.setTextSize(AndroidUtilities.dp(13)); + + titlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + titlePaint.setTextSize(AndroidUtilities.dp(16)); + titlePaint.setColor(0xff212121); + titlePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + + authorPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + authorPaint.setTextSize(AndroidUtilities.dp(15)); + authorPaint.setColor(0xff212121); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + MediaController.getInstance().removeLoadingFileObserver(this); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + updateButtonState(false); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + float x = event.getX(); + float y = event.getY(); + boolean result = seekBar.onTouch(event.getAction(), event.getX() - seekBarX, event.getY() - seekBarY); + if (result) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + getParent().requestDisallowInterceptTouchEvent(true); + } + invalidate(); + } else { + int side = AndroidUtilities.dp(36); + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side) { + buttonPressed = true; + invalidate(); + result = true; + } + } else if (buttonPressed) { + if (event.getAction() == MotionEvent.ACTION_UP) { + buttonPressed = false; + playSoundEffect(SoundEffectConstants.CLICK); + didPressedButton(); + invalidate(); + } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { + buttonPressed = false; + invalidate(); + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (!(x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side)) { + buttonPressed = false; + invalidate(); + } + } + } + if (!result) { + result = super.onTouchEvent(event); + } + } + + return result; + } + + private void didPressedButton() { + if (buttonState == 0) { + if (musicDelegate != null) { + if (musicDelegate.needPlayMusic(currentMessageObject)) { + buttonState = 1; + radialProgress.setBackground(getDrawableForCurrentState(), false, false); + invalidate(); + } + } + } else if (buttonState == 1) { + boolean result = MediaController.getInstance().pauseAudio(currentMessageObject); + if (result) { + buttonState = 0; + radialProgress.setBackground(getDrawableForCurrentState(), false, false); + invalidate(); + } + } else if (buttonState == 2) { + FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true, false); + buttonState = 3; + radialProgress.setBackground(getDrawableForCurrentState(), true, false); + invalidate(); + } else if (buttonState == 3) { + FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.document); + buttonState = 2; + radialProgress.setBackground(getDrawableForCurrentState(), false, false); + invalidate(); + } else if (buttonState == 4) { + if (currentMessageObject.isOut() && currentMessageObject.isSending()) { + if (delegate != null) { + delegate.didPressedCancelSendButton(this); + } + } + } + } + + public void setMusicDelegate(ChatMusicCellDelegate delegate) { + musicDelegate = delegate; + } + + public void updateProgress() { + if (currentMessageObject == null) { + return; + } + + if (!seekBar.isDragging()) { + seekBar.setProgress(currentMessageObject.audioProgress); + } + + int duration = 0; + int currentProgress = 0; + for (TLRPC.DocumentAttribute attribute : currentMessageObject.messageOwner.media.document.attributes) { + if (attribute instanceof TLRPC.TL_documentAttributeAudio) { + duration = attribute.duration; + break; + } + } + if (MediaController.getInstance().isPlayingAudio(currentMessageObject)) { + currentProgress = currentMessageObject.audioProgressSec; + } + String timeString = String.format("%d:%02d / %d:%02d", currentProgress / 60, currentProgress % 60, duration / 60, duration % 60); + if (lastTimeString == null || lastTimeString != null && !lastTimeString.equals(timeString)) { + lastTimeString = timeString; + int timeWidth = (int) Math.ceil(timePaint.measureText(timeString)); + timeLayout = new StaticLayout(timeString, timePaint, timeWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } + invalidate(); + } + + public void downloadAudioIfNeed() { + //if (buttonState == 2) { + //FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true, false); + // buttonState = 3; + // invalidate(); + //} + } + + public void updateButtonState(boolean animated) { + if (currentMessageObject == null) { + return; + } + if (currentMessageObject.isOut() && currentMessageObject.isSending()) { + MediaController.getInstance().addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this); + buttonState = 4; + radialProgress.setBackground(getDrawableForCurrentState(), true, animated); + Float progress = ImageLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath); + if (progress == null && SendMessagesHelper.getInstance().isSendingMessage(currentMessageObject.getId())) { + progress = 1.0f; + } + radialProgress.setProgress(progress != null ? progress : 0, false); + } else { + File cacheFile = null; + if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() > 0) { + cacheFile = new File(currentMessageObject.messageOwner.attachPath); + if(!cacheFile.exists()) { + cacheFile = null; + } + } + if (cacheFile == null) { + cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + } + if (cacheFile.exists()) { + MediaController.getInstance().removeLoadingFileObserver(this); + boolean playing = MediaController.getInstance().isPlayingAudio(currentMessageObject); + if (!playing || playing && MediaController.getInstance().isAudioPaused()) { + buttonState = 0; + } else { + buttonState = 1; + } + radialProgress.setProgress(0, animated); + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); + } else { + String fileName = currentMessageObject.getFileName(); + MediaController.getInstance().addLoadingFileObserver(fileName, this); + if (!FileLoader.getInstance().isLoadingFile(fileName)) { + buttonState = 2; + radialProgress.setProgress(0, animated); + radialProgress.setBackground(getDrawableForCurrentState(), false, animated); + } else { + buttonState = 3; + Float progress = ImageLoader.getInstance().getFileProgress(fileName); + if (progress != null) { + radialProgress.setProgress(progress, animated); + } else { + radialProgress.setProgress(0, animated); + } + radialProgress.setBackground(getDrawableForCurrentState(), true, animated); + } + } + } + updateProgress(); + } + + @Override + public void onFailedDownload(String fileName) { + updateButtonState(true); + } + + @Override + public void onSuccessDownload(String fileName) { + updateButtonState(true); + } + + @Override + public void onProgressDownload(String fileName, float progress) { + radialProgress.setProgress(progress, true); + if (buttonState != 3) { + updateButtonState(false); + } + } + + @Override + public void onProgressUpload(String fileName, float progress, boolean isEncrypted) { + radialProgress.setProgress(progress, true); + } + + @Override + public int getObserverTag() { + return TAG; + } + + @Override + public void onSeekBarDrag(float progress) { + if (currentMessageObject == null) { + return; + } + currentMessageObject.audioProgress = progress; + MediaController.getInstance().seekToProgress(currentMessageObject, progress); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = MeasureSpec.getSize(widthMeasureSpec); + setMeasuredDimension(width, AndroidUtilities.dp(78) + namesOffset); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + if (currentMessageObject.isOut()) { + seekBarX = layoutWidth - backgroundWidth + AndroidUtilities.dp(52); + buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(13); + timeX = layoutWidth - backgroundWidth + AndroidUtilities.dp(63); + } else { + if (isChat) { + seekBarX = AndroidUtilities.dp(113); + buttonX = AndroidUtilities.dp(74); + timeX = AndroidUtilities.dp(124); + } else { + seekBarX = AndroidUtilities.dp(61); + buttonX = AndroidUtilities.dp(22); + timeX = AndroidUtilities.dp(72); + } + } + + seekBar.width = backgroundWidth - AndroidUtilities.dp(67); + seekBar.height = AndroidUtilities.dp(30); + seekBarY = AndroidUtilities.dp(26) + namesOffset; + buttonY = AndroidUtilities.dp(13) + namesOffset; + radialProgress.setProgressRect(buttonX, buttonY, buttonX + AndroidUtilities.dp(40), buttonY + AndroidUtilities.dp(40)); + + updateProgress(); + } + + @Override + public void setMessageObject(MessageObject messageObject) { + boolean dataChanged = currentMessageObject == messageObject && isUserDataChanged(); + if (currentMessageObject != messageObject || dataChanged) { + 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)); + } + + if (messageObject.isOut()) { + seekBar.type = 0; + radialProgress.setProgressColor(0xff87bf78); + } else { + seekBar.type = 1; + radialProgress.setProgressColor(0xffa2b5c7); + } + + int maxWidth = backgroundWidth - AndroidUtilities.dp(86); + + CharSequence stringFinal = TextUtils.ellipsize(messageObject.getMusicTitle().replace("\n", " "), titlePaint, maxWidth, TextUtils.TruncateAt.END); + titleLayout = new StaticLayout(stringFinal, titlePaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (titleLayout.getLineCount() > 0) { + titleX = (int) Math.ceil(titleLayout.getLineLeft(0)); + } + + stringFinal = TextUtils.ellipsize(messageObject.getMusicAuthor().replace("\n", " "), authorPaint, maxWidth, TextUtils.TruncateAt.END); + authorLayout = new StaticLayout(stringFinal, authorPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (authorLayout.getLineCount() > 0) { + authorX = (int) Math.ceil(authorLayout.getLineLeft(0)); + } + + super.setMessageObject(messageObject); + } + updateButtonState(dataChanged); + } + + private Drawable getDrawableForCurrentState() { + return ResourceLoader.audioStatesDrawable[currentMessageObject.isOut() ? buttonState : buttonState + 5][0]; + //buttonPressed ? 1 : + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (currentMessageObject == null) { + return; + } + + if (currentMessageObject.isOut()) { + timePaint.setColor(0xff70b15c); + } else { + timePaint.setColor(0xffa1aab3); + } + radialProgress.onDraw(canvas); + + canvas.save(); + canvas.translate(timeX + titleX, AndroidUtilities.dp(12) + namesOffset); + titleLayout.draw(canvas); + canvas.restore(); + + canvas.save(); + if (MediaController.getInstance().isPlayingAudio(currentMessageObject)) { + canvas.translate(seekBarX, seekBarY); + seekBar.draw(canvas); + } else { + canvas.translate(timeX + authorX, AndroidUtilities.dp(32) + namesOffset); + authorLayout.draw(canvas); + } + canvas.restore(); + + canvas.save(); + canvas.translate(timeX, AndroidUtilities.dp(52) + namesOffset); + timeLayout.draw(canvas); + canvas.restore(); + } +} 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 b163ec918..73ac7d063 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -356,15 +356,7 @@ public class DialogCell extends BaseCell { if (message.isOut()) { name = LocaleController.getString("FromYou", R.string.FromYou); } else { - if (UserObject.isDeleted(fromUser)) { - name = "Deleted"; - } else { - if (fromUser.first_name != null && fromUser.first_name.length() > 0) { - name = fromUser.first_name; - } else { - name = fromUser.last_name; - } - } + name = UserObject.getFirstName(fromUser); } checkMessage = false; if (message.caption != null) { @@ -373,11 +365,11 @@ public class DialogCell extends BaseCell { mess = mess.substring(0, 150); } mess = mess.replace("\n", " "); - messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20)); + messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } else { if (message.messageOwner.media != null && !message.isMediaEmpty()) { currentMessagePaint = messagePrintingPaint; - messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, message.messageText), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20)); + messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, message.messageText), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } else { if (message.messageOwner.message != null) { String mess = message.messageOwner.message; @@ -385,7 +377,7 @@ public class DialogCell extends BaseCell { mess = mess.substring(0, 150); } mess = mess.replace("\n", " "); - messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20)); + messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); } } } @@ -580,7 +572,7 @@ public class DialogCell extends BaseCell { mess = mess.substring(0, 150); } mess = mess.replace("\n", " "); - messageString = Emoji.replaceEmoji(mess, messagePaint.getFontMetricsInt(), AndroidUtilities.dp(17)); + messageString = Emoji.replaceEmoji(mess, messagePaint.getFontMetricsInt(), AndroidUtilities.dp(17), false); } messageWidth = Math.max(AndroidUtilities.dp(12), messageWidth); CharSequence messageStringFinal = TextUtils.ellipsize(messageString, currentMessagePaint, messageWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java index 54414ebc2..c389b017d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java @@ -13,7 +13,6 @@ import android.widget.FrameLayout; import android.widget.ImageView; import org.telegram.android.AndroidUtilities; -import org.telegram.messenger.R; import org.telegram.ui.Components.LayoutHelper; public class PhotoAttachCameraCell extends FrameLayout { @@ -23,7 +22,7 @@ public class PhotoAttachCameraCell extends FrameLayout { ImageView imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setImageResource(R.drawable.ic_attach_photobig); + //imageView.setImageResource(R.drawable.ic_attach_photobig); imageView.setBackgroundColor(0xff777777); addView(imageView, LayoutHelper.createFrame(80, 80)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java index bf00964c4..9018a1623 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java @@ -81,5 +81,6 @@ public class PhotoAttachPhotoCell extends FrameLayout { public void setOnCheckClickLisnener(OnClickListener onCheckClickLisnener) { checkFrame.setOnClickListener(onCheckClickLisnener); + imageView.setOnClickListener(onCheckClickLisnener); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index 7cc059b68..9d677bb44 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -100,7 +100,7 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F }); nameTextView = new TextView(context); - nameTextView.setTextColor(0xff222222); + nameTextView.setTextColor(0xff212121); nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); nameTextView.setLines(1); @@ -318,6 +318,9 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F @Override public void onProgressDownload(String fileName, float progress) { + if (progressView.getVisibility() != VISIBLE) { + updateFileExistIcon(); + } progressView.setProgress(progress, true); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java index 1646b509b..010b51a0c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java @@ -28,7 +28,7 @@ public class SharedMediaSectionCell extends FrameLayout { textView = new TextView(getContext()); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - textView.setTextColor(0xff222222); + textView.setTextColor(0xff212121); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 13, 0, 13, 0)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java index ce803d315..1f5c47eeb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java @@ -63,14 +63,14 @@ public class StickerEmojiCell extends FrameLayout { for (TLRPC.DocumentAttribute attribute : document.attributes) { if (attribute instanceof TLRPC.TL_documentAttributeSticker) { if (attribute.alt != null && attribute.alt.length() > 0) { - emojiTextView.setText(Emoji.replaceEmoji(attribute.alt, emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16))); + emojiTextView.setText(Emoji.replaceEmoji(attribute.alt, emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16), false)); set = true; } break; } } if (!set) { - emojiTextView.setText(Emoji.replaceEmoji(StickersQuery.getEmojiForSticker(sticker.id), emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16))); + emojiTextView.setText(Emoji.replaceEmoji(StickersQuery.getEmojiForSticker(sticker.id), emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16), false)); } emojiTextView.setVisibility(VISIBLE); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java index 7889b7803..7cab5ae05 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java @@ -36,7 +36,7 @@ public class TextDetailCell extends FrameLayout { textView.setMaxLines(1); textView.setSingleLine(true); textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 10, LocaleController.isRTL ? 16 : 71, 0)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 10, LocaleController.isRTL ? 71 : 16, 0)); valueTextView = new TextView(context); valueTextView.setTextColor(0xff8a8a8a); @@ -45,7 +45,7 @@ public class TextDetailCell extends FrameLayout { valueTextView.setMaxLines(1); valueTextView.setSingleLine(true); valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 35, LocaleController.isRTL ? 16 : 71, 0)); + addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 35, LocaleController.isRTL ? 71 : 16, 0)); imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java index 8eb72c7e1..2addf5a7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java @@ -16,7 +16,6 @@ import android.text.InputType; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -57,7 +56,7 @@ public class ChangeChatNameActivity extends BaseFragment { } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("EditName", R.string.EditName)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java index 5c0088490..a71dcc505 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java @@ -15,7 +15,6 @@ import android.text.InputType; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -50,7 +49,7 @@ public class ChangeNameActivity extends BaseFragment { private final static int done_button = 1; @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("EditName", R.string.EditName)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java index bc6040073..b06244418 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java @@ -24,7 +24,6 @@ import android.text.TextWatcher; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.animation.AccelerateDecelerateInterpolator; @@ -102,7 +101,7 @@ public class ChangePhoneActivity extends BaseFragment { } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName)); actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java index e4077ef3b..5144dc26d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java @@ -13,7 +13,6 @@ import android.content.Context; import android.content.DialogInterface; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; @@ -36,7 +35,7 @@ import org.telegram.ui.Components.LayoutHelper; public class ChangePhoneHelpActivity extends BaseFragment { @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java index 0e40b1a41..0f607ee9a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java @@ -20,7 +20,6 @@ import android.text.TextWatcher; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -62,7 +61,7 @@ public class ChangeUsernameActivity extends BaseFragment { private final static int done_button = 1; @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("Username", R.string.Username)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 8e59129c3..0077cde01 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -14,7 +14,6 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; -import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.Cursor; @@ -32,7 +31,6 @@ import android.util.Base64; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -40,6 +38,7 @@ import android.view.ViewTreeObserver; import android.view.WindowManager; import android.webkit.MimeTypeMap; import android.widget.AdapterView; +import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -96,6 +95,7 @@ import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.Cells.ChatMessageCell; +import org.telegram.ui.Cells.ChatMusicCell; import org.telegram.ui.Cells.ChatUnreadCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AvatarDrawable; @@ -123,7 +123,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.concurrent.Semaphore; -public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate, +public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.MessagesActivityDelegate, PhotoViewer.PhotoViewerProvider { protected TLRPC.Chat currentChat; @@ -177,6 +177,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private ListView mentionListView; private AnimatorSetProxy mentionListAnimation; private ChatAttachView chatAttachView; + private BottomSheet chatAttachViewSheet; private boolean allowStickersPanel; private AnimatorSetProxy runningAnimation; @@ -455,6 +456,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.getInstance().addObserver(this, NotificationCenter.removeAllMessagesFromDialog); NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioProgressDidChanged); NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged); NotificationCenter.getInstance().addObserver(this, NotificationCenter.screenshotTook); NotificationCenter.getInstance().addObserver(this, NotificationCenter.blockedUsersDidLoaded); NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileNewChunkAvailable); @@ -558,6 +560,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.getInstance().removeObserver(this, NotificationCenter.botInfoDidLoaded); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.botKeyboardDidLoaded); NotificationCenter.getInstance().removeObserver(this, NotificationCenter.chatSearchResultsAvailable); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged); if (AndroidUtilities.isTablet()) { NotificationCenter.getInstance().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, true); @@ -578,11 +581,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatAttachView.onDestroy(); } AndroidUtilities.unlockOrientation(getParentActivity()); - MediaController.getInstance().stopAudio(); + MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + if (messageObject != null && !messageObject.isMusic()) { + MediaController.getInstance().stopAudio(); + } } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { for (int a = 0; a < 8; a++) { chatMessageCellsCache.add(new ChatMessageCell(context)); @@ -595,6 +601,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not lastStatus = null; hasOwnBackground = true; chatAttachView = null; + chatAttachViewSheet = null; ResourceLoader.loadRecources(context); @@ -673,7 +680,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", 1); - MessagesActivity fragment = new MessagesActivity(args); + DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ChatActivity.this); presentFragment(fragment); } else if (id == chat_enc_timer) { @@ -770,20 +777,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedMessagesCanCopyIds.clear(); actionBar.hideActionMode(); updateVisibleRows(); - }/* else if (id == chat_menu_attach) { + } else if (id == chat_menu_attach) { if (getParentActivity() == null) { return; } - BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); + if (chatAttachView == null) { + BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); chatAttachView = new ChatAttachView(getParentActivity()); chatAttachView.setDelegate(new ChatAttachView.ChatAttachViewDelegate() { @Override public void didPressedButton(int button) { - if (visibleDialog != null) { - visibleDialog.dismiss(); - } if (button == 7) { + chatAttachViewSheet.dismiss(); HashMap selectedPhotos = chatAttachView.getSelectedPhotos(); if (!selectedPhotos.isEmpty()) { ArrayList photos = new ArrayList<>(); @@ -796,31 +802,50 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showReplyPanel(false, null, null, null, false, true); } return; + } else { + chatAttachViewSheet.dismissWithButtonClick(button); } processSelectedAttach(button); } }); + builder.setDelegate(new BottomSheet.BottomSheetDelegate() { + + @Override + public void onRevealAnimationStart(boolean open) { + chatAttachView.onRevealAnimationStart(open); + } + + @Override + public void onRevealAnimationProgress(boolean open, float radius, int x, int y) { + chatAttachView.onRevealAnimationProgress(open, radius, x, y); + } + + @Override + public void onRevealAnimationEnd(boolean open) { + chatAttachView.onRevealAnimationEnd(open); + } + + @Override + public void onOpenAnimationEnd() { + chatAttachView.onRevealAnimationEnd(true); + } + + @Override + public View getRevealView() { + return menuItem; + } + }); + builder.setApplyTopPaddings(false); + builder.setUseRevealAnimation(); + builder.setCustomView(chatAttachView); + chatAttachViewSheet = builder.create(); } - builder.setCustomView(chatAttachView); - final int coords[] = new int[2]; - menuItem.getLocationInWindow(coords); - builder.setRevealAnimation(coords[0] + menuItem.getWidth() / 2, coords[1] + menuItem.getHeight() / 2); - builder.setDelegate(new BottomSheet.BottomSheetDelegate() { - @Override - public void onOpenAnimationStart() { - chatAttachView.startAnimations(coords[1] > AndroidUtilities.displaySize.y - AndroidUtilities.dp(100)); - } - @Override - public void onOpenAnimationEnd() { - - } - }); chatAttachView.init(ChatActivity.this); - showDialog(builder.create()); - }*/ else if (id == attach_gallery || id == attach_video || id == attach_document || id == attach_location || id == attach_photo || id == attach_audio || id == attach_contact) { + showDialog(chatAttachViewSheet); + }/* else if (id == attach_gallery || id == attach_video || id == attach_document || id == attach_location || id == attach_photo || id == attach_audio || id == attach_contact) { processSelectedAttach(id); - } else if (id == bot_help) { + } */else if (id == bot_help) { SendMessagesHelper.getInstance().sendMessage("/help", dialog_id, null, null, false); } else if (id == bot_settings) { SendMessagesHelper.getInstance().sendMessage("/settings", dialog_id, null, null, false); @@ -922,12 +947,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ActionBarMenu menu = actionBar.createMenu(); if (currentEncryptedChat == null && !isBroadcast) { - /*searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true, false).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { + searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true, false).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override public void onSearchCollapse() { avatarContainer.setVisibility(View.VISIBLE); - headerItem.setVisibility(View.VISIBLE); + if (chatActivityEnterView.hasText()) { + if (headerItem != null) { + headerItem.setVisibility(View.GONE); + } + if (attachItem != null) { + attachItem.setVisibility(View.VISIBLE); + } + } else { + if (headerItem != null) { + headerItem.setVisibility(View.VISIBLE); + } + if (attachItem != null) { + attachItem.setVisibility(View.GONE); + } + } searchItem.setVisibility(View.GONE); //chatActivityEnterView.setVisibility(View.VISIBLE); searchUpItem.clearAnimation(); @@ -945,7 +984,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchItem.getSearchField().requestFocus(); AndroidUtilities.showKeyboard(searchItem.getSearchField()); } - }, 200); //TODO find a better way to open keyboard + }, 300); //TODO find a better way to open keyboard } @Override @@ -960,7 +999,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUpItem = menu.addItem(search_up, R.drawable.search_up); searchUpItem.setVisibility(View.GONE); searchDownItem = menu.addItem(search_down, R.drawable.search_down); - searchDownItem.setVisibility(View.GONE);*/ + searchDownItem.setVisibility(View.GONE); } headerItem = menu.addItem(0, R.drawable.ic_ab_other); @@ -990,22 +1029,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateSubtitle(); updateTitleIcons(); - attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other).setAllowCloseAnimation(false); - attachItem.addSubItem(attach_photo, LocaleController.getString("ChatTakePhoto", R.string.ChatTakePhoto), R.drawable.ic_attach_photo); - attachItem.addSubItem(attach_gallery, LocaleController.getString("ChatGallery", R.string.ChatGallery), R.drawable.ic_attach_gallery); - attachItem.addSubItem(attach_video, LocaleController.getString("ChatVideo", R.string.ChatVideo), R.drawable.ic_attach_video); - attachItem.addSubItem(attach_document, LocaleController.getString("ChatDocument", R.string.ChatDocument), R.drawable.ic_ab_doc); - attachItem.addSubItem(attach_location, LocaleController.getString("ChatLocation", R.string.ChatLocation), R.drawable.ic_attach_location); + attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other).setOverrideMenuClick(true).setAllowCloseAnimation(false); attachItem.setVisibility(View.GONE); - menuItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_attach).setAllowCloseAnimation(false); - menuItem.addSubItem(attach_photo, LocaleController.getString("ChatTakePhoto", R.string.ChatTakePhoto), R.drawable.ic_attach_photo); - menuItem.addSubItem(attach_gallery, LocaleController.getString("ChatGallery", R.string.ChatGallery), R.drawable.ic_attach_gallery); - menuItem.addSubItem(attach_video, LocaleController.getString("ChatVideo", R.string.ChatVideo), R.drawable.ic_attach_video); - menuItem.addSubItem(attach_document, LocaleController.getString("ChatDocument", R.string.ChatDocument), R.drawable.ic_ab_doc); - menuItem.addSubItem(attach_location, LocaleController.getString("ChatLocation", R.string.ChatLocation), R.drawable.ic_attach_location); - menuItem.setShowFromBottom(true); - menuItem.setBackgroundDrawable(null); actionModeViews.clear(); @@ -1053,8 +1079,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); @@ -1067,14 +1091,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - if (child == chatActivityEnterView) { - measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0); - inputFieldHeight = child.getMeasuredHeight(); - break; - } - } + + measureChildWithMargins(chatActivityEnterView, widthMeasureSpec, 0, heightMeasureSpec, 0); + inputFieldHeight = chatActivityEnterView.getMeasuredHeight(); + for (int i = 0; i < childCount; i++) { View child = getChildAt(i); if (child.getVisibility() == GONE || child == chatActivityEnterView) { @@ -1660,6 +1680,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onAttachButtonHidden() { + if (actionBar.isSearchFieldVisible()) { + return; + } if (attachItem != null) { attachItem.setVisibility(View.VISIBLE); } @@ -1670,6 +1693,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onAttachButtonShow() { + if (actionBar.isSearchFieldVisible()) { + return; + } if (attachItem != null) { attachItem.setVisibility(View.GONE); } @@ -1680,7 +1706,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onWindowSizeChanged(int size) { - if (size < AndroidUtilities.dp(72) + AndroidUtilities.getCurrentActionBarHeight()) { + if (size < AndroidUtilities.dp(72) + ActionBar.getCurrentActionBarHeight()) { allowStickersPanel = false; if (stickersPanel.getVisibility() == View.VISIBLE) { stickersPanel.clearAnimation(); @@ -2089,12 +2115,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); presentFragment(fragment); } else if (which == attach_audio) { - try { - Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI); - startActivityForResult(intent, 32); - } catch (Exception e) { - FileLog.e("tmessages", e); - } + AudioSelectActivity fragment = new AudioSelectActivity(); + fragment.setDelegate(new AudioSelectActivity.AudioSelectActivityDelegate() { + @Override + public void didSelectAudio(ArrayList audios) { + SendMessagesHelper.prepareSendingAudioDocuments(audios, dialog_id, replyingMessageObject); + showReplyPanel(false, null, null, null, false, true); + } + }); + presentFragment(fragment); } else if (which == attach_contact) { try { Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); @@ -2216,7 +2245,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mess = mess.substring(0, 150); } mess = mess.replace("\n", " "); - replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14))); + replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); } } else if (messageObjects != null) { if (messageObjects.isEmpty()) { @@ -2277,7 +2306,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mess = mess.substring(0, 150); } mess = mess.replace("\n", " "); - replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14))); + replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); } else { replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedMessage", messageObjects.size())); } @@ -2296,7 +2325,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (type == 12) { replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedContact", messageObjects.size())); - } else if (type == 2) { + } else if (type == 2 || type == 14) { replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedAudio", messageObjects.size())); } else if (type == 13) { replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedSticker", messageObjects.size())); @@ -3221,22 +3250,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not FileLog.e("tmessages", e); } } - } else if (requestCode == 32) { - if (data == null || data.getData() == null) { - showAttachmentError(); - return; - } - Uri uri = data.getData(); - String path = AndroidUtilities.getPath(uri); - if (path != null) { - TLRPC.TL_audio audio = new TLRPC.TL_audio(); - audio.dc_id = Integer.MIN_VALUE; - audio.id = Integer.MIN_VALUE; - audio.user_id = UserConfig.getClientUserId(); - audio.mime_type = "audio/mp3"; - SendMessagesHelper.getInstance().sendMessage(audio, path, dialog_id, replyingMessageObject); - showReplyPanel(false, null, null, null, false, true); - } } } } @@ -3587,7 +3600,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentEncryptedChat != null && obj.isOut() && obj.messageOwner.action != null && obj.messageOwner.action instanceof TLRPC.TL_messageEncryptedAction && obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL && getParentActivity() != null) { - TLRPC.TL_decryptedMessageActionSetMessageTTL action = (TLRPC.TL_decryptedMessageActionSetMessageTTL) obj.messageOwner.action.encryptedAction; 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)); @@ -4005,7 +4017,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int encId = (Integer) args[0]; if (currentEncryptedChat != null && currentEncryptedChat.id == encId) { int date = (Integer) args[1]; - boolean started = false; for (MessageObject obj : messages) { if (!obj.isOut()) { continue; @@ -4018,7 +4029,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } updateVisibleRows(); } - } else if (id == NotificationCenter.audioDidReset) { + } else if (id == NotificationCenter.audioDidReset || id == NotificationCenter.audioPlayStateChanged) { Integer mid = (Integer) args[0]; if (chatListView != null) { int count = chatListView.getChildCount(); @@ -4027,7 +4038,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (view instanceof ChatAudioCell) { ChatAudioCell cell = (ChatAudioCell) view; if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { - cell.updateButtonState(); + cell.updateButtonState(false); + break; + } + } else if (view instanceof ChatMusicCell) { + ChatMusicCell cell = (ChatMusicCell) view; + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { + cell.updateButtonState(false); break; } } @@ -4045,6 +4062,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not cell.updateProgress(); break; } + } else if (view instanceof ChatMusicCell) { + ChatMusicCell cell = (ChatMusicCell) view; + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { + MessageObject playing = cell.getMessageObject(); + MessageObject player = MediaController.getInstance().getPlayingMessageObject(); + playing.audioProgress = player.audioProgress; + playing.audioProgressSec = player.audioProgressSec; + cell.updateProgress(); + break; + } } } } @@ -4121,6 +4148,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (id == NotificationCenter.audioDidStarted) { MessageObject messageObject = (MessageObject) args[0]; sendSecretMessageRead(messageObject); + + int mid = messageObject.getId(); + if (chatListView != null) { + int count = chatListView.getChildCount(); + for (int a = 0; a < count; a++) { + View view = chatListView.getChildAt(a); + if (view instanceof ChatAudioCell) { + ChatAudioCell cell = (ChatAudioCell) view; + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { + cell.updateButtonState(false); + break; + } + } else if (view instanceof ChatMusicCell) { + ChatMusicCell cell = (ChatMusicCell) view; + if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) { + cell.updateButtonState(false); + break; + } + } + } + } } else if (id == NotificationCenter.updateMessageMedia) { MessageObject messageObject = (MessageObject) args[0]; MessageObject existMessageObject = messagesDict.get(messageObject.getId()); @@ -4555,7 +4603,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not actionBar.setBackButtonImage(R.drawable.ic_close_white); } } - int padding = (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2; + int padding = (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2; avatarContainer.setPadding(avatarContainer.getPaddingLeft(), padding, avatarContainer.getPaddingRight(), padding); FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) avatarContainer.getLayoutParams(); layoutParams.topMargin = (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0); @@ -4629,7 +4677,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + String saveString; + if (selectedObject.isMusic()) { + saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic); + } else { + saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads); + } + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{8, 10, 4, 2, 1}; } 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)}; @@ -4639,7 +4693,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + String saveString; + if (selectedObject.isMusic()) { + saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic); + } else { + saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads); + } + items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{8, 7, 10, 6, 2, 1}; } else if (type == 7) { items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("AddToStickers", R.string.AddToStickers), LocaleController.getString("Delete", R.string.Delete)}; @@ -4654,7 +4714,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options = new int[]{2, 3, 1}; } else if (type == 4) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { - items = new CharSequence[]{LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + String saveString; + if (selectedObject.isMusic()) { + saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic); + } else { + saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads); + } + items = new CharSequence[]{saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{10, 4, 2, 1}; } else { items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; @@ -4664,7 +4730,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not 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("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; + String saveString; + if (selectedObject.isMusic()) { + saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic); + } else { + saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads); + } + items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{7, 10, 6, 2, 1}; } else if (type == 7) { items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("AddToStickers", R.string.AddToStickers), LocaleController.getString("Delete", R.string.Delete)}; @@ -4680,7 +4752,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options = new int[]{3, 1}; } else if (type == 4) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) { - items = new CharSequence[]{LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Delete", R.string.Delete)}; + String saveString; + if (selectedObject.isMusic()) { + saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic); + } else { + saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads); + } + items = new CharSequence[]{saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Delete", R.string.Delete)}; options = new int[]{10, 4, 1}; } else { items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Delete", R.string.Delete)}; @@ -4770,7 +4848,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", 1); - MessagesActivity fragment = new MessagesActivity(args); + DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(this); presentFragment(fragment); } else if (option == 3) { @@ -4787,7 +4865,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not FileLog.e("tmessages", e); } } else if (option == 4) { - String fileName = selectedObject.getFileName(); String path = selectedObject.messageOwner.attachPath; if (path != null && path.length() > 0) { File temp = new File(path); @@ -4802,7 +4879,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not MediaController.saveFile(path, getParentActivity(), 1, null); } else if (selectedObject.type == 1) { MediaController.saveFile(path, getParentActivity(), 0, null); - } else if (selectedObject.type == 8 || selectedObject.type == 9) { + } else if (selectedObject.type == 8 || selectedObject.type == 9 || selectedObject.type == 14) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(selectedObject.messageOwner.media.document.mime_type); intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path))); @@ -4837,7 +4914,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } else if (option == 6 || option == 7) { - String fileName = selectedObject.getFileName(); String path = selectedObject.messageOwner.attachPath; if (path != null && path.length() > 0) { File temp = new File(path); @@ -4848,7 +4924,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (path == null || path.length() == 0) { path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); } - if (selectedObject.type == 8 || selectedObject.type == 9) { + if (selectedObject.type == 8 || selectedObject.type == 9 || selectedObject.type == 14) { if (option == 6) { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(selectedObject.messageOwner.media.document.mime_type); @@ -4877,13 +4953,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (path == null || path.length() == 0) { path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); } - MediaController.saveFile(path, getParentActivity(), 2, fileName); + MediaController.saveFile(path, getParentActivity(), selectedObject.isMusic() ? 3 : 2, fileName); } selectedObject = null; } @Override - public void didSelectDialog(MessagesActivity activity, long did, boolean param) { + public void didSelectDialog(DialogsActivity activity, long did, boolean param) { if (dialog_id != 0 && (forwaringMessage != null || !selectedMessagesIds.isEmpty())) { ArrayList fmessages = new ArrayList<>(); if (forwaringMessage != null) { @@ -4961,7 +5037,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public boolean isGoogleMapsInstalled() { try { - ApplicationInfo info = ApplicationLoader.applicationContext.getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0); + ApplicationLoader.applicationContext.getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0); return true; } catch (PackageManager.NameNotFoundException e) { if (getParentActivity() == null) { @@ -5213,7 +5289,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (url.startsWith("@")) { MessagesController.openByUserName(url.substring(1), ChatActivity.this, 0); } else if (url.startsWith("#")) { - MessagesActivity fragment = new MessagesActivity(null); + DialogsActivity fragment = new DialogsActivity(null); fragment.setSearchString(url); presentFragment(fragment); } else if (url.startsWith("/")) { @@ -5221,6 +5297,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } }); + } else if (viewType == 8) { + view = new ChatMusicCell(mContext); } if (view instanceof ChatBaseCell) { @@ -5261,7 +5339,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (url.startsWith("@")) { MessagesController.openByUserName(url.substring(1), ChatActivity.this, 0); } else if (url.startsWith("#")) { - MessagesActivity fragment = new MessagesActivity(null); + DialogsActivity fragment = new DialogsActivity(null); fragment.setSearchString(url); presentFragment(fragment); } else if (url.startsWith("/")) { @@ -5273,7 +5351,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void needOpenWebView(String url, String title, String originalUrl, int w, int h) { BottomSheet.Builder builder = new BottomSheet.Builder(mContext); builder.setCustomView(new WebFrameLayout(mContext, builder.create(), title, originalUrl, url, w, h)); - builder.setOverrideTabletWidth(true); + builder.setUseFullWidth(true); showDialog(builder.create()); } @@ -5434,6 +5512,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(builder.create()); } }); + } else if (view instanceof ChatMusicCell) { + ((ChatMusicCell) view).setMusicDelegate(new ChatMusicCell.ChatMusicCellDelegate() { + @Override + public boolean needPlayMusic(MessageObject messageObject) { + return MediaController.getInstance().setPlaylist(messages, messageObject); + } + }); } } else if (view instanceof ChatActionCell) { ((ChatActionCell) view).setDelegate(new ChatActionCell.ChatActionCellDelegate() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java index cb8164d78..a6d987748 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java @@ -57,7 +57,7 @@ public class BotKeyboardView extends LinearLayout { public void setPanelHeight(int height) { panelHeight = height; - if (isFullSize && botButtons != null) { + if (isFullSize && botButtons != null && botButtons.rows.size() != 0) { buttonHeight = !isFullSize ? 42 : (int) Math.max(42, (panelHeight - AndroidUtilities.dp(30) - (botButtons.rows.size() - 1) * AndroidUtilities.dp(10)) / botButtons.rows.size() / AndroidUtilities.density); int count = container.getChildCount(); int newHeight = AndroidUtilities.dp(buttonHeight); @@ -87,7 +87,7 @@ public class BotKeyboardView extends LinearLayout { container.removeAllViews(); buttonViews.clear(); - if (buttons != null) { + if (buttons != null && botButtons.rows.size() != 0) { isFullSize = (buttons.flags & 1) == 0; buttonHeight = !isFullSize ? 42 : (int) Math.max(42, (panelHeight - AndroidUtilities.dp(30) - (botButtons.rows.size() - 1) * AndroidUtilities.dp(10)) / botButtons.rows.size() / AndroidUtilities.density); for (int a = 0; a < buttons.rows.size(); a++) { @@ -106,7 +106,7 @@ public class BotKeyboardView extends LinearLayout { textView.setGravity(Gravity.CENTER); textView.setBackgroundResource(R.drawable.bot_keyboard_states); textView.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); - textView.setText(Emoji.replaceEmoji(button.text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16))); + textView.setText(Emoji.replaceEmoji(button.text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16), false)); layout.addView(textView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, weight, 0, 0, b != row.buttons.size() - 1 ? 10 : 0, 0)); textView.setOnClickListener(new OnClickListener() { @Override 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 6fc40e4a8..b939a3ec7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -44,6 +44,7 @@ import org.telegram.android.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.TLRPC; import org.telegram.messenger.UserConfig; +import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.android.AnimationCompat.AnimatorListenerAdapterProxy; import org.telegram.android.AnimationCompat.AnimatorSetProxy; @@ -117,6 +118,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat private BaseFragment parentFragment; private long dialog_id; private boolean ignoreTextChange; + private int innerTextChange; private MessageObject replyingMessageObject; private MessageObject botMessageObject; private TLRPC.WebPage messageWebPage; @@ -187,7 +189,16 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } }); - messageEditText = new EditText(context); + messageEditText = new EditText(context) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isPopupShowing() && event.getAction() == MotionEvent.ACTION_DOWN) { + showPopup(AndroidUtilities.usingHardwareInput ? 0 : 2, 0); + openKeyboardInternal(); + } + return super.onTouchEvent(event); + } + }; messageEditText.setHint(LocaleController.getString("TypeMessage", R.string.TypeMessage)); messageEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); messageEditText.setInputType(messageEditText.getInputType() | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE); @@ -216,14 +227,6 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat return false; } }); - messageEditText.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (isPopupShowing()) { - showPopup(AndroidUtilities.usingHardwareInput ? 0 : 2, 0); - } - } - }); messageEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) { @@ -240,6 +243,8 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } }); messageEditText.addTextChangedListener(new TextWatcher() { + boolean processChange = false; + @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { @@ -247,16 +252,20 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat @Override public void onTextChanged(CharSequence charSequence, int start, int before, int count) { - String message = getTrimmedString(charSequence.toString()); + if (innerTextChange == 1) { + return; + } checkSendButton(true); - + String message = getTrimmedString(charSequence.toString()); if (delegate != null) { if (count > 2 || charSequence == null || charSequence.length() == 0) { messageWebPageSearch = true; } delegate.onTextChanged(charSequence, before > count + 1 || (count - before) > 2); } - + if (innerTextChange != 2 && before != count && (count - before) > 1) { + processChange = true; + } if (message.length() != 0 && lastTypingTimeSend < System.currentTimeMillis() - 5000 && !ignoreTextChange) { int currentTime = ConnectionsManager.getInstance().getCurrentTime(); TLRPC.User currentUser = null; @@ -275,19 +284,19 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat @Override public void afterTextChanged(Editable editable) { + if (innerTextChange != 0) { + return; + } if (sendByEnter && editable.length() > 0 && editable.charAt(editable.length() - 1) == '\n') { sendMessage(); } - int i = 0; - ImageSpan[] arrayOfImageSpan = editable.getSpans(0, editable.length(), ImageSpan.class); - int j = arrayOfImageSpan.length; - while (true) { - if (i >= j) { - Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); - return; + if (processChange) { + ImageSpan[] spans = editable.getSpans(0, editable.length(), ImageSpan.class); + for (int i = 0; i < spans.length; i++) { + editable.removeSpan(spans[i]); } - editable.removeSpan(arrayOfImageSpan[i]); - i++; + Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); + processChange = false; } } }); @@ -590,7 +599,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat delegate.onWindowSizeChanged(size); } if (topView != null) { - if (size < AndroidUtilities.dp(72) + AndroidUtilities.getCurrentActionBarHeight()) { + if (size < AndroidUtilities.dp(72) + ActionBar.getCurrentActionBarHeight()) { if (allowShowTopView) { allowShowTopView = false; if (needShowTopView) { @@ -773,11 +782,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat }); runningAnimation2.start(); - if (messageEditText != null) { - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams(); - layoutParams.rightMargin = AndroidUtilities.dp(0); - messageEditText.setLayoutParams(layoutParams); - } + updateFieldRight(0); delegate.onAttachButtonHidden(); } @@ -823,9 +828,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat attachButton.setVisibility(View.GONE); attachButton.clearAnimation(); delegate.onAttachButtonHidden(); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams(); - layoutParams.rightMargin = AndroidUtilities.dp(0); - messageEditText.setLayoutParams(layoutParams); + updateFieldRight(0); } } } @@ -854,11 +857,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat runningAnimation2.setDuration(100); runningAnimation2.start(); - if (messageEditText != null) { - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams(); - layoutParams.rightMargin = AndroidUtilities.dp(50); - messageEditText.setLayoutParams(layoutParams); - } + updateFieldRight(1); delegate.onAttachButtonShow(); } @@ -903,14 +902,37 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat if (attachButton != null) { delegate.onAttachButtonShow(); attachButton.setVisibility(View.VISIBLE); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams(); - layoutParams.rightMargin = AndroidUtilities.dp(50); - messageEditText.setLayoutParams(layoutParams); + updateFieldRight(1); } } } } + private void updateFieldRight(int attachVisible) { + if (messageEditText == null) { + return; + } + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams(); + if (attachVisible == 1) { + if (botButton != null && botButton.getVisibility() == VISIBLE) { + layoutParams.rightMargin = AndroidUtilities.dp(98); + } else { + layoutParams.rightMargin = AndroidUtilities.dp(50); + } + } else if (attachVisible == 2) { + if (layoutParams.rightMargin != AndroidUtilities.dp(2)) { + if (botButton != null && botButton.getVisibility() == VISIBLE) { + layoutParams.rightMargin = AndroidUtilities.dp(98); + } else { + layoutParams.rightMargin = AndroidUtilities.dp(50); + } + } + } else { + layoutParams.rightMargin = AndroidUtilities.dp(2); + } + messageEditText.setLayoutParams(layoutParams); + } + private void updateAudioRecordIntefrace() { if (recordingAudio) { if (audioInterfaceState == 1) { @@ -1108,6 +1130,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat } else { botButton.setVisibility(GONE); } + updateFieldRight(2); ViewProxy.setPivotX(attachButton, AndroidUtilities.dp(botButton.getVisibility() == GONE ? 48 : 96)); attachButton.clearAnimation(); } @@ -1209,12 +1232,15 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat i = 0; } try { - CharSequence localCharSequence = Emoji.replaceEmoji(symbol/* + "\uFE0F"*/, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); + innerTextChange = 2; + CharSequence localCharSequence = Emoji.replaceEmoji(symbol/* + "\uFE0F"*/, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); messageEditText.setText(messageEditText.getText().insert(i, localCharSequence)); int j = i + localCharSequence.length(); messageEditText.setSelection(j, j); } catch (Exception e) { FileLog.e("tmessages", e); + } finally { + innerTextChange = 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java index 461e32f9b..3b175e09a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java @@ -8,8 +8,11 @@ package org.telegram.ui.Components; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; import android.content.Context; import android.os.Build; import android.text.TextUtils; @@ -18,6 +21,7 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -25,14 +29,16 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.android.MediaController; +import org.telegram.android.NotificationCenter; import org.telegram.android.support.widget.LinearLayoutManager; import org.telegram.messenger.R; import org.telegram.ui.Adapters.PhotoAttachAdapter; import org.telegram.ui.ChatActivity; +import java.util.ArrayList; import java.util.HashMap; -public class ChatAttachView extends FrameLayout { +public class ChatAttachView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { public interface ChatAttachViewDelegate { void didPressedButton(int button); @@ -42,7 +48,16 @@ public class ChatAttachView extends FrameLayout { private PhotoAttachAdapter photoAttachAdapter; private ChatActivity baseFragment; private AttachButton sendPhotosButton; - private AttachButton buttons[] = new AttachButton[8]; + private View views[] = new View[20]; + private RecyclerListView attachPhotoRecyclerView; + private View lineView; + private EmptyTextProgressView progressView; + + private float[] distCache = new float[20]; + + private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(); + + private boolean loading; private ChatAttachViewDelegate delegate; @@ -56,7 +71,6 @@ public class ChatAttachView extends FrameLayout { imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - //imageView.setColorFilter(0x33000000); addView(imageView, LayoutHelper.createFrame(64, 64, Gravity.CENTER_HORIZONTAL | Gravity.TOP)); textView = new TextView(context); @@ -83,10 +97,15 @@ public class ChatAttachView extends FrameLayout { public ChatAttachView(Context context) { super(context); - RecyclerListView attachPhotoRecyclerView = new RecyclerListView(context); - if (photoAttachAdapter != null) { - photoAttachAdapter.onDestroy(); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.albumsDidLoaded); + if (MediaController.allPhotosAlbumEntry == null) { + if (Build.VERSION.SDK_INT >= 21) { + MediaController.loadGalleryPhotosAlbums(0); + } + loading = true; } + + views[8] = attachPhotoRecyclerView = new RecyclerListView(context); attachPhotoRecyclerView.setVerticalScrollBarEnabled(true); attachPhotoRecyclerView.setAdapter(photoAttachAdapter = new PhotoAttachAdapter(context)); attachPhotoRecyclerView.setClipToPadding(false); @@ -112,11 +131,14 @@ public class ChatAttachView extends FrameLayout { } }); - View lineView = new View(getContext()); + views[9] = progressView = new EmptyTextProgressView(context); + progressView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos)); + addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 80)); + attachPhotoRecyclerView.setEmptyView(progressView); + + views[10] = lineView = new View(getContext()); lineView.setBackgroundColor(0xffd2d2d2); - FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1, Gravity.TOP | Gravity.LEFT); - layoutParams.topMargin = AndroidUtilities.dp(88); - addView(lineView, layoutParams); + addView(lineView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1, Gravity.TOP | Gravity.LEFT)); CharSequence[] items = new CharSequence[]{ LocaleController.getString("ChatCamera", R.string.ChatCamera), LocaleController.getString("ChatGallery", R.string.ChatGallery), @@ -128,23 +150,21 @@ public class ChatAttachView extends FrameLayout { "" }; int itemIcons[] = new int[] { - R.drawable.ic_attach_photo_big, - R.drawable.ic_attach_gallery_big, - R.drawable.ic_attach_video_big, - R.drawable.ic_attach_music_big, - R.drawable.ic_attach_file_big, - R.drawable.ic_attach_contact_big, - R.drawable.ic_attach_location_big, - R.drawable.ic_attach_hide_big, + R.drawable.attach_camera_states, + R.drawable.attach_gallery_states, + R.drawable.attach_video_states, + R.drawable.attach_audio_states, + R.drawable.attach_file_states, + R.drawable.attach_contact_states, + R.drawable.attach_location_states, + R.drawable.attach_hide_states, }; for (int a = 0; a < 8; a++) { AttachButton attachButton = new AttachButton(context); attachButton.setTextAndIcon(items[a], itemIcons[a]); - int y = 97 + 95 * (a / 4); - int x = 10 + (a % 4) * 85; - addView(attachButton, LayoutHelper.createFrame(85, 90, Gravity.LEFT | Gravity.TOP, x, y, 0, 0)); + addView(attachButton, LayoutHelper.createFrame(85, 90, Gravity.LEFT | Gravity.TOP)); attachButton.setTag(a); - buttons[a] = attachButton; + views[a] = attachButton; if (a == 7) { sendPhotosButton = attachButton; sendPhotosButton.imageView.setPadding(0, AndroidUtilities.dp(4), 0, 0); @@ -164,24 +184,58 @@ public class ChatAttachView extends FrameLayout { return true; } }); + + if (loading) { + progressView.showProgress(); + } else { + progressView.showTextView(); + } + } + + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.albumsDidLoaded) { + if (photoAttachAdapter != null) { + loading = false; + progressView.showTextView(); + photoAttachAdapter.notifyDataSetChanged(); + } + } } @Override protected void onMeasure(int widthSpec, int heightSpec) { - super.onMeasure(widthSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(278), MeasureSpec.EXACTLY)); + super.onMeasure(widthSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(294), MeasureSpec.EXACTLY)); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + int width = right - left; + + int t = AndroidUtilities.dp(8); + attachPhotoRecyclerView.layout(0, t, width, t + attachPhotoRecyclerView.getMeasuredHeight()); + progressView.layout(0, t, width, t + progressView.getMeasuredHeight()); + lineView.layout(0, AndroidUtilities.dp(96), width, AndroidUtilities.dp(96) + lineView.getMeasuredHeight()); + + int diff = (width - AndroidUtilities.dp(85 * 4 + 20)) / 3; + for (int a = 0; a < 8; a++) { + int y = AndroidUtilities.dp(105 + 95 * (a / 4)); + int x = AndroidUtilities.dp(10) + (a % 4) * (AndroidUtilities.dp(85) + diff); + views[a].layout(x, y, x + views[a].getMeasuredWidth(), y + views[a].getMeasuredHeight()); + } } public void updatePhotosButton() { int count = photoAttachAdapter.getSelectedPhotos().size(); if (count == 0) { sendPhotosButton.imageView.setPadding(0, AndroidUtilities.dp(4), 0, 0); - sendPhotosButton.imageView.setBackgroundResource(R.drawable.ic_attach_hide_big); - sendPhotosButton.imageView.setImageResource(R.drawable.ic_attach_hide_big_icon); + sendPhotosButton.imageView.setBackgroundResource(R.drawable.attach_hide_states); + sendPhotosButton.imageView.setImageResource(R.drawable.attach_hide2); sendPhotosButton.textView.setText(""); } else { sendPhotosButton.imageView.setPadding(AndroidUtilities.dp(2), 0, 0, 0); - sendPhotosButton.imageView.setBackgroundResource(R.drawable.ic_attach_send_big); - sendPhotosButton.imageView.setImageResource(R.drawable.ic_attach_send_big_icon); + sendPhotosButton.imageView.setBackgroundResource(R.drawable.attach_send_states); + sendPhotosButton.imageView.setImageResource(R.drawable.attach_send2); sendPhotosButton.textView.setText(LocaleController.formatString("SendItems", R.string.SendItems, String.format("(%d)", count))); } } @@ -190,22 +244,83 @@ public class ChatAttachView extends FrameLayout { delegate = chatAttachViewDelegate; } - public void startAnimations(boolean up) { - for (int a = 0; a < 4; a++) { - //buttons[a].setTranslationY(AndroidUtilities.dp(up ? 20 : -20)); - //buttons[a + 4].setTranslationY(AndroidUtilities.dp(up ? 20 : -20)); - buttons[a].setScaleX(0.8f); - buttons[a].setScaleY(0.8f); - buttons[a + 4].setScaleX(0.8f); - buttons[a + 4].setScaleY(0.8f); - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(buttons[a], "scaleX", 1), - ObjectAnimator.ofFloat(buttons[a + 4], "scaleX", 1), - ObjectAnimator.ofFloat(buttons[a], "scaleY", 1), - ObjectAnimator.ofFloat(buttons[a + 4], "scaleY", 1)); - animatorSet.setDuration(150); - animatorSet.setStartDelay((3 - a) * 40); - animatorSet.start(); + public void onRevealAnimationEnd(boolean open) { + if (open && Build.VERSION.SDK_INT <= 19 && MediaController.allPhotosAlbumEntry == null) { + MediaController.loadGalleryPhotosAlbums(0); + } + } + + @SuppressLint("NewApi") + public void onRevealAnimationStart(boolean open) { + if (!open) { + return; + } + int count = Build.VERSION.SDK_INT <= 19 ? 11 : 8; + for (int a = 0; a < count; a++) { + if (Build.VERSION.SDK_INT <= 19) { + if (a < 8) { + views[a].setScaleX(0.1f); + views[a].setScaleY(0.1f); + } + views[a].setAlpha(0.0f); + } else { + views[a].setScaleX(0.7f); + views[a].setScaleY(0.7f); + } + views[a].setTag(R.string.AppName, null); + distCache[a] = 0; + } + } + + @SuppressLint("NewApi") + public void onRevealAnimationProgress(boolean open, float radius, int x, int y) { + if (!open) { + return; + } + int count = Build.VERSION.SDK_INT <= 19 ? 11 : 8; + for (int a = 0; a < count; a++) { + if (views[a].getTag(R.string.AppName) == null) { + if (distCache[a] == 0) { + int buttonX = views[a].getLeft() + views[a].getMeasuredWidth() / 2; + int buttonY = views[a].getTop() + views[a].getMeasuredHeight() / 2; + distCache[a] = (float) Math.sqrt((x - buttonX) * (x - buttonX) + (y - buttonY) * (y - buttonY)); + float vecX = (x - buttonX) / distCache[a]; + float vecY = (y - buttonY) / distCache[a]; + views[a].setPivotX(views[a].getMeasuredWidth() / 2 + vecX * AndroidUtilities.dp(20)); + views[a].setPivotY(views[a].getMeasuredHeight() / 2 + vecY * AndroidUtilities.dp(20)); + } + if (distCache[a] > radius + AndroidUtilities.dp(27)) { + continue; + } + + views[a].setTag(R.string.AppName, 1); + final ArrayList animators = new ArrayList<>(); + final ArrayList animators2 = new ArrayList<>(); + if (a < 8) { + animators.add(ObjectAnimator.ofFloat(views[a], "scaleX", 0.7f, 1.05f)); + animators.add(ObjectAnimator.ofFloat(views[a], "scaleY", 0.7f, 1.05f)); + animators2.add(ObjectAnimator.ofFloat(views[a], "scaleX", 1.0f)); + animators2.add(ObjectAnimator.ofFloat(views[a], "scaleY", 1.0f)); + } + if (Build.VERSION.SDK_INT <= 19) { + animators.add(ObjectAnimator.ofFloat(views[a], "alpha", 1.0f)); + } + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(animators); + animatorSet.setDuration(150); + animatorSet.setInterpolator(decelerateInterpolator); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(animators2); + animatorSet.setDuration(100); + animatorSet.setInterpolator(decelerateInterpolator); + animatorSet.start(); + } + }); + animatorSet.start(); + } } } @@ -221,7 +336,7 @@ public class ChatAttachView extends FrameLayout { } public void onDestroy() { - photoAttachAdapter.onDestroy(); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.albumsDidLoaded); baseFragment = null; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java new file mode 100644 index 000000000..3e39df2e0 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java @@ -0,0 +1,130 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.content.Context; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import org.telegram.android.AndroidUtilities; +import org.telegram.android.MediaController; +import org.telegram.android.MessageObject; +import org.telegram.android.NotificationCenter; +import org.telegram.messenger.R; + +public class DrawerPlayerView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + + private ImageView playButton; + private TextView titleTextView; + private ListView parentListView; + private MessageObject lastMessageObject; + + public DrawerPlayerView(Context context, ListView listView) { + super(context); + parentListView = listView; + + View shadow = new View(context); + shadow.setBackgroundResource(R.drawable.header_shadow_reverse); + addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3)); + + FrameLayout frameLayout = new FrameLayout(context); + frameLayout.setBackgroundColor(0xffffffff); + addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 3, 0, 0)); + + playButton = new ImageView(context); + playButton.setScaleType(ImageView.ScaleType.CENTER); + addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.TOP | Gravity.LEFT, 2, 3, 0, 0)); + playButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (MediaController.getInstance().isAudioPaused()) { + MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject()); + } else { + MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject()); + } + } + }); + + titleTextView = new TextView(context); + titleTextView.setTextColor(0xff15a5ed); + titleTextView.setMaxLines(1); + titleTextView.setLines(1); + titleTextView.setSingleLine(true); + titleTextView.setEllipsize(TextUtils.TruncateAt.END); + titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextView.setGravity(Gravity.CENTER_VERTICAL); + addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP, 72, 3, 8, 0)); + + checkPlayer(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged); + NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidStarted); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged); + NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidStarted); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, AndroidUtilities.dp(51)); + } + + @Override + public void didReceivedNotification(int id, Object... args) { + if (id == NotificationCenter.audioDidStarted || id == NotificationCenter.audioPlayStateChanged || id == NotificationCenter.audioDidReset) { + checkPlayer(); + } + } + + private void checkPlayer() { + MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); + if (messageObject == null || !messageObject.isMusic()) { + lastMessageObject = null; + if (getVisibility() != GONE) { + setVisibility(GONE); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) parentListView.getLayoutParams(); + layoutParams.bottomMargin = 0; + parentListView.setLayoutParams(layoutParams); + } + } else { + if (getVisibility() != VISIBLE) { + setVisibility(VISIBLE); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) parentListView.getLayoutParams(); + layoutParams.bottomMargin = AndroidUtilities.dp(48); + parentListView.setLayoutParams(layoutParams); + } + if (MediaController.getInstance().isAudioPaused()) { + playButton.setImageResource(R.drawable.menu_play); + } else { + playButton.setImageResource(R.drawable.menu_pause); + } + if (lastMessageObject != messageObject) { + lastMessageObject = messageObject; + titleTextView.setText(String.format("%s - %s", messageObject.getMusicAuthor(), messageObject.getMusicTitle())); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 076a91869..683ad8e31 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -196,6 +196,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific scrollSlidingTabStrip.setUnderlineHeight(AndroidUtilities.dp(1)); scrollSlidingTabStrip.setIndicatorColor(0xffe2e5e7); scrollSlidingTabStrip.setUnderlineColor(0xffe2e5e7); + scrollSlidingTabStrip.setVisibility(INVISIBLE); addView(scrollSlidingTabStrip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); ViewProxy.setTranslationX(scrollSlidingTabStrip, AndroidUtilities.displaySize.x); updateStickerTabs(); @@ -360,6 +361,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (ViewProxy.getTranslationX(pagerSlidingTabStripContainer) != margin) { ViewProxy.setTranslationX(pagerSlidingTabStripContainer, margin); ViewProxy.setTranslationX(scrollSlidingTabStrip, width + margin); + scrollSlidingTabStrip.setVisibility(margin < 0 ? VISIBLE : INVISIBLE); if (Build.VERSION.SDK_INT < 11) { if (margin <= -width) { pagerSlidingTabStripContainer.clearAnimation(); @@ -449,7 +451,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific stringBuilder.append("="); stringBuilder.append(entry.getValue()); } - getContext().getSharedPreferences("emoji", 0).edit().putString("stickers", stringBuilder.toString()).commit(); + preferences.edit().putString("stickers", stringBuilder.toString()).commit(); } private void sortStickers() { @@ -565,10 +567,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific layoutParams.width = View.MeasureSpec.getSize(widthMeasureSpec); if (scrollSlidingTabStrip != null) { layoutParams1 = (FrameLayout.LayoutParams) scrollSlidingTabStrip.getLayoutParams(); - layoutParams1.width = layoutParams.width; + if (layoutParams1 != null) { + layoutParams1.width = layoutParams.width; + } } if (layoutParams.width != oldWidth) { - if (scrollSlidingTabStrip != null) { + if (scrollSlidingTabStrip != null && layoutParams1 != null) { onPageScrolled(pager.getCurrentItem(), layoutParams.width, 0); scrollSlidingTabStrip.setLayoutParams(layoutParams1); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java index 0e38769e6..3bd67919d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java @@ -17,6 +17,7 @@ import android.widget.FrameLayout; import android.widget.ProgressBar; import android.widget.TextView; +import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.messenger.R; @@ -39,6 +40,7 @@ public class EmptyTextProgressView extends FrameLayout { textView.setTextColor(0xff808080); textView.setGravity(Gravity.CENTER); textView.setVisibility(INVISIBLE); + textView.setPadding(AndroidUtilities.dp(20), 0, AndroidUtilities.dp(20), 0); textView.setText(LocaleController.getString("NoResult", R.string.NoResult)); addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); @@ -81,7 +83,6 @@ public class EmptyTextProgressView extends FrameLayout { continue; } - LayoutParams lp = (LayoutParams) child.getLayoutParams(); int x = (width - child.getMeasuredWidth()) / 2; int y; if (showAtCenter) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java index aedc5bcd6..9ac490ad4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java @@ -113,7 +113,7 @@ public class LetterSectionsListView extends ListView implements AbsListView.OnSc header.setTag(-header.getHeight()); } else if (pos == count - 2) { View child = getChildAt(itemNum - firstVisibleItem); - int headerTop = 0; + int headerTop; if (child != null) { headerTop = child.getTop(); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java index 60c2522eb..74f4168a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java @@ -25,6 +25,9 @@ public class LineProgressView extends View { private float animatedProgressValue = 0; private float animatedAlphaValue = 1.0f; + private int backColor; + private int progressColor = 0xff36a2ee; + private static DecelerateInterpolator decelerateInterpolator = null; private static Paint progressPaint = null; @@ -37,7 +40,6 @@ public class LineProgressView extends View { progressPaint.setStyle(Paint.Style.STROKE); progressPaint.setStrokeCap(Paint.Cap.ROUND); progressPaint.setStrokeWidth(AndroidUtilities.dp(2)); - progressPaint.setColor(0xff36a2ee); } } @@ -70,7 +72,11 @@ public class LineProgressView extends View { } public void setProgressColor(int color) { - progressPaint.setColor(color); + progressColor = color; + } + + public void setBackColor(int color) { + backColor = color; } public void setProgress(float value, boolean animated) { @@ -91,6 +97,14 @@ public class LineProgressView extends View { } public void onDraw(Canvas canvas) { + if (backColor != 0 && animatedProgressValue != 1) { + progressPaint.setColor(backColor); + progressPaint.setAlpha((int) (255 * animatedAlphaValue)); + int start = (int) (getWidth() * animatedProgressValue); + canvas.drawRect(start, 0, getWidth(), getHeight(), progressPaint); + } + + progressPaint.setColor(progressColor); progressPaint.setAlpha((int)(255 * animatedAlphaValue)); canvas.drawRect(0, 0, getWidth() * animatedProgressValue, getHeight(), progressPaint); updateAnimation(); 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 e87f71c0c..10b9309ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java @@ -533,7 +533,6 @@ public class NumberPicker extends LinearLayout { } maxTextWidth = (int) (numberOfDigits * maxDigitWidth); } else { - final int valueCount = mDisplayedValues.length; for (String mDisplayedValue : mDisplayedValues) { final float textWidth = mSelectorWheelPaint.measureText(mDisplayedValue); if (textWidth > maxTextWidth) { 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 6321efc63..b4d408792 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java @@ -15,7 +15,6 @@ import android.graphics.Paint.Style; import android.os.Build; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; -import android.util.DisplayMetrics; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.FrameLayout; @@ -70,8 +69,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView { tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); addView(tabsContainer); - DisplayMetrics dm = getResources().getDisplayMetrics(); - rectPaint = new Paint(); rectPaint.setAntiAlias(true); rectPaint.setStyle(Style.FILL); 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 22f7a4326..1834f9cf4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java @@ -671,7 +671,6 @@ public class PasscodeView extends FrameLayout { @Override public void onClick(View v) { int tag = (Integer) v.getTag(); - int key = KeyEvent.KEYCODE_DEL; switch (tag) { case 0: passwordEditText2.appendCharacter("0"); @@ -845,7 +844,6 @@ public class PasscodeView extends FrameLayout { } SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); int selectedBackground = preferences.getInt("selectedBackground", 1000001); - boolean customTheme = false; if (selectedBackground == 1000001) { backgroundFrameLayout.setBackgroundColor(0xff517c9e); } else { 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 ced235b6a..d2de9216e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java @@ -11,9 +11,7 @@ package org.telegram.ui.Components; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Matrix; -import android.graphics.Paint; import android.graphics.SurfaceTexture; import android.opengl.GLES20; import android.opengl.GLUtils; @@ -1205,28 +1203,29 @@ public class PhotoFilterView extends FrameLayout { } private Bitmap createBitmap(Bitmap bitmap, int w, int h, float scale) { - Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(result); - Paint paint = new Paint(); - paint.setFilterBitmap(true); + //Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + //Canvas canvas = new Canvas(result); + //Paint paint = new Paint(); + //paint.setFilterBitmap(true); Matrix matrix = new Matrix(); matrix.setScale(scale, scale); - matrix.postTranslate(-bitmap.getWidth() / 2, -bitmap.getHeight() / 2); + //matrix.postTranslate(-bitmap.getWidth() / 2, -bitmap.getHeight() / 2); matrix.postRotate(orientation); - if (orientation == 90 || orientation == 270) { + /*if (orientation == 90 || orientation == 270) { matrix.postTranslate(bitmap.getHeight() / 2, bitmap.getWidth() / 2); } else { matrix.postTranslate(bitmap.getWidth() / 2, bitmap.getHeight() / 2); - } - canvas.drawBitmap(bitmap, matrix, paint); - try { - canvas.setBitmap(null); - } catch (Exception e) { + }*/ + //canvas.drawBitmap(bitmap, matrix, paint); + //try { + // canvas.setBitmap(null); + //} catch (Exception e) { //don't promt, this will crash on 2.x - } + //} + return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); - return result; + //return result; } private void loadTexture(Bitmap bitmap) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java index fcff6ef23..4f0051ce5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java @@ -62,6 +62,8 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not private boolean keyboardVisible; private int emojiPadding; + private boolean innerTextChange; + private PhotoViewerCaptionEnterViewDelegate delegate; public PhotoViewerCaptionEnterView(Context context, SizeNotifierFrameLayoutPhoto parent) { @@ -149,6 +151,8 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not } }); messageEditText.addTextChangedListener(new TextWatcher() { + boolean processChange = false; + @Override public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { @@ -156,23 +160,31 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not @Override public void onTextChanged(CharSequence charSequence, int start, int before, int count) { + if (innerTextChange) { + return; + } + if (delegate != null) { delegate.onTextChanged(charSequence); } + + if (before != count && (count - before) > 1) { + processChange = true; + } } @Override public void afterTextChanged(Editable editable) { - int i = 0; - ImageSpan[] arrayOfImageSpan = editable.getSpans(0, editable.length(), ImageSpan.class); - int j = arrayOfImageSpan.length; - while (true) { - if (i >= j) { - Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); - return; + if (innerTextChange) { + return; + } + if (processChange) { + ImageSpan[] spans = editable.getSpans(0, editable.length(), ImageSpan.class); + for (int i = 0; i < spans.length; i++) { + editable.removeSpan(spans[i]); } - editable.removeSpan(arrayOfImageSpan[i]); - i++; + Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); + processChange = false; } } }); @@ -299,12 +311,15 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not i = 0; } try { - CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20)); + innerTextChange = true; + CharSequence localCharSequence = Emoji.replaceEmoji(symbol/* + "\uFE0F"*/, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); messageEditText.setText(messageEditText.getText().insert(i, localCharSequence)); int j = i + localCharSequence.length(); messageEditText.setSelection(j, j); } catch (Exception e) { FileLog.e("tmessages", e); + } finally { + innerTextChange = false; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPickerBottomLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java similarity index 81% rename from TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPickerBottomLayout.java rename to TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java index 67c72c127..657566273 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPickerBottomLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java @@ -20,22 +20,30 @@ import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; import org.telegram.messenger.R; -public class PhotoPickerBottomLayout extends FrameLayout { +public class PickerBottomLayout extends FrameLayout { public LinearLayout doneButton; public TextView cancelButton; public TextView doneButtonTextView; public TextView doneButtonBadgeTextView; - public PhotoPickerBottomLayout(Context context) { + private boolean isDarkTheme; + + public PickerBottomLayout(Context context) { + this(context, true); + } + + public PickerBottomLayout(Context context, boolean darkTheme) { super(context); - setBackgroundColor(0xff1a1a1a); + isDarkTheme = darkTheme; + + setBackgroundColor(isDarkTheme ? 0xff1a1a1a : 0xffffffff); cancelButton = new TextView(context); cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - cancelButton.setTextColor(0xffffffff); + cancelButton.setTextColor(isDarkTheme ? 0xffffffff : 0xff19a7e8); cancelButton.setGravity(Gravity.CENTER); - cancelButton.setBackgroundResource(R.drawable.bar_selector_picker); + cancelButton.setBackgroundResource(isDarkTheme ? R.drawable.bar_selector_picker : R.drawable.bar_selector_audio); cancelButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0); cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); cancelButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); @@ -48,7 +56,7 @@ public class PhotoPickerBottomLayout extends FrameLayout { doneButton = new LinearLayout(context); doneButton.setOrientation(LinearLayout.HORIZONTAL); - doneButton.setBackgroundResource(R.drawable.bar_selector_picker); + doneButton.setBackgroundResource(isDarkTheme ? R.drawable.bar_selector_picker : R.drawable.bar_selector_audio); doneButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0); addView(doneButton); layoutParams = (LayoutParams) doneButton.getLayoutParams(); @@ -62,7 +70,7 @@ public class PhotoPickerBottomLayout extends FrameLayout { doneButtonBadgeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); doneButtonBadgeTextView.setTextColor(0xffffffff); doneButtonBadgeTextView.setGravity(Gravity.CENTER); - doneButtonBadgeTextView.setBackgroundResource(R.drawable.photobadge); + doneButtonBadgeTextView.setBackgroundResource(isDarkTheme ? R.drawable.photobadge : R.drawable.bluecounter); doneButtonBadgeTextView.setMinWidth(AndroidUtilities.dp(23)); doneButtonBadgeTextView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), AndroidUtilities.dp(1)); doneButton.addView(doneButtonBadgeTextView); @@ -75,7 +83,7 @@ public class PhotoPickerBottomLayout extends FrameLayout { doneButtonTextView = new TextView(context); doneButtonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - doneButtonTextView.setTextColor(0xffffffff); + doneButtonTextView.setTextColor(isDarkTheme ? 0xffffffff : 0xff19a7e8); doneButtonTextView.setGravity(Gravity.CENTER); doneButtonTextView.setCompoundDrawablePadding(AndroidUtilities.dp(8)); doneButtonTextView.setText(LocaleController.getString("Send", R.string.Send).toUpperCase()); @@ -96,18 +104,16 @@ public class PhotoPickerBottomLayout extends FrameLayout { doneButtonTextView.setTextColor(0xff999999); doneButton.setEnabled(false); } else { - doneButtonTextView.setTextColor(0xffffffff); + doneButtonTextView.setTextColor(isDarkTheme ? 0xffffffff : 0xff19a7e8); } } else { doneButtonTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); doneButtonBadgeTextView.setVisibility(View.VISIBLE); doneButtonBadgeTextView.setText(String.format("%d", count)); + doneButtonTextView.setTextColor(isDarkTheme ? 0xffffffff : 0xff19a7e8); if (disable) { - doneButtonTextView.setTextColor(0xffffffff); doneButton.setEnabled(true); - } else { - doneButtonTextView.setTextColor(0xffffffff); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java index c6f7bb038..d145ca2f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java @@ -90,11 +90,6 @@ public class PopupAudioView extends BaseCell implements SeekBar.SeekBarDelegate, public void setMessageObject(MessageObject messageObject) { if (currentMessageObject != messageObject) { - int uid = messageObject.messageOwner.media.audio.user_id; - if (uid == 0) { - uid = messageObject.messageOwner.from_id; - } - seekBar.type = 1; progressView.setProgressColors(0xffd9e2eb, 0xff86c5f8); @@ -269,7 +264,7 @@ public class PopupAudioView extends BaseCell implements SeekBar.SeekBarDelegate, seekBar.setProgress(currentMessageObject.audioProgress); } - int duration = 0; + int duration; if (!MediaController.getInstance().isPlayingAudio(currentMessageObject)) { duration = currentMessageObject.messageOwner.media.audio.duration; } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java index af86334cd..8826b64a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java @@ -35,6 +35,7 @@ public class RadialProgress { private Drawable currentDrawable; private Drawable previousDrawable; private boolean hideCurrentDrawable; + private int progressColor = 0xffffffff; private static DecelerateInterpolator decelerateInterpolator = null; private static Paint progressPaint = null; @@ -46,7 +47,6 @@ public class RadialProgress { progressPaint.setStyle(Paint.Style.STROKE); progressPaint.setStrokeCap(Paint.Cap.ROUND); progressPaint.setStrokeWidth(AndroidUtilities.dp(2)); - progressPaint.setColor(0xffffffff); } parent = parentView; } @@ -86,7 +86,7 @@ public class RadialProgress { } public void setProgressColor(int color) { - progressPaint.setColor(color); + progressColor = color; } public void setHideCurrentDrawable(boolean value) { @@ -154,6 +154,7 @@ public class RadialProgress { if (currentWithRound || previousWithRound) { int diff = AndroidUtilities.dp(1); + progressPaint.setColor(progressColor); if (previousWithRound) { progressPaint.setAlpha((int)(255 * animatedAlphaValue)); } else { 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 b356c7196..f503341e1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -161,6 +161,11 @@ public class RecyclerListView extends RecyclerView { public void onTouchEvent(RecyclerView view, MotionEvent e) { } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + + } } private AdapterDataObserver observer = new AdapterDataObserver() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java index a5b56b4d3..9b4ce1c41 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java @@ -12,7 +12,6 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.Style; -import android.util.DisplayMetrics; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; @@ -61,8 +60,6 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); addView(tabsContainer); - DisplayMetrics dm = getResources().getDisplayMetrics(); - rectPaint = new Paint(); rectPaint.setAntiAlias(true); rectPaint.setStyle(Style.FILL); 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 bc15136a0..727b3bacb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java @@ -11,11 +11,9 @@ package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; -import android.graphics.drawable.Drawable; import android.view.MotionEvent; import org.telegram.android.AndroidUtilities; -import org.telegram.messenger.R; public class SeekBar { @@ -23,14 +21,10 @@ public class SeekBar { void onSeekBarDrag(float progress); } - private static Drawable thumbDrawable1; - private static Drawable thumbDrawablePressed1; - private static Drawable thumbDrawable2; - private static Drawable thumbDrawablePressed2; - private static Paint innerPaint1 = new Paint(); - private static Paint outerPaint1 = new Paint(); - private static Paint innerPaint2 = new Paint(); - private static Paint outerPaint2 = new Paint(); + private static Paint innerPaint1; + private static Paint outerPaint1; + private static Paint innerPaint2; + private static Paint outerPaint2; private static int thumbWidth; private static int thumbHeight; public int type; @@ -42,17 +36,21 @@ public class SeekBar { public SeekBarDelegate delegate; public SeekBar(Context context) { - if (thumbDrawable1 == null) { - thumbDrawable1 = context.getResources().getDrawable(R.drawable.player1); - thumbDrawablePressed1 = context.getResources().getDrawable(R.drawable.player1_pressed); - thumbDrawable2 = context.getResources().getDrawable(R.drawable.player2); - thumbDrawablePressed2 = context.getResources().getDrawable(R.drawable.player2_pressed); - innerPaint1.setColor(0xffb4e396); - outerPaint1.setColor(0xff6ac453); - innerPaint2.setColor(0xffd9e2eb); - outerPaint2.setColor(0xff86c5f8); - thumbWidth = thumbDrawable1.getIntrinsicWidth(); - thumbHeight = thumbDrawable1.getIntrinsicHeight(); + if (innerPaint1 == null) { + innerPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + innerPaint1.setColor(0xffc3e3ab); + + outerPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + outerPaint1.setColor(0xff87bf78); + + innerPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + innerPaint2.setColor(0xffe4eaf0); + + outerPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + outerPaint2.setColor(0xff4195e5); + + thumbWidth = AndroidUtilities.dp(24); + thumbHeight = AndroidUtilities.dp(24); } } @@ -100,30 +98,18 @@ public class SeekBar { } public void draw(Canvas canvas) { - Drawable thumb = null; Paint inner = null; Paint outer = null; if (type == 0) { - if (!pressed) { - thumb = thumbDrawable1; - } else { - thumb = thumbDrawablePressed1; - } inner = innerPaint1; outer = outerPaint1; } else if (type == 1) { - if (!pressed) { - thumb = thumbDrawable2; - } else { - thumb = thumbDrawablePressed2; - } inner = innerPaint2; outer = outerPaint2; } int y = (height - thumbHeight) / 2; canvas.drawRect(thumbWidth / 2, height / 2 - AndroidUtilities.dp(1), width - thumbWidth / 2, height / 2 + AndroidUtilities.dp(1), inner); canvas.drawRect(thumbWidth / 2, height / 2 - AndroidUtilities.dp(1), thumbWidth / 2 + thumbX, height / 2 + AndroidUtilities.dp(1), outer); - thumb.setBounds(thumbX, y, thumbX + thumbWidth, y + thumbHeight); - thumb.draw(canvas); + canvas.drawCircle(thumbX + thumbWidth / 2, y + thumbHeight / 2, AndroidUtilities.dp(pressed ? 8 : 6), outer); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java new file mode 100644 index 000000000..c64b07616 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java @@ -0,0 +1,88 @@ +/* + * This is the source code of Telegram for Android v. 2.x.x. + * It is licensed under GNU GPL v. 2 or later. + * You should have received a copy of the license in this archive (see LICENSE). + * + * Copyright Nikolai Kudashov, 2013-2015. + */ + +package org.telegram.ui.Components; + +import android.text.SpannableString; + +import org.telegram.messenger.FileLog; + +import java.lang.reflect.Field; + +public class SpannableStringLight extends SpannableString { + + private static Field mSpansField; + private static Field mSpanDataField; + private static Field mSpanCountField; + private static boolean fieldsAvailable; + + private Object[] mSpansOverride; + private int[] mSpanDataOverride; + private int mSpanCountOverride; + private int num; + + public SpannableStringLight(CharSequence source) { + super(source); + + try { + mSpansOverride = (Object[]) mSpansField.get(this); + mSpanDataOverride = (int[]) mSpanDataField.get(this); + mSpanCountOverride = (int) mSpanCountField.get(this); + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + } + + public void setSpansCount(int count) { + count += mSpanCountOverride; + mSpansOverride = new Object[count]; + mSpanDataOverride = new int[count * 3]; + num = mSpanCountOverride; + mSpanCountOverride = count; + + try { + mSpansField.set(this, mSpansOverride); + mSpanDataField.set(this, mSpanDataOverride); + mSpanCountField.set(this, mSpanCountOverride); + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + } + + public static boolean isFieldsAvailable() { + if (!fieldsAvailable && mSpansField == null) { + try { + mSpansField = SpannableString.class.getSuperclass().getDeclaredField("mSpans"); + mSpansField.setAccessible(true); + + mSpanDataField = SpannableString.class.getSuperclass().getDeclaredField("mSpanData"); + mSpanDataField.setAccessible(true); + + mSpanCountField = SpannableString.class.getSuperclass().getDeclaredField("mSpanCount"); + mSpanCountField.setAccessible(true); + } catch (Throwable e) { + FileLog.e("tmessages", e); + } + fieldsAvailable = true; + } + return mSpansField != null; + } + + public void setSpanLight(Object what, int start, int end, int flags) { + mSpansOverride[num] = what; + mSpanDataOverride[num * 3] = start; + mSpanDataOverride[num * 3 + 1] = end; + mSpanDataOverride[num * 3 + 2] = flags; + num++; + } + + @Override + public void removeSpan(Object what) { + super.removeSpan(what); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java index fa6740a9d..b57b21894 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java @@ -555,8 +555,6 @@ public class Switch extends CompoundButton { final int switchTop = mSwitchTop; final int switchBottom = mSwitchBottom; - final int switchInnerTop = switchTop + padding.top; - final int switchInnerBottom = switchBottom - padding.bottom; final Drawable thumbDrawable = mThumbDrawable; if (trackDrawable != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java index 7bfd47999..1aae15996 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java @@ -45,7 +45,7 @@ public class TimerDrawable extends Drawable { public void setTime(int value) { time = value; - String timeString = null; + String timeString; if (time >= 1 && time < 60) { timeString = "" + value; if (timeString.length() < 2) { @@ -91,7 +91,7 @@ public class TimerDrawable extends Drawable { public void draw(Canvas canvas) { int width = timerDrawable.getIntrinsicWidth(); int height = timerDrawable.getIntrinsicHeight(); - Drawable drawable = null; + Drawable drawable; if (time == 0) { drawable = timerDrawable; } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java index d644d7d6d..f26e450f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java @@ -88,7 +88,7 @@ public class TypingDotsDrawable extends Drawable { @Override public void draw(Canvas canvas) { - int y = 0; + int y; if (isChat) { y = AndroidUtilities.dp(6); } else { 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 d562cc6bb..980237dfc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java @@ -202,7 +202,6 @@ public class VideoTimelineView extends View { int h = (int) (bitmap.getHeight() * scale); Rect srcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); Rect destRect = new Rect((frameWidth - w) / 2, (frameHeight - h) / 2, w, h); - Paint paint = new Paint(); canvas.drawBitmap(bitmap, srcRect, destRect, null); bitmap.recycle(); bitmap = result; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java index d794f29db..e42fe5ae4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java @@ -59,6 +59,10 @@ public class WebFrameLayout extends FrameLayout { openUrl = originalUrl; width = w; height = h; + if (width == 0 || height == 0) { + width = AndroidUtilities.displaySize.x; + height = AndroidUtilities.displaySize.y / 2; + } dialog = parentDialog; fullscreenVideoContainer = new FrameLayout(context); @@ -211,10 +215,6 @@ public class WebFrameLayout extends FrameLayout { }); parentDialog.setDelegate(new BottomSheet.BottomSheetDelegate() { - @Override - public void onOpenAnimationStart() { - - } @Override public void onOpenAnimationEnd() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index c09173f9d..f57e4f9bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -17,7 +17,6 @@ import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.inputmethod.EditorInfo; @@ -79,7 +78,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); if (addContact) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index 6a6695aeb..88ce8849b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -20,7 +20,6 @@ import android.text.InputType; import android.text.TextWatcher; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -125,7 +124,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { searching = false; searchWas = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java index 3058d6912..16e710294 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java @@ -11,7 +11,6 @@ package org.telegram.ui; import android.content.Context; import android.os.Build; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.AbsListView; @@ -62,7 +61,7 @@ public class CountrySelectActivity extends BaseFragment { } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); @@ -185,7 +184,7 @@ public class CountrySelectActivity extends BaseFragment { listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { - Country country = null; + Country country; if (searching && searchWas) { country = searchListViewAdapter.getItem(i); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java similarity index 98% rename from TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java rename to TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 53ec757da..3362c6714 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -20,7 +20,6 @@ import android.os.Build; import android.os.Bundle; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewOutlineProvider; @@ -67,7 +66,7 @@ import org.telegram.ui.Components.ResourceLoader; import java.util.ArrayList; -public class MessagesActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { +public class DialogsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; private LinearLayoutManager layoutManager; @@ -101,10 +100,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter private MessagesActivityDelegate delegate; public interface MessagesActivityDelegate { - void didSelectDialog(MessagesActivity fragment, long dialog_id, boolean param); + void didSelectDialog(DialogsActivity fragment, long dialog_id, boolean param); } - public MessagesActivity(Bundle args) { + public DialogsActivity(Bundle args) { super(args); } @@ -165,7 +164,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(final Context context, LayoutInflater inflater) { + public View createView(final Context context) { searching = false; searchWas = false; @@ -887,7 +886,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter showDialog(builder.create()); } else { if (delegate != null) { - delegate.didSelectDialog(MessagesActivity.this, dialog_id, param); + delegate.didSelectDialog(DialogsActivity.this, dialog_id, param); delegate = null; } else { finishFragment(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java index 260092182..cee01daf9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java @@ -19,7 +19,6 @@ import android.os.Environment; import android.os.StatFs; import android.text.TextUtils; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -126,7 +125,7 @@ public class DocumentSelectActivity extends BaseFragment { } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { if (!receiverRegistered) { receiverRegistered = true; IntentFilter filter = new IntentFilter(); @@ -194,7 +193,7 @@ public class DocumentSelectActivity extends BaseFragment { actionModeViews.add(actionMode.addItem(done, R.drawable.ic_ab_done_gray, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); - fragmentView = inflater.inflate(R.layout.document_select_layout, null, false); + fragmentView = getParentActivity().getLayoutInflater().inflate(R.layout.document_select_layout, null, false); listAdapter = new ListAdapter(context); emptyView = (TextView) fragmentView.findViewById(R.id.searchEmptyView); emptyView.setOnTouchListener(new View.OnTouchListener() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 2639f756a..a5142a02a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -142,7 +142,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { searching = false; searchWas = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java index 93aaffa07..5684bc3fb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java @@ -19,7 +19,6 @@ import android.text.InputType; import android.text.TextWatcher; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; @@ -139,7 +138,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); if (isBroadcast) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java index 1ea12de42..3677a8ee9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java @@ -14,7 +14,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.os.Build; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -88,7 +87,7 @@ public class GroupInviteActivity extends BaseFragment implements NotificationCen } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("InviteLink", R.string.InviteLink)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java index fea96db4c..b75c2d366 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java @@ -10,7 +10,6 @@ package org.telegram.ui; import android.content.Context; import android.os.Bundle; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -44,7 +43,7 @@ public class IdenticonActivity extends BaseFragment { } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("EncryptionKey", R.string.EncryptionKey)); @@ -58,7 +57,7 @@ public class IdenticonActivity extends BaseFragment { } }); - fragmentView = inflater.inflate(R.layout.identicon_layout, null, false); + fragmentView = getParentActivity().getLayoutInflater().inflate(R.layout.identicon_layout, null, false); ImageView identiconView = (ImageView) fragmentView.findViewById(R.id.identicon_view); TextView textView = (TextView) fragmentView.findViewById(R.id.identicon_text); TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat(chat_id); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index 96fc7648f..be68ecf57 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -12,7 +12,6 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -53,7 +52,7 @@ public class LanguageSelectActivity extends BaseFragment { public ArrayList searchResult; @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { searching = false; searchWas = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java index 1b1f81c04..2ac98eb9f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java @@ -18,7 +18,6 @@ import android.os.Bundle; import android.text.Spannable; import android.text.method.LinkMovementMethod; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -100,7 +99,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("PrivacyLastSeen", R.string.PrivacyLastSeen)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java index b476860fc..7b5950b6f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java @@ -14,7 +14,6 @@ import android.content.DialogInterface; import android.os.Build; import android.os.Bundle; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -76,7 +75,7 @@ public class LastSeenUsersActivity extends BaseFragment implements NotificationC } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); if (isAlwaysShare) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index e77c865dc..7e9980499 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -24,6 +24,7 @@ import android.os.Bundle; import android.os.Parcelable; import android.provider.ContactsContract; import android.view.ActionMode; +import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -61,6 +62,7 @@ import org.telegram.ui.Adapters.DrawerLayoutAdapter; import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.DrawerLayoutContainer; +import org.telegram.ui.Components.DrawerPlayerView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PasscodeView; @@ -70,7 +72,7 @@ import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Map; -public class LaunchActivity extends Activity implements ActionBarLayout.ActionBarLayoutDelegate, NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate { +public class LaunchActivity extends Activity implements ActionBarLayout.ActionBarLayoutDelegate, NotificationCenter.NotificationCenterDelegate, DialogsActivity.MessagesActivityDelegate { private boolean finished; private String videoPath; @@ -253,20 +255,22 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa drawerLayoutContainer.addView(actionBarLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } - ListView listView = new ListView(this); - listView.setAdapter(drawerLayoutAdapter = new DrawerLayoutAdapter(this)); - drawerLayoutContainer.setDrawerLayout(listView); - listView.setBackgroundColor(0xffffffff); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)listView.getLayoutParams(); + FrameLayout listViewContainer = new FrameLayout(this); + listViewContainer.setBackgroundColor(0xffffffff); + drawerLayoutContainer.setDrawerLayout(listViewContainer); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listViewContainer.getLayoutParams(); Point screenSize = AndroidUtilities.getRealScreenSize(); layoutParams.width = AndroidUtilities.isTablet() ? AndroidUtilities.dp(320) : Math.min(screenSize.x, screenSize.y) - AndroidUtilities.dp(56); layoutParams.height = LayoutHelper.MATCH_PARENT; - listView.setPadding(0, 0, 0, 0); + listViewContainer.setLayoutParams(layoutParams); + + ListView listView = new ListView(this); + listView.setAdapter(drawerLayoutAdapter = new DrawerLayoutAdapter(this)); listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE); listView.setDivider(null); listView.setDividerHeight(0); - listView.setLayoutParams(layoutParams); listView.setVerticalScrollBarEnabled(false); + listViewContainer.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override @@ -320,6 +324,16 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } }); + DrawerPlayerView drawerPlayerView = new DrawerPlayerView(this, listView); + listViewContainer.addView(drawerPlayerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.LEFT | Gravity.BOTTOM)); + drawerPlayerView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + actionBarLayout.presentFragment(new AudioPlayerActivity()); + drawerLayoutContainer.closeDrawer(false); + } + }); + drawerLayoutContainer.setParentActionBarLayout(actionBarLayout); actionBarLayout.setDrawerLayoutContainer(drawerLayoutContainer); actionBarLayout.init(mainFragmentsStack); @@ -350,7 +364,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa actionBarLayout.addFragmentToStack(new LoginActivity()); drawerLayoutContainer.setAllowOpenDrawer(false, false); } else { - actionBarLayout.addFragmentToStack(new MessagesActivity(null)); + actionBarLayout.addFragmentToStack(new DialogsActivity(null)); drawerLayoutContainer.setAllowOpenDrawer(true, false); } @@ -469,6 +483,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa Integer push_enc_id = 0; Integer open_settings = 0; boolean showDialogsList = false; + boolean showPlayer = false; photoPathsArray = null; videoPath = null; @@ -589,7 +604,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } Uri uri = (Uri) parcelable; if (uri != null && (type != null && type.startsWith("image/") || uri.toString().toLowerCase().endsWith(".jpg"))) { - String tempPath = AndroidUtilities.getPath(uri); if (photoPathsArray == null) { photoPathsArray = new ArrayList<>(); } @@ -762,6 +776,8 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } else { showDialogsList = true; } + } else if (intent.getAction().equals("com.tmessages.openplayer")) { + showPlayer = true; } } } @@ -801,6 +817,30 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } pushOpened = false; isNew = false; + } else if (showPlayer) { + if (AndroidUtilities.isTablet()) { + for (int a = 0; a < layersActionBarLayout.fragmentsStack.size(); a++) { + BaseFragment fragment = layersActionBarLayout.fragmentsStack.get(a); + if (fragment instanceof AudioPlayerActivity) { + layersActionBarLayout.removeFragmentFromStack(fragment); + break; + } + } + actionBarLayout.showLastFragment(); + rightActionBarLayout.showLastFragment(); + drawerLayoutContainer.setAllowOpenDrawer(false, false); + } else { + for (int a = 0; a < actionBarLayout.fragmentsStack.size(); a++) { + BaseFragment fragment = actionBarLayout.fragmentsStack.get(a); + if (fragment instanceof AudioPlayerActivity) { + actionBarLayout.removeFragmentFromStack(fragment); + break; + } + } + drawerLayoutContainer.setAllowOpenDrawer(true, false); + } + actionBarLayout.presentFragment(new AudioPlayerActivity(), false, true, true); + pushOpened = true; } else if (videoPath != null || photoPathsArray != null || sendingText != null || documentsPathsArray != null || contactsToSend != null || documentsUrisArray != null) { if (!AndroidUtilities.isTablet()) { NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); @@ -809,13 +849,13 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa args.putBoolean("onlySelect", true); args.putString("selectAlertString", LocaleController.getString("SendMessagesTo", R.string.SendMessagesTo)); args.putString("selectAlertStringGroup", LocaleController.getString("SendMessagesToGroup", R.string.SendMessagesToGroup)); - MessagesActivity fragment = new MessagesActivity(args); + DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(this); boolean removeLast; if (AndroidUtilities.isTablet()) { - removeLast = layersActionBarLayout.fragmentsStack.size() > 0 && layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1) instanceof MessagesActivity; + removeLast = layersActionBarLayout.fragmentsStack.size() > 0 && layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1) instanceof DialogsActivity; } else { - removeLast = actionBarLayout.fragmentsStack.size() > 1 && actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1) instanceof MessagesActivity; + removeLast = actionBarLayout.fragmentsStack.size() > 1 && actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1) instanceof DialogsActivity; } actionBarLayout.presentFragment(fragment, removeLast, true, true); pushOpened = true; @@ -851,7 +891,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } } else { if (actionBarLayout.fragmentsStack.isEmpty()) { - actionBarLayout.addFragmentToStack(new MessagesActivity(null)); + actionBarLayout.addFragmentToStack(new DialogsActivity(null)); drawerLayoutContainer.setAllowOpenDrawer(true, false); } } @@ -861,7 +901,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa actionBarLayout.addFragmentToStack(new LoginActivity()); drawerLayoutContainer.setAllowOpenDrawer(false, false); } else { - actionBarLayout.addFragmentToStack(new MessagesActivity(null)); + actionBarLayout.addFragmentToStack(new DialogsActivity(null)); drawerLayoutContainer.setAllowOpenDrawer(true, false); } } @@ -920,10 +960,10 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa args.putBoolean("onlySelect", true); args.putInt("dialogsType", 2); args.putString("addToGroupAlertString", LocaleController.formatString("AddToTheGroupTitle", R.string.AddToTheGroupTitle, UserObject.getUserName(user), "%1$s")); - MessagesActivity fragment = new MessagesActivity(args); - fragment.setDelegate(new MessagesActivity.MessagesActivityDelegate() { + DialogsActivity fragment = new DialogsActivity(args); + fragment.setDelegate(new DialogsActivity.MessagesActivityDelegate() { @Override - public void didSelectDialog(MessagesActivity fragment, long did, boolean param) { + public void didSelectDialog(DialogsActivity fragment, long did, boolean param) { NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); MessagesController.getInstance().addUserToChat(-(int) did, user, null, 0, botChat); Bundle args = new Bundle(); @@ -1113,7 +1153,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa } @Override - public void didSelectDialog(MessagesActivity messageFragment, long dialog_id, boolean param) { + public void didSelectDialog(DialogsActivity messageFragment, long dialog_id, boolean param) { if (dialog_id != 0) { int lower_part = (int)dialog_id; int high_id = (int)(dialog_id >> 32); @@ -1637,9 +1677,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa public boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout) { if (AndroidUtilities.isTablet()) { drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity || fragment instanceof CountrySelectActivity) && layersActionBarLayout.getVisibility() != View.VISIBLE, true); - if (fragment instanceof MessagesActivity) { - MessagesActivity messagesActivity = (MessagesActivity)fragment; - if (messagesActivity.isMainDialogList() && layout != actionBarLayout) { + if (fragment instanceof DialogsActivity) { + DialogsActivity dialogsActivity = (DialogsActivity)fragment; + if (dialogsActivity.isMainDialogList() && layout != actionBarLayout) { actionBarLayout.removeAllFragments(); actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, false); layersActionBarLayout.removeAllFragments(); @@ -1726,9 +1766,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa public boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout) { if (AndroidUtilities.isTablet()) { drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity || fragment instanceof CountrySelectActivity) && layersActionBarLayout.getVisibility() != View.VISIBLE, true); - if (fragment instanceof MessagesActivity) { - MessagesActivity messagesActivity = (MessagesActivity)fragment; - if (messagesActivity.isMainDialogList() && layout != actionBarLayout) { + if (fragment instanceof DialogsActivity) { + DialogsActivity dialogsActivity = (DialogsActivity)fragment; + if (dialogsActivity.isMainDialogList() && layout != actionBarLayout) { actionBarLayout.removeAllFragments(); actionBarLayout.addFragmentToStack(fragment); layersActionBarLayout.removeAllFragments(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index 9907ecccb..36cec820e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -21,7 +21,6 @@ import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -107,7 +106,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private CircleOptions circleOptions; private LocationActivityDelegate delegate; - private int overScrollHeight = AndroidUtilities.displaySize.x - AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(66); + private int overScrollHeight = AndroidUtilities.displaySize.x - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(66); private int halfHeight; private final static int share = 1; @@ -152,7 +151,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); if (AndroidUtilities.isTablet()) { @@ -501,7 +500,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter View shadow = new View(context); shadow.setBackgroundResource(R.drawable.header_shadow_reverse); - mapViewClip.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, AndroidUtilities.dp(3), Gravity.LEFT | Gravity.BOTTOM)); + mapViewClip.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.LEFT | Gravity.BOTTOM)); markerImageView = new ImageView(context); markerImageView.setImageResource(R.drawable.map_pin); @@ -696,7 +695,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter private void fixLayoutInternal(final boolean resume) { if (listView != null) { - int height = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight(); + int height = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight(); int viewHeight = fragmentView.getMeasuredHeight(); if (viewHeight == 0) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index dfe8b5867..1d8bddab0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -34,7 +34,6 @@ import android.text.method.PasswordTransformationMethod; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; import android.view.animation.AccelerateDecelerateInterpolator; @@ -109,7 +108,7 @@ public class LoginActivity extends BaseFragment { } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName)); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @@ -395,7 +394,7 @@ public class LoginActivity extends BaseFragment { public void needFinishActivity() { clearCurrentState(); - presentFragment(new MessagesActivity(null), true); + presentFragment(new DialogsActivity(null), true); NotificationCenter.getInstance().postNotificationName(NotificationCenter.mainUserInfoChanged); } @@ -724,11 +723,9 @@ public class LoginActivity extends BaseFragment { if (!codeText.equals(resultCode)) { phone = PhoneFormat.getInstance().format(phoneField.getText().toString()).trim(); phoneField.setText(phone); - int len = phoneField.length(); phoneField.setSelection(phoneField.length()); } else { phoneField.setText(phone.substring(idx).trim()); - int len = phoneField.length(); phoneField.setSelection(phoneField.length()); } } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java index fb10c8d0e..b52d4b1ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java @@ -21,7 +21,6 @@ import android.os.Bundle; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -40,6 +39,7 @@ import android.widget.TextView; import org.telegram.android.AndroidUtilities; import org.telegram.android.LocaleController; +import org.telegram.android.MediaController; import org.telegram.android.MessagesController; import org.telegram.android.query.SharedMediaQuery; import org.telegram.messenger.ApplicationLoader; @@ -217,7 +217,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setTitle(""); actionBar.setAllowOverlayTitle(false); @@ -284,10 +284,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", 1); - MessagesActivity fragment = new MessagesActivity(args); - fragment.setDelegate(new MessagesActivity.MessagesActivityDelegate() { + DialogsActivity fragment = new DialogsActivity(args); + fragment.setDelegate(new DialogsActivity.MessagesActivityDelegate() { @Override - public void didSelectDialog(MessagesActivity fragment, long did, boolean param) { + public void didSelectDialog(DialogsActivity fragment, long did, boolean param) { int lower_part = (int) did; if (lower_part != 0) { Bundle args = new Bundle(); @@ -374,14 +374,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No dropDownContainer.setSubMenuOpenSide(1); dropDownContainer.addSubItem(shared_media_item, LocaleController.getString("SharedMediaTitle", R.string.SharedMediaTitle), 0); dropDownContainer.addSubItem(files_item, LocaleController.getString("DocumentsTitle", R.string.DocumentsTitle), 0); - actionBar.addView(dropDownContainer); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) dropDownContainer.getLayoutParams(); - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.rightMargin = AndroidUtilities.dp(40); - layoutParams.leftMargin = AndroidUtilities.isTablet() ? AndroidUtilities.dp(64) : AndroidUtilities.dp(56); - layoutParams.gravity = Gravity.TOP | Gravity.LEFT; - dropDownContainer.setLayoutParams(layoutParams); + actionBar.addView(dropDownContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, AndroidUtilities.isTablet() ? 64 : 56, 0, 40, 0)); dropDownContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -400,13 +393,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No dropDown.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_arrow_drop_down, 0); dropDown.setCompoundDrawablePadding(AndroidUtilities.dp(4)); dropDown.setPadding(0, 0, AndroidUtilities.dp(10), 0); - dropDownContainer.addView(dropDown); - layoutParams = (FrameLayout.LayoutParams) dropDown.getLayoutParams(); - layoutParams.width = LayoutHelper.WRAP_CONTENT; - layoutParams.height = LayoutHelper.WRAP_CONTENT; - layoutParams.leftMargin = AndroidUtilities.dp(16); - layoutParams.gravity = Gravity.CENTER_VERTICAL; - dropDown.setLayoutParams(layoutParams); + dropDownContainer.addView(dropDown, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 16, 0, 0, 0)); final ActionBarMenu actionMode = actionBar.createActionMode(); actionModeViews.add(actionMode.addItem(-2, R.drawable.ic_ab_back_grey, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); @@ -426,12 +413,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No return true; } }); - actionMode.addView(selectedMessagesCountTextView); - LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams) selectedMessagesCountTextView.getLayoutParams(); - layoutParams1.weight = 1; - layoutParams1.width = 0; - layoutParams1.height = LayoutHelper.MATCH_PARENT; - selectedMessagesCountTextView.setLayoutParams(layoutParams1); + actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f)); if ((int) dialog_id != 0) { actionModeViews.add(actionMode.addItem(forward, R.drawable.ic_ab_fwd_forward, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54))); @@ -450,12 +432,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No listView.setDividerHeight(0); listView.setDrawSelectorOnTop(true); listView.setClipToPadding(false); - frameLayout.addView(listView); - layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - layoutParams.gravity = Gravity.TOP; - listView.setLayoutParams(layoutParams); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, final int i, long l) { @@ -515,11 +492,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No emptyView.setGravity(Gravity.CENTER); emptyView.setVisibility(View.GONE); emptyView.setBackgroundColor(0xfff0f0f0); - frameLayout.addView(emptyView); - layoutParams = (FrameLayout.LayoutParams) emptyView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - emptyView.setLayoutParams(layoutParams); + frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); emptyView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { @@ -528,42 +501,24 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No }); emptyImageView = new ImageView(context); - emptyView.addView(emptyImageView); - layoutParams1 = (LinearLayout.LayoutParams) emptyImageView.getLayoutParams(); - layoutParams1.width = LayoutHelper.WRAP_CONTENT; - layoutParams1.height = LayoutHelper.WRAP_CONTENT; - emptyImageView.setLayoutParams(layoutParams1); + emptyView.addView(emptyImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); emptyTextView = new TextView(context); emptyTextView.setTextColor(0xff8a8a8a); emptyTextView.setGravity(Gravity.CENTER); emptyTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); emptyTextView.setPadding(AndroidUtilities.dp(40), 0, AndroidUtilities.dp(40), AndroidUtilities.dp(128)); - emptyView.addView(emptyTextView); - layoutParams1 = (LinearLayout.LayoutParams) emptyTextView.getLayoutParams(); - layoutParams1.topMargin = AndroidUtilities.dp(24); - layoutParams1.width = LayoutHelper.WRAP_CONTENT; - layoutParams1.height = LayoutHelper.WRAP_CONTENT; - layoutParams1.gravity = Gravity.CENTER; - emptyTextView.setLayoutParams(layoutParams1); + emptyView.addView(emptyTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 24, 0, 0)); progressView = new LinearLayout(context); progressView.setGravity(Gravity.CENTER); progressView.setOrientation(LinearLayout.VERTICAL); progressView.setVisibility(View.GONE); progressView.setBackgroundColor(0xfff0f0f0); - frameLayout.addView(progressView); - layoutParams = (FrameLayout.LayoutParams) progressView.getLayoutParams(); - layoutParams.width = LayoutHelper.MATCH_PARENT; - layoutParams.height = LayoutHelper.MATCH_PARENT; - progressView.setLayoutParams(layoutParams); + frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); ProgressBar progressBar = new ProgressBar(context); - progressView.addView(progressBar); - layoutParams1 = (LinearLayout.LayoutParams) progressBar.getLayoutParams(); - layoutParams1.width = LayoutHelper.WRAP_CONTENT; - layoutParams1.height = LayoutHelper.WRAP_CONTENT; - progressBar.setLayoutParams(layoutParams1); + progressView.addView(progressBar, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); switchToCurrentSelectedMode(); @@ -639,7 +594,6 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } else if (id == NotificationCenter.didReceivedNewMessages) { long uid = (Long) args[0]; if (uid == dialog_id) { - boolean markAsRead = false; ArrayList arr = (ArrayList) args[1]; boolean enc = ((int) dialog_id) == 0; boolean updated = false; @@ -804,7 +758,6 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No } else if (selectedMode == 1) { listView.setAdapter(documentsAdapter); dropDown.setText(LocaleController.getString("DocumentsTitle", R.string.DocumentsTitle)); - int lower_id = (int) dialog_id; emptyImageView.setImageResource(R.drawable.tip2); emptyTextView.setText(LocaleController.getString("NoSharedFiles", R.string.NoSharedFiles)); searchItem.setVisibility(!sharedMediaData[1].messages.isEmpty() ? View.VISIBLE : View.GONE); @@ -887,6 +840,11 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No if (view instanceof SharedDocumentCell) { SharedDocumentCell cell = (SharedDocumentCell) view; if (cell.isLoaded()) { + if (message.isMusic()) { + if (MediaController.getInstance().setPlaylist(sharedMediaData[1].messages, message)) { + return; + } + } File f = null; String fileName = FileLoader.getAttachFileName(message.messageOwner.media.document); if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java index a2ad12143..84ae277c6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java @@ -20,7 +20,6 @@ import android.net.Uri; import android.os.Build; import android.provider.Settings; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -88,7 +87,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif private int otherSectionRow2; private int otherSectionRow; private int badgeNumberRow; - private int pebbleAlertRow; private int androidAutoAlertRow; private int repeatRow; private int resetSectionRow2; @@ -143,7 +141,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif otherSectionRow = rowCount++; badgeNumberRow = rowCount++; androidAutoAlertRow = -1; - pebbleAlertRow = rowCount++; repeatRow = rowCount++; resetSectionRow2 = rowCount++; resetSectionRow = rowCount++; @@ -161,7 +158,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds)); @@ -321,12 +318,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif MessagesController.getInstance().enableJoined = !enabled; editor.putBoolean("EnableContactJoined", !enabled); editor.commit(); - } else if (i == pebbleAlertRow) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - enabled = preferences.getBoolean("EnablePebbleNotifications", false); - editor.putBoolean("EnablePebbleNotifications", !enabled); - editor.commit(); } else if (i == androidAutoAlertRow) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE); SharedPreferences.Editor editor = preferences.edit(); @@ -448,7 +439,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif builder.setTitle(LocaleController.getString("Vibrate", R.string.Vibrate)); builder.setItems(new CharSequence[]{ LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled), - LocaleController.getString("Default", R.string.Default), + LocaleController.getString("VibrationDefault", R.string.VibrationDefault), LocaleController.getString("Short", R.string.Short), LocaleController.getString("Long", R.string.Long), LocaleController.getString("OnlyIfSilent", R.string.OnlyIfSilent) @@ -708,8 +699,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif checkCell.setTextAndCheck(LocaleController.getString("NotificationsPriority", R.string.NotificationsPriority), preferences.getBoolean("EnableInAppPriority", false), false); } else if (i == contactJoinedRow) { checkCell.setTextAndCheck(LocaleController.getString("ContactJoined", R.string.ContactJoined), preferences.getBoolean("EnableContactJoined", true), false); - } else if (i == pebbleAlertRow) { - checkCell.setTextAndCheck(LocaleController.getString("Pebble", R.string.Pebble), preferences.getBoolean("EnablePebbleNotifications", false), true); } else if (i == androidAutoAlertRow) { checkCell.setTextAndCheck("Android Auto", preferences.getBoolean("EnableAutoNotifications", false), true); } else if (i == notificationsServiceRow) { @@ -771,7 +760,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif value = preferences.getInt("vibrate_group", 0); } if (value == 0) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Default", R.string.Default), true); + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDefault", R.string.VibrationDefault), true); } else if (value == 1) { textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Short", R.string.Short), true); } else if (value == 2) { @@ -837,7 +826,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif return 0; } else if (i == messageAlertRow || i == messagePreviewRow || i == groupAlertRow || i == groupPreviewRow || i == inappSoundRow || i == inappVibrateRow || - i == inappPreviewRow || i == contactJoinedRow || i == pebbleAlertRow || + i == inappPreviewRow || i == contactJoinedRow || i == notificationsServiceRow || i == badgeNumberRow || i == inappPriorityRow || i == inchatSoundRow || i == androidAutoAlertRow) { return 1; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java index 677837b97..c48cc65aa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java @@ -27,7 +27,6 @@ import android.view.ActionMode; import android.view.ContextMenu; import android.view.Gravity; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -108,7 +107,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { if (type != 3) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index 74b2b80f6..303bc9f85 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -15,7 +15,6 @@ import android.graphics.drawable.ColorDrawable; import android.os.Build; import android.text.TextUtils; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -42,7 +41,7 @@ import org.telegram.ui.Adapters.BaseFragmentAdapter; import org.telegram.ui.Cells.PhotoPickerAlbumsCell; import org.telegram.ui.Cells.PhotoPickerSearchCell; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.PhotoPickerBottomLayout; +import org.telegram.ui.Components.PickerBottomLayout; import java.util.ArrayList; import java.util.HashMap; @@ -72,7 +71,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati private TextView emptyView; private TextView dropDown; private ActionBarMenuItem dropDownContainer; - private PhotoPickerBottomLayout photoPickerBottomLayout; + private PickerBottomLayout pickerBottomLayout; private boolean sendPressed = false; private boolean singlePhoto = false; private int selectedMode; @@ -109,7 +108,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati @SuppressWarnings("unchecked") @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackgroundColor(0xff333333); actionBar.setItemsBackground(R.drawable.bar_selector_picker); actionBar.setBackButtonImage(R.drawable.ic_ab_back); @@ -256,20 +255,20 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati layoutParams.gravity = Gravity.CENTER; progressView.setLayoutParams(layoutParams); - photoPickerBottomLayout = new PhotoPickerBottomLayout(context); - frameLayout.addView(photoPickerBottomLayout); - layoutParams = (FrameLayout.LayoutParams) photoPickerBottomLayout.getLayoutParams(); + pickerBottomLayout = new PickerBottomLayout(context); + frameLayout.addView(pickerBottomLayout); + layoutParams = (FrameLayout.LayoutParams) pickerBottomLayout.getLayoutParams(); layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = AndroidUtilities.dp(48); layoutParams.gravity = Gravity.BOTTOM; - photoPickerBottomLayout.setLayoutParams(layoutParams); - photoPickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() { + pickerBottomLayout.setLayoutParams(layoutParams); + pickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { finishFragment(); } }); - photoPickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() { + pickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { sendSelectedPhotos(); @@ -284,7 +283,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati progressView.setVisibility(View.GONE); listView.setEmptyView(emptyView); } - photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); + pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); return fragmentView; } @@ -464,8 +463,8 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati fragment.setDelegate(new PhotoPickerActivity.PhotoPickerActivityDelegate() { @Override public void selectedPhotosChanged() { - if (photoPickerBottomLayout != null) { - photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); + if (pickerBottomLayout != null) { + pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java index fd947b253..db5fba6ec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java @@ -16,7 +16,6 @@ import android.graphics.drawable.BitmapDrawable; import android.net.Uri; import android.os.Bundle; import android.util.AttributeSet; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; @@ -400,7 +399,7 @@ public class PhotoCropActivity extends BaseFragment { return false; } } - int size = 0; + int size; if (AndroidUtilities.isTablet()) { size = AndroidUtilities.dp(520); } else { @@ -432,7 +431,7 @@ public class PhotoCropActivity extends BaseFragment { } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackgroundColor(0xff333333); actionBar.setItemsBackground(R.drawable.bar_selector_picker); actionBar.setBackButtonImage(R.drawable.ic_ab_back); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index a9f420e8c..4c0f327a4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -61,7 +61,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Cells.PhotoPickerPhotoCell; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.PhotoPickerBottomLayout; +import org.telegram.ui.Components.PickerBottomLayout; import java.net.URLEncoder; import java.util.ArrayList; @@ -98,7 +98,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen private GridView listView; private ListAdapter listAdapter; - private PhotoPickerBottomLayout photoPickerBottomLayout; + private PickerBottomLayout pickerBottomLayout; private FrameLayout progressView; private TextView emptyView; private ActionBarMenuItem searchItem; @@ -150,7 +150,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen @SuppressWarnings("unchecked") @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackgroundColor(0xff333333); actionBar.setItemsBackground(R.drawable.bar_selector_picker); actionBar.setBackButtonImage(R.drawable.ic_ab_back); @@ -395,32 +395,32 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen updateSearchInterface(); } - photoPickerBottomLayout = new PhotoPickerBottomLayout(context); - frameLayout.addView(photoPickerBottomLayout); - layoutParams = (FrameLayout.LayoutParams) photoPickerBottomLayout.getLayoutParams(); + pickerBottomLayout = new PickerBottomLayout(context); + frameLayout.addView(pickerBottomLayout); + layoutParams = (FrameLayout.LayoutParams) pickerBottomLayout.getLayoutParams(); layoutParams.width = LayoutHelper.MATCH_PARENT; layoutParams.height = AndroidUtilities.dp(48); layoutParams.gravity = Gravity.BOTTOM; - photoPickerBottomLayout.setLayoutParams(layoutParams); - photoPickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() { + pickerBottomLayout.setLayoutParams(layoutParams); + pickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { delegate.actionButtonPressed(true); finishFragment(); } }); - photoPickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() { + pickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { sendSelectedPhotos(); } }); if (singlePhoto) { - photoPickerBottomLayout.setVisibility(View.GONE); + pickerBottomLayout.setVisibility(View.GONE); } listView.setEmptyView(emptyView); - photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); + pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); return fragmentView; } @@ -650,7 +650,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen break; } } - photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); + pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); delegate.selectedPhotosChanged(); } @@ -935,7 +935,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen listView.setSelection(position); if (selectedAlbum == null) { - emptyView.setPadding(0, 0, 0, (int)((AndroidUtilities.displaySize.y - AndroidUtilities.getCurrentActionBarHeight()) * 0.4f)); + emptyView.setPadding(0, 0, 0, (int)((AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight()) * 0.4f)); } } @@ -1033,7 +1033,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } ((PhotoPickerPhotoCell) v.getParent()).checkBox.setChecked(selectedWebPhotos.containsKey(photoEntry.id), true); } - photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); + pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true); delegate.selectedPhotosChanged(); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index 2816c6257..bffc3f51a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -78,7 +78,7 @@ import org.telegram.ui.Components.GifDrawable; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.PhotoCropView; import org.telegram.ui.Components.PhotoFilterView; -import org.telegram.ui.Components.PhotoPickerBottomLayout; +import org.telegram.ui.Components.PickerBottomLayout; import org.telegram.ui.Components.PhotoViewerCaptionEnterView; import org.telegram.ui.Components.SizeNotifierFrameLayoutPhoto; @@ -114,8 +114,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private ImageView shareButton; private BackgroundDrawable backgroundDrawable = new BackgroundDrawable(0xff000000); private CheckBox checkImageView; - private PhotoPickerBottomLayout pickerView; - private PhotoPickerBottomLayout editorDoneLayout; + private PickerBottomLayout pickerView; + private PickerBottomLayout editorDoneLayout; private RadialProgressView radialProgressViews[] = new RadialProgressView[3]; private GifDrawable gifDrawable; private ActionBarMenuItem cropItem; @@ -522,8 +522,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); @@ -1209,7 +1207,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat dateTextView.setGravity(Gravity.LEFT); bottomLayout.addView(dateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 16, 25, 50, 0)); - pickerView = new PhotoPickerBottomLayout(parentActivity); + pickerView = new PickerBottomLayout(parentActivity); pickerView.setBackgroundColor(0x7f000000); containerView.addView(pickerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT)); pickerView.cancelButton.setOnClickListener(new View.OnClickListener() { @@ -1231,7 +1229,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } }); - editorDoneLayout = new PhotoPickerBottomLayout(parentActivity); + editorDoneLayout = new PickerBottomLayout(parentActivity); editorDoneLayout.setBackgroundColor(0x7f000000); editorDoneLayout.updateSelectedCount(0, false); editorDoneLayout.setVisibility(View.GONE); @@ -1310,7 +1308,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override public void onWindowSizeChanged(int size) { int height = AndroidUtilities.dp(36 * Math.min(3, mentionsAdapter.getCount()) + (mentionsAdapter.getCount() > 3 ? 18 : 0)); - if (size - AndroidUtilities.getCurrentActionBarHeight() * 2 < height) { + if (size - ActionBar.getCurrentActionBarHeight() * 2 < height) { allowMentions = false; if (mentionListView != null && mentionListView.getVisibility() == View.VISIBLE) { mentionListView.clearAnimation(); @@ -1613,8 +1611,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat float newScaleY = (float) getContainerViewHeight(0) / (float) bitmapHeight; float scale = scaleX > scaleY ? scaleY : scaleX; float newScale = newScaleX > newScaleY ? newScaleY : newScaleX; - int width = (int) (bitmapWidth * scale); - int height = (int) (bitmapHeight * scale); animateToScale = newScale / scale; animateToX = 0; @@ -1767,8 +1763,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat float newScaleY = (float) getContainerViewHeight(1) / (float) bitmapHeight; float scale = scaleX > scaleY ? scaleY : scaleX; float newScale = newScaleX > newScaleY ? newScaleY : newScaleX; - int width = (int) (bitmapWidth * scale); - int height = (int) (bitmapHeight * scale); animateToScale = newScale / scale; animateToX = 0; @@ -1887,8 +1881,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat float newScaleY = (float) getContainerViewHeight(2) / (float) bitmapHeight; float scale = scaleX > scaleY ? scaleY : scaleX; float newScale = newScaleX > newScaleY ? newScaleY : newScaleX; - int width = (int) (bitmapWidth * scale); - int height = (int) (bitmapHeight * scale); animateToScale = newScale / scale; animateToX = 0; @@ -2557,7 +2549,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat captionTextViewNew = captionTextView; captionItem.setIcon(R.drawable.photo_text2); - CharSequence oldText = captionTextView.getText(); captionTextView.setTag(caption); captionTextView.setText(caption); ViewProxy.setAlpha(captionTextView, bottomLayout.getVisibility() == View.VISIBLE || pickerView.getVisibility() == View.VISIBLE ? 1.0f : 0.0f); @@ -3055,7 +3046,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (animated) { animationInProgress = 1; - int visibility = animatingImageView.getVisibility(); animatingImageView.setVisibility(View.VISIBLE); containerView.invalidate(); @@ -3739,7 +3729,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } ImageReceiver sideImage = null; - Bitmap bitmap; if (currentEditMode == 0) { if (scale >= 1.0f && !zoomAnimation && !zooming) { if (currentTranslationX > maxX + AndroidUtilities.dp(5)) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index f5d4a8828..0404394b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -153,6 +153,12 @@ public class PopupNotificationActivity extends Activity implements NotificationC @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + AndroidUtilities.statusBarHeight = getResources().getDimensionPixelSize(resourceId); + } + classGuid = ConnectionsManager.getInstance().generateClassGuid(); NotificationCenter.getInstance().addObserver(this, NotificationCenter.appDidLogout); NotificationCenter.getInstance().addObserver(this, NotificationCenter.pushMessagesUpdated); @@ -822,7 +828,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC if (avatarContainer != null) { avatarContainer.getViewTreeObserver().removeOnPreDrawListener(this); } - int padding = (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2; + int padding = (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2; avatarContainer.setPadding(avatarContainer.getPaddingLeft(), padding, avatarContainer.getPaddingRight(), padding); return true; } @@ -835,7 +841,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC messageContainer.getViewTreeObserver().removeOnPreDrawListener(this); if (!checkTransitionAnimation() && !startedMoving) { ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) messageContainer.getLayoutParams(); - layoutParams.topMargin = AndroidUtilities.getCurrentActionBarHeight(); + layoutParams.topMargin = ActionBar.getCurrentActionBarHeight(); layoutParams.bottomMargin = AndroidUtilities.dp(48); layoutParams.width = ViewGroup.MarginLayoutParams.MATCH_PARENT; layoutParams.height = ViewGroup.MarginLayoutParams.MATCH_PARENT; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 6b6449365..78159d5bc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -12,7 +12,6 @@ import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -90,7 +89,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("PrivacySettings", R.string.PrivacySettings)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 07f415931..ecc42b868 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -25,7 +25,6 @@ import android.os.Bundle; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; @@ -87,7 +86,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.concurrent.Semaphore; -public class ProfileActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate, PhotoViewer.PhotoViewerProvider { +public class ProfileActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.MessagesActivityDelegate, PhotoViewer.PhotoViewerProvider { private ListView listView; private ListAdapter listAdapter; @@ -245,7 +244,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(user_id != 0 ? 5 : chat_id)); actionBar.setItemsBackground(AvatarDrawable.getButtonColorForId(user_id != 0 ? 5 : chat_id)); actionBar.setBackButtonImage(R.drawable.ic_ab_back); @@ -290,7 +289,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", 1); - MessagesActivity fragment = new MessagesActivity(args); + DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ProfileActivity.this); presentFragment(fragment); } else if (id == edit_contact) { @@ -342,10 +341,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. args.putBoolean("onlySelect", true); args.putInt("dialogsType", 2); args.putString("addToGroupAlertString", LocaleController.formatString("AddToTheGroupTitle", R.string.AddToTheGroupTitle, UserObject.getUserName(user), "%1$s")); - MessagesActivity fragment = new MessagesActivity(args); - fragment.setDelegate(new MessagesActivity.MessagesActivityDelegate() { + DialogsActivity fragment = new DialogsActivity(args); + fragment.setDelegate(new DialogsActivity.MessagesActivityDelegate() { @Override - public void didSelectDialog(MessagesActivity fragment, long did, boolean param) { + public void didSelectDialog(DialogsActivity fragment, long did, boolean param) { NotificationCenter.getInstance().removeObserver(ProfileActivity.this, NotificationCenter.closeChats); NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats); MessagesController.getInstance().addUserToChat(-(int) did, user, null, 0, null); @@ -689,7 +688,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { - int action = 0; if (i == 0) { avatarUpdater.openCamera(); } else if (i == 1) { @@ -796,7 +794,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. FrameLayout.LayoutParams layoutParams; if (listView != null) { layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight(); + layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight(); listView.setLayoutParams(layoutParams); } @@ -806,7 +804,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. int avatarSize = 42 + (int)(18 * diff); int avatarX = 17 + (int)(47 * diffm); - int avatarY = AndroidUtilities.dp(22) - (int)((AndroidUtilities.dp(22) - (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff)); + int avatarY = AndroidUtilities.dp(22) - (int)((AndroidUtilities.dp(22) - (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff)); int nameX = 97 + (int)(21 * diffm); int nameEndX = 16 + (int)(32 * diffm); int nameY = avatarY + AndroidUtilities.dp(29 - 10 * diffm); @@ -815,7 +813,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (writeButton != null) { layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams(); - layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f); + layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f); writeButton.setLayoutParams(layoutParams); /*ViewProxy.setAlpha(writeButton, diff); writeButton.setVisibility(diff <= 0.02 ? View.GONE : View.VISIBLE); @@ -1240,7 +1238,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. emptyRowChat2 = rowCount++; rowCount += info.participants.size(); membersEndRow = rowCount; - int maxCount = chat_id > 0 ? MessagesController.getInstance().maxGroupCount : MessagesController.getInstance().maxBroadcastCount; addMemberRow = rowCount++; } else { membersEndRow = -1; @@ -1358,7 +1355,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } @Override - public void didSelectDialog(MessagesActivity messageFragment, long dialog_id, boolean param) { + public void didSelectDialog(DialogsActivity messageFragment, long dialog_id, boolean param) { if (dialog_id != 0) { Bundle args = new Bundle(); args.putBoolean("scrollToTopOnResume", true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 103ac0c18..401dbfe86 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -22,7 +22,6 @@ import android.os.Bundle; import android.provider.Settings; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -98,7 +97,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index a7185bc3d..7e89a3458 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -15,7 +15,6 @@ import android.content.DialogInterface; import android.os.Build; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -86,7 +85,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("SessionsTitle", R.string.SessionsTitle)); @@ -109,7 +108,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter emptyLayout.setOrientation(LinearLayout.VERTICAL); emptyLayout.setGravity(Gravity.CENTER); emptyLayout.setBackgroundResource(R.drawable.greydivider_bottom); - emptyLayout.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AndroidUtilities.displaySize.y - AndroidUtilities.getCurrentActionBarHeight())); + emptyLayout.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight())); ImageView imageView = new ImageView(context); imageView.setImageResource(R.drawable.devices); @@ -433,7 +432,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } else if (type == 3) { ViewGroup.LayoutParams layoutParams = emptyLayout.getLayoutParams(); if (layoutParams != null) { - layoutParams.height = Math.max(AndroidUtilities.dp(220), AndroidUtilities.displaySize.y - AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(128) - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0)); + layoutParams.height = Math.max(AndroidUtilities.dp(220), AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(128) - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0)); emptyLayout.setLayoutParams(layoutParams); } return emptyLayout; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java index 9c0be40e4..119f3dcd6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java @@ -33,7 +33,6 @@ import android.text.method.LinkMovementMethod; import android.util.Base64; import android.util.TypedValue; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -278,7 +277,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(5)); actionBar.setItemsBackground(AvatarDrawable.getButtonColorForId(5)); actionBar.setBackButtonImage(R.drawable.ic_ab_back); @@ -896,7 +895,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter FrameLayout.LayoutParams layoutParams; if (listView != null) { layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); - layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight(); + layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight(); listView.setLayoutParams(layoutParams); } @@ -906,7 +905,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter int avatarSize = 42 + (int) (18 * diff); int avatarX = 17 + (int) (47 * diffm); - int avatarY = AndroidUtilities.dp(22) - (int) ((AndroidUtilities.dp(22) - (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff)); + int avatarY = AndroidUtilities.dp(22) - (int) ((AndroidUtilities.dp(22) - (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff)); int nameX = 97 + (int) (21 * diffm); int nameEndX = 16 + (int) (32 * diffm); int nameY = avatarY + AndroidUtilities.dp(29 - 13 * diffm); @@ -914,7 +913,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter float scale = 1.0f - 0.12f * diffm; layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams(); - layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f); + layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f); writeButton.setLayoutParams(layoutParams); //ViewProxy.setScaleX(writeButton, diff > 0.2f ? 1.0f : diff / 0.2f); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java index 0fd9958b1..897b521cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java @@ -16,7 +16,6 @@ import android.os.Build; import android.os.Message; import android.text.SpannableStringBuilder; import android.text.Spanned; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; @@ -69,7 +68,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("Stickers", R.string.Stickers)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java index 079bf6926..d6d39f973 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java @@ -22,7 +22,6 @@ import android.view.ActionMode; import android.view.ContextMenu; import android.view.Gravity; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; @@ -144,7 +143,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(false); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java index 37fa05bf4..f5f02e4fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java @@ -19,7 +19,6 @@ import android.media.MediaPlayer; import android.os.Build; import android.os.Bundle; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.Surface; import android.view.TextureView; import android.view.View; @@ -224,7 +223,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackgroundColor(0xff333333); actionBar.setItemsBackground(R.drawable.bar_selector_white); actionBar.setBackButtonImage(R.drawable.ic_ab_back); @@ -261,7 +260,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur ActionBarMenu menu = actionBar.createMenu(); menu.addItemWithWidth(1, R.drawable.ic_done, AndroidUtilities.dp(56)); - fragmentView = inflater.inflate(R.layout.video_editor_layout, null, false); + fragmentView = getParentActivity().getLayoutInflater().inflate(R.layout.video_editor_layout, null, false); originalSizeTextView = (TextView) fragmentView.findViewById(R.id.original_size); editedSizeTextView = (TextView) fragmentView.findViewById(R.id.edited_size); videoContainerView = fragmentView.findViewById(R.id.video_container); @@ -539,7 +538,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur if (AndroidUtilities.isTablet()) { viewHeight = AndroidUtilities.dp(472); } else { - viewHeight = AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - AndroidUtilities.getCurrentActionBarHeight(); + viewHeight = AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - ActionBar.getCurrentActionBarHeight(); } int width; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java index 1689a0e62..060dbf839 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java @@ -21,7 +21,6 @@ import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.view.Gravity; -import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; @@ -102,7 +101,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent } @Override - public View createView(Context context, LayoutInflater inflater) { + public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("ChatBackground", R.string.ChatBackground)); diff --git a/TMessagesProj/src/main/res/anim/no_animation.xml b/TMessagesProj/src/main/res/anim/no_animation.xml new file mode 100644 index 000000000..bfaa5cfba --- /dev/null +++ b/TMessagesProj/src/main/res/anim/no_animation.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_audio.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music_big.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_audio.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_audio_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_audio_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..f29f74faa4861b7b40ccf39ef8bd69ffbc8efafa GIT binary patch literal 3041 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_contact.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact_big.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_contact.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_contact_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_contact_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..8c38efd61d407d4c8785616a3911fe7de45d64e7 GIT binary patch literal 2859 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 Y>TkV2ceLK7Y3`RWz$chq=f%$YFK2dR>i_@% literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery_big.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_gallery.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..354e4617b72376ba839d77346975344771f7e714 GIT binary patch literal 2718 zcmaJ@Ygkg*8s3WHCAG{P#v# z-WolXX_{D5Bbj-bGVN+(R$2{}WjdvjX=YjnyUqD=I{Vpse`~Ghec$g}-+G^C?|s2R z{-(y(#sC1A25cmUYGdsDV+hs0A1NewZCEDuql?49c(H^bWCK1dFpdom;4u=|p=<^# zHKmK~2>=iTmqr)UshbH*kmtmh$2duO0xcT=JiVj>1~Z8*hR3lJxO^gF?Cg02oXa92 zB5+g;RX}2MxEs@i?69;T8Z#}4>CQrUZGd}930eUjTg-quC|d+>7c#X67jHM8N+@CaycKu?ZDulC$o-DZq6k4A{KJ+B z+^^T-_Eo)4T-MiX!GD#D))s@FKiK~|=+8@9_skE!*j79FVth7V>vo~m))j=4@c>}3 zIDqU!llDK4dJEG0U~{Kkf^7=uk&A77ch@KkImRoq6m%QJzS+23#7Zc+(g=n-R{4IH z;l4lQMmhz1b5>Qt41If+R)reZZS-*r<}9dtrQAV3{bH)A{DjBu*wp9u(_ddZCmFI| zJ&>%Dw73slyZ3X`gdrJW?tCNL-fkDR6&4$7f`P(dkX#+;HM`UXt2^ak$q6#9dYxd^ zG)AFw0MaS9YYmBA4bv^Tm9XeIfR;O`118H*^pnWI6FTj&Ay)E!Bszn<*O{N@&<52dENR^KUl z(ExO(-s?&Og`B=F@$5h}0OB?Sa-4hr$Sc7FLX`&ebSZ1s;{Ik2Z=c4V}Xw)&534zRv2x!d?| zxbD_vnla;Yr->Yt10eA#*&eOx^oWl$zN)C89JAQdlRqf8bDR|WS1VPSn_g!023r=j z$n^1+hYv-l^wu3*>h)sR!-I1#^)^+MK2l7Z1nvKG@RU20!IEzo2+^-Qc;J=tIc<~m z;u~9I1pUi1P3g!)d15rG@PISV*LZjj73;a+DrHj5*Mqn3b4-S zS>ub8FF~*;d(`Ji`$Bv*{+kj~+IO zB3e}nss~UHvle&DUwUn;js;CEM{DhhllA&mF}yD=c;t3le8V<-&-q1la@LP|LbK>U%)+58J)PV|O|3>QVb`|MF0p^fzf?5AI)$p_g zM+*_28*`WeyeBN)CL()#w_m<}j%e;U+j2nV@!Kd_5YR54P*otIg~ zWZn;iDC5Wxk7JzoWfgP0MeD(c$scNlqo0|)CYKz!_JG2^QNOiP5A(7#M^$UrUpYLg zIvZIKon$(v+SFNcgnA;Z7c?vpcp1ZQN~g|>Rf%MU4uN2gcFWSsJoXD+1On=3lCFQI$o zSf1blhbVZZcQ0TeMxs-c_7Bfy6hDiZR8E(k@%!;`RGKCV ziC^eBMABS8)?BzL+NJBr*};HuMcyA?M_$@Tt6oH=cQc!tgMaR%G^a<8E-fskcsTKg zW@7j&G%JbMLtf>gPwZl*M?YyhjawYFuJwVzhM))59*^i1!0Z09{IIp^)H@kxng;7u z-1j_qRf&pFZp9ZI`g7Z&@imSW*w&7_K2}E8mCZ-v1|GB82~%>lL_XWMcT2yzE4mnG z9P?|OTL0EJwB$hvWTq{w=#9gB(h}ltdjtJzA;UuJzp5WRr&(s6X4Cojz#kJ94LVNQ zKJAhjm-_Uagd0Hk(22pg@@THvM6mot?BllwlB;(SV9Ix4;S5a$00FL>nz3N%`(X2bi~)W@@Cw<`n literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_hide_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_hide1.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_hide_big.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_hide1.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_hide1_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_hide1_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..ac59126865b2437c3dfca024bc3ec698d287f27b GIT binary patch literal 2275 zcmaJ@Yg7~07EXYSR6u#Cs0dDj4_YBFNJ1ik013#|C_)MmixQI|R#?U-8Is7>07GRIOG^(Rxx4wSr3La5yFn2EzkKcxaMUm{jMX(zs44 z2q2A2twb>;q5@5d(hW!=#v|jAenT~8p8B0~iJVqN!ebQdD> zpXZX>xw||np!^!_KK(RECLbtB8QJe5&WT#Lz|zJ2UAiwAHr+lx`|0gv%fv^f2Q07` zhppYy@$XL8_Kv4FU#DJwQd;_$qj@lVp887t21OL9y=>11#hhn*25)tBRa#6O$eIlT zTZm?KzP0TZ;)XOZ6Dams_bB%53H_i!j=C3GO`DRH_Et|cXphevZz@3=n+>iL^;YM! zRp|#Iq4MoHg?_HZR_^@PDGz>dX#8o$`9V@FW2a=Kx%cjchx#GI%-Bt#X4BG%3sB;( zz_(^E*gY+0rr6b{!G`1!H{BP*BTIGX`2h&v)HwHeCuy{9iI%fF1Va8i;LZZZNVOSl zhE$h(Z_Rc!I3}2B(H=6)r>~#a^2*FDG z4c{H732GnY7_Td#LYo0|mqWoM6tyhb4*amoV3)U049GJg8x!qxlIWIStZj0LWsPeM z)s}6uL*3b&(|jkIOFeOscx;=YbCE@RnuXt*ywF>uOA%K6q_(t#bBRusrTN=8FW>7t z!#s{LTzoac&g}li)`pB2JrO;WJwH}Gto-uGOXA}E$lW8~r568k_*C^k<^zB~zIyzW zw_87ODs5-X1 z>$MuYds*%P{N&(Vvt4n4ko>y6c{aYZb*`cRo=N;qX&H+lntd}8yBp-^09en!&H7AY zuQ2#!Omo@|@=jLNCBpZ&D1b31f04CrG54Q;)O=xHBnXDRifD$d0~NV|18{e1UU!A3 zRPPMIugGZL(#mr&+Hab8kW97qCTZ33mh8(#1H{a#(w}9Ww_A@A?+I2lSJ0IN_*wg+ zqHaK$c(ssNjG-&Bn%rke5tlfF#LTkNDtO+>H^Rlhw-Ft;;~U@kckQUTY-4!-c$1*F zpfjG$)+?tkn-(}<@Q2F3dtTC0^I!md9DZitcaLj(?`I8;5dwZZ5yl`zj~3T#wCE8$ znrZZ2Sfq6ZZ@ylYyn(QXzbYk1@Uo=hM`Kh}`N@aL87EkWw=9j4Sb3D!McX{8S~Evu z9#Qr@@->b{E$0u(zMin#QW7z|$ezkdua&t?z}Jv(}%r}f>zI#+JFqVmLb<5Z`L>n+~@LR2&R zgk~?+pi^~pL0@?E&*|+d$NS#^J`IP;+Lpx4VqOXF64%-vjX&u~N@*Z9DxtmfihL$Y>l(qffV*Vk+3Ii!9aVDFXTKPdZpoF z&ZYI@%X286jfo>3R&JJxkfae|exXn6PH)HJ^6Hb|9ir%^Z)nHUe{fnoNjsK|?5G-v zJ61X;p{cjI>qX@G8~YMuw+~wsRfV`HmS0_n6~i%is_*j^ro(Jz6M@eEaI}G`#xL~* X$|y9aIGC{AbnOTct`r;%h)Mr1#cQ48 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_hide_big_icon.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_hide2.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_hide_big_icon.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_hide2.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_location.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location_big.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_location.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_location_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_location_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..bc2f11844606be92d68511fd7ae3a7907a97529d GIT binary patch literal 3117 zcmaJ@c|4SB8=e`<$PluHXiO>VY|Jo|wHaHCeHlv_voJAcnicRbm|nMiPDBr zq(wxjWLHv&ii1kF9HJ=S=v3$X<GjTZ3GPZ4Z@GIg8dT| zndAW_u(@<725xFXMWRqpEEbM3!(g!}V<;MlLL-pk7i)qt!(*^`v^n(q0~34W(inIz zqQiGz;*}LFlF#Sh5eR`m02i3T+1v;O3Wvk3YM{|3VuT4#7{jN;o5b)o{ZJs%c~mZw z!)LN%psR|MaCR);3MP*9pA=Y}pRzH$@5dxQFho3sgFwNNt10~el1Tp_%3}RQ^Y~u$ zf8+h1!aN@#hmP=~^VqRmsr^Vz&eHU~=Z#zOV| znK3lBfM@UxPa@%+V|aW@43+Low1SBh;7leBk3^f{2t+$18nYdXLfK<*7N!msC=3Q` zYC$x&K-&G_64}&P7CnalgG>9Di~1#ZwG~(#v1cNk%Z#Jb9Jp*2^jpe!<}YKx+5b}S zJD2v$Sa1%%Cd(mFMc*YJx1K^Tya|?&ViNz0GSeJqMc8C z|HMvaw2!ZfwTY{Xx$GdB1uj+!Bsd@sUi~ zcjX+=Iq>um?Vz~4`Wk-0#qLM-#gDvpSVbgc+SA7BJNGO!6g1=}6=Vpf8+e`Og4+u_ zbH~OQNT|XI2N^k_*w%x@hLjW=RA;i76gDwL5A0V@P13;0Jy+K_Fp(kW@EP{y(88gs zEjvC2q`Er3q={CbE?3b=J;v2wpha4$W?E75hTILM&|?X@Y3o_}i_NckAKyx~%&=@H zzro^?y-`lUUkzc`K-%R`nHm@ zh!Hp1^_-yeq4xWm8P!2DNG+iT?n!##o5KNZ%p4=g>w^RP26E*1P1atHBiIoJ4eYNB zRS~M(Xq3m7_gY$~%JEcz3A*mOp}S8hNz9IJ{+sj^GD47fg-Ve)B0nRk_vR0JjDjtxDEiFK;;F`>G`&?m~2hih#V1}BdwB(qdjVjP1 z0+JL-S{KpbU*#I8mwPP1#-Ke425q2ww9Ea+Eqg0+9MYNN@Z(<(JOm$gC3&*$&zGBofyVScTYTEJx&~R7O%eOmC_4T?^4~l1)hQtPMlF1e$vx_TX7%7Qu6KAijC8%VGBzT z-vEz<+x=6R^M5keij>1;6-T|y6o4@MfcNJHL+2ZZkq28HAeMZj^vEc4-KZB^2P9*J zG$A)z945$=oXL6pj`FJVbLN8mjoyQq0K3wPShH+P!>UVnXM-MI?-|V4e-hQ_rD$^x>mnvE=uk2OuYWs11Ovq*xwjwBLFDM)6Aow%%^g*3YoEKYIl&) zZvEqOhJ}&6JmGXfj>t0zfQ!9X8qBpwIz`)_A8{xT}df5hC~u>-LR4 z*{6?u6eur?RTKtxp6g6?nA}FmD%lL~-Ea0b*f(Q1YFoi_h4bcdm9vNB%mXg;E@6JX? z|1o6}*PvfY$y_X@UI{GlkC)--Y_9jDIri*+pJo2$kwr@Vs~rKLB0*sCk^CoRSGXx< z@2sN@onrQMX(ra^jDgLXO&qH!J9vPh{l*9{qnJDATaQ=X6u30$78D2Dqr43pJqu1O z=hwZ$Pn?wA#ug>NzxoN?;Wlgls2^*CwJ8U_(KvSe+~Vgb%nilR_+ZA2fgkwBnq<00 z?0IEc0{V?V(A{@nF3Q^~SdhjQnmY_~_*W$#($h%UHF?GzUG`oNZV z5e~ORO>cIky)p#m%ha75WnGgF%*#eS?-b)K)QSOI}ByMepaK zfE2&FM|CBTe%l#H!KGlo#RTqG-)^-pN#<*)l<0fh?Oc%%K`jp>|DC_(&`HL6X5!*lv@B6|eXE*S-@%0y`JE zn7j_t0tNX%D`K;BbfJ~T+KZStVr`D?RL^I-($2gR3M4@&Ro{gi3|WsZABIdSmv@9(Hf>tS1<6+_HM+B+rv`-1JKeZng9R* literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_send_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_send1.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_send_big.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_send1.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_send1_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_send1_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..86dafab4ad2470162ed966ea1ad948bf8785cce5 GIT binary patch literal 2261 zcmaJ>Yg7~G7M&0vDEO+%Lj}fQe3d*UfkZ-p1PE7y$eS3Im<%LhG9eixz>*?*?X{?& z6%;8#1d9qv3c1iK5v*23w1S8zg0)sC4<3!R*hfEXkkjz?0&Y6$R?!doCPSRqb;!XU9U zHK`f$1^_Hx9ub4Y2-dPBu!1C>#E`TK70LzxZ;nsbOi^`1iUjbUk@Y#)I!6 zNFp2mS5h&8P>>6&A&^d5MU+seRFJ_SQ9bAk2Gt#;QK&RB1$`Jqst1eCV9`9m4+D=z zQ%mDnVZ6W(vCthGFGCO&i%d>QNg<`IBEjkeGL^|>PHNC-L=-{Pq$&}ymZ;RYO)2mo zjYKV1A#zv=PAZDGz{v<3k7oMU6%?wEvP#W|GNA<{YsD%ul|-4m(iBi2`2SFa;v-sv zgh7Aj`#*&>5veMO90qCNWVHlsT)f+4C>4vVhQtW0j)389Q&kL=!3eC8!77j&&H$H3 z%au|%MYG~PULarvD>aB%DS?7{Y&@z!lFOwmN+5+BKxZ;&bbkhw8bJ5r(x^NJox$YN z{XG16UQ=8iEJ;>CN@R*F{hRCgN$#W-6e=__4^qpwL()JstN`C%nI->pE*_uM`@ofc zIv4sUxnwjM@?>NGtI<UxoX^~Ou{CE6*!F9=j()L;*}Z;9>u0kJ-m__8m#Qa9hC#QbZ95ml#4ek2 z%3!G66>pQ};n%XXknDHw@Tr@1*v?m-@6z3cnpZp64R3mXFqv={x8ZJ$i8^1r^XYuo zP3~NC^U9UoZUgJr*g67O&@K}*+qx0pKktqjz!`>J_t#_)WKIUl^R8R>^!eB53PRb4 z^MYL&oed5p#U-vUOw{GI|Cov7-Ja3tNPQ73voc#6ym(}z^VZP3)WOXYEqQ&QnP~p^ zpjw%h*(TOI3$bT+5ANeM1g7Wq(`AdgaKl+M{XM@LUkC;^OfT9qt{ZW@QGBM`!LW8k zda29x>2n+HWVRj_#)_sFhTQ5pzss#d!a5PI^(^OraU5GXzl_8d){S^ut7e(447jb= zM`Oib-~Dd$&^OsYlpn{pC=y9~s7nZ`s9*6k<=ucT&EjzaZ5Sp*6kGGI-*J48x z?^?+2gx9?$P2A`VAG}&=33^_BDa`o%OlFi~%sJL3ZndF%eok-KOS6US0cWK{?2sra z)ybtYgaFKQKQd@yR&O-&>v8o}(b)kB`Dq750ADoXxV`mFA=3D@!`x|rRkP%>OPbH# zx;usU(i^Rh3~#tDZ!3GqJF)b7zif$n&d8I2^?NfW$PT)`o#$@Hh}dz&n+=4T4!1Yl z*%#kE?-H1`LPkY&AKUk8mwQP=`)xb6a}bc&f7TeSvuJIv$TQPDZv9xpYH<;s{m++ZR=C;BDdrWtLtMPQ5%_G*1eK{1&+u*`_CkZg1 zF2Izv5VC=c(wv8Hx6Wy#>@fEk0)X=VQctcu#_o0yY)!QA8q6YW<|7B97B%`t%MTkH zvx|T2vC4J<7o8|RIITDK9&k}td~l%7&Nu({g7R|RoT{0}tTH79qA=6RD&2kDt*gZJ zOnvsnJ$<|MSE}^mmtU8uum`*Y|z-+6?GsvDQ>AONufkeP>-#UbbQ2)slx1u&A5u>z{klxuNWL zPbRR==VhvdPHa_BGZgRFHS?X;b9kcybKXd-Iw~G~H9qyLkwbs0Zk})gFgoC1@Syd$b4gTla zHqH^r*h$53zOg6mc~9`E8LWfcv30TsA;JuqV(l-7nne1$>P=pi3Yw`WNx;dY9;B`R zfsE^WCEq~$>DjMIKTqVpQKAJSonL#ItR1wV0GkB?Xu>q_89Er zuWXN>X|@~{ka}?M+=RG-(4Nv{P3o+YectEOo2(XckgX>EmeC`JpPkOXe+Y^hISULg;i)Sx9bYMUa Opd&aSgm=zAF6%$Z#HxY- literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_send_big_icon.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_send2.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_send_big_icon.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_send2.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_video_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_video.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_video_big.png rename to TMessagesProj/src/main/res/drawable-hdpi/attach_video.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_video_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_video_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..db40e51ce1a4579233f39345c60752a2aa33d23a GIT binary patch literal 2369 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 P{hC7pC8D!}U55Vv9ceZq literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png new file mode 100755 index 0000000000000000000000000000000000000000..4b13c02e6a9dc4a756b65237646092fd5a9e1297 GIT binary patch literal 2604 zcmaJ@dpwi-AD>H35l;A(RGOit*o|S!rP(vAn#-(%T#nfuv+QPH4wE(QiM2+pCFdfg&>5$;fTsffpJVA(-mpZmSb#?&rBW$E>WbhCSx7Vvhnv;FU|e(v7f~utOiyv)iR`~9 z0HBB=WDCS>J`XypNRQ`B#NIGnrvH?{6?~QDi9R2b?!b^KbO92LK+Tr)1xTU%e<+vx z6)h4|!T;p@KZQlKQ~`*jf+D^|$j~(|!G1QB08bQxbTMB@qe)mC&JX2B zAQDLc0YfCYqP}neK10F?LwWceIQR_AP}P?WPm_R z=^u+`b7&i_e6;v7GkiwFVJV{E$9)t*tE5v9#S8TyVG0JV0##c zHPO?vjYq_Fk*_SzUTj|qdmA|y{T7`W&$Fy(TAKr}lGn-W4!ZtJg%AFFl@=m0(OQmx z`{$sn`fXI{WvTn#os1`>U7bH}kjc;eNU&dLCt9X8)Pf^{YQ)1=j^h`DhFVTmI`37U zFCVRbZgQqQIdDkb3ZMJXU<6Tpz-UpMMPJUS58R$oV{O}a>*4hRY$QnxDop*@($?tgk`RHc&u7k~;u!fa+4l_Fx0Aa;@Y&U7rXy~KAx^OQ%7X75U zLhnqG>d;9zs=h4JpJ)P75mJ05r{Oldu&cJoX=7+{Kh(U#D(St=-rYXE-h(xoOIzwL zv^^#J7cG)|4ClfXZ?aqNtSeq#J+F0Fgmcbb2 zt%*1K3Y*7A$@XP5YFtQ0`OjJR7i>1o9-Zj<9vf?X`?6MV^LS39-TdB+)n|H(u#bID z-`Kn7`NE@`!hjoXyb{;b+cfX;%NM<7RT-O>c&W+Sv&|oPO9&sj3=>&}d%Dg@pU=N( zKb*NHv}mO`Eru2em}{O@$A_oyGEF8uolk-a=!p^0cUtphf1?2&y?XcB7J-s8dMtRIGxFK)aVw`dXz!FOKs?WRRtpabRiLiO)! zwr339qUU4eP=}vdubGWq-IL$1AF7~5l|{aUg~v7(yG4&xK0c7OZtRNLm|nfPuMNty za>GWhByab^wf9@LQ3p;>#!th6Ie=66U`JYIkImL+vfcvfKt1cPp5o;_G7rG%2X6D( zOK07M(a&gWq}#od3>&9v%S#sHN7lUaZ}OcN03WvVl-uE#%HCGJm-`iQ4qI4{p=x3Y zWwxzWeO5h_X-lTd8j4YyawHCs&tKYZ{k1j9^E&yia_6M&VHFsv!Pu6MR76?$Tc`6J zca+>R3f&}@W$Dw3C%gzd|JrvdUs8ay9t{uaOfL2BJrrybUEZPWV;)+&uw)(I(>yfa z?Cr0~p7TO&awNG#0|19PL0oFK)@tcpQ}d(+H$CKA?2OGuY^{6kH?3Fp7Bz1&7?iGZ z`O%bFGsJ$)corw4*8TBjrg8g;+{(+r+!Jugs(^|z)z*aG{$+qjB%@mXWTbP`qjWO;qRG1(JjqLZWR8tw0p)i zrm3zYV5Z=YC%neL0)}GWIN9L;9H8ncG|VId$H-5dM`!FNxNE`ne zg=vZKRHd&}0r!4ue!|JDED$R*|ICGcbm-l80k~Y*-Hn5(U8C3c7cQ7npMi8O+Wuzi zz`&yEW1+wAyZ)m%mbJ9_O{k(WZtQyMFT02vzAs`OD?);y+g6O^&CI`xB1hQ`SBgn` z^@G%(I|oLx#AMv0shHl7G<@!ulcb+k5G2c#ViwgjY~NP?KDM)ivtsU0jHWNJ@HqU^ zDXVF4<9Ui9&S89JpPDkt!B!Mr8F2Bjd6EUa&|)A_D1g&x$y2cjk@z5N6?te=;mcb2 zXte|8$0_yZY3RY2503epWvjW?d0DByMA{YBDV=xSUXiidF@N{+eD#YY=SPoTSQW~D zN1Jb6SQR@(%YBf!adGcBb@7-z*J6mWW>3h3gLY#6a=(b|>+bC=W~0Xo2Q%5j)twfL zO$EHZw3XdJo-Oj~ZBA)zt9qC`D@igq6W8=Bm`x}`Q K1f2AX%lbF0sbeny literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png new file mode 100644 index 0000000000000000000000000000000000000000..afafbee3bdd73caef1893c686c460fec7dad1962 GIT binary patch literal 489 zcmVr&~G%SylAxJ@FyB3hk z;Bj9txqNu41SF1$w;|f=PoRqloZ!Tdwt#3a+H)(A5^rkYeWgGhAFf)55t8B*mtN%f zO&5^O;z0q3(m~A#tXd0V$bl&DXoL|S2fZ9fBucJX{TxVSZQVeD3=|pwG+hDFLt+3> zDg&h^0nw37O*%3&UTQyimx205xxER25o6(f4%8jY4|S&wVkjh6(NSmuiiexoK5KIf zDnGOpXbilq6=T+ewOqok^=c(WKK4zml^mNrT6r6Ulb`orC6@MP|D;h|JHALEOw_oQ zUX3nG&J=l{N4At*#~{>=2%gIt5Z~DvT&w(kNWQS5ypttl%+R9R{1OVqcYT+^gERg- fZhB$G4UzQ&eXXNX(EUKW00000NkvXXu0mjfsDIV% literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_action_next.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_next.png new file mode 100755 index 0000000000000000000000000000000000000000..4eaf7caab0a5b06d3404a4a2fdb1d1f21d85dd7d GIT binary patch literal 291 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;Lb6AYF9SoB8UsT^3j@P1pisjL z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?iC2(Vqap8ZL^>u^&mbHnnO2I&K=A40@Ah1xZnT9huRs93XX ze*Ik4cyj)>7f1FeIZOT$++tezJL03B#=b@?ap!i9j^$H#x?8bq-KWO1$TZm1VMF*X zH;0(1-vk9hmc0`c=xt2qxe~tIIeYV$YfWu?js4>5v$KQ+C(aA5%9t+pa-prX>zs)j i4o|C}$n%%CicvQzhtcI_^Gl#J89ZJ6T-G@yGywp0C1C~t literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_action_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_pause.png new file mode 100755 index 0000000000000000000000000000000000000000..da17d12ba2bd45785cc964a7c2c02107c0a2525a GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL0wmRZ7KH&Rg=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tWO>_%)r1c48n{Iv*t(u z1(Q5o977@wzrC@Mv%x@w<$`>nfO+B6o@s$4!sZvxDK(wYXF9a|Q_+W6CZ3kbG0Peb zCTz%gHhr_y*6gS)N1h39J95i3I_q)Mfdm5y9=2wntfBuhO>_%)r1c48n{Iv*t(u z1+RFzIEF+VetTmh?;!($*2GC&(-*6v*!y*#@ck+7jx27JL+xzm|vkgff9-RqlW%PMdB5`2qRKDh! z&3w!|HeO5okgy;;@dvly;W@1xN$Z?a5}rAwBrbD$lGx_-Bq^S2Vy`K;;$551(?70= zIujhnPdaBrKJlE9`K0lTtCB~! qE@Fp&$9(tj{gb)0*KD|d;NH30dzNI^ExH8sAA_f>pUXO@geCxJ+lTW2 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_action_previous.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_previous.png new file mode 100755 index 0000000000000000000000000000000000000000..e59dedb62bb7ea25035a3afdd8a6ab2d36f047d0 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;Lb6AYF9SoB8UsT^3j@P1pisjL z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?9nXRfyf9(dU5Fmn~Ct9NOiMhH`Eb zog5$V%UUx{gbTS=G_)Ps5aJiT+ok;Ln@t_pZJe&!1e~2%zGD`1R6%n@ zsZGXt?qyBSVqU&hzc5YRht;&CWeR6hQG4Nnl1-Nnp5aP4>{)2?-R)w|%dfl3yBxgS yj~Ha}buBDiFLJ(P_tQUnqo(TbZurOfg>gmbZMEzYf1pPh7(8A5T-G@yGywpE{B3#w literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact.png deleted file mode 100755 index 671f56f99c2bd5fbb52f75faf549c0b1c44ccfc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1255 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?&B@8o(!j{fz`)$h(9qS?(%8bx&Dhn@+`_=j z(ACHVrq?AuximL5uLPzy1)j23ho_mR$Ergh!BJd8Q{*C#X8h*b>uUC)L!zf zS4v| zcN_V3x+P^a$;5FU>29o07dRcD&8s@;p+pM9rP(fLUG~oBdRc0JRfdIU?*5R13-YU$ zDkdEIYoBylQBB6ytEzGO5ep5`l?xVcO%A%qD(QZ_-A&d-k%7a2VK0Z@A{)CD9Z=EZ M>FVdQ&MBb@0Ea7{FaQ7m diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery.png deleted file mode 100755 index 1c60351cba0a88777282645de89328a6df77fbb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1248 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?+{oC;*u~M@%)-Uk(9qSy!qmjV$F! zNq_$Tw?CY~)U%jRN{mlSQ!|kzXrIFx{v&5Xwtbcth-Y|o*5S|o<;&S!C$Y9CUt=s} z=w(i37GQ6bY1KK=;<`{@R^~9n*2CB`sq{k}biX+hA z(hCKp0agO>(mH&zxQ=XYun_6kfAO$mcf$`;zMaAjF)XRgP8zeX@mcX4IeDS%jK0av z>lXqX#o`%`aA!VU@Z3R$E$881#z)E*N|>1I8!ebR<|ka7?&?*gbj`7TL0=`KFvBLt zeeGNAvl}Yp`S#xT@bo`owSq@V>%{_@4(`SslN;(5T^2Uvi{dTuu{YyfV6oz$9pm2E z9%g~5^EfPDSP7^HZuC%?F)xBcVgcuo`Hi*{8Fg3wzqoPP5AU94y$cr|pLZ5sNXt;~ zyOzK!kgvK_`z`ZZbHmFDv(7ooHeZ}7C;L~TRA4EC!U2ZJ>|BpxuUYp%Wsaw-pUXO@ GgeCy+_n_1O diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location.png deleted file mode 100755 index 52bf605163d220aed9116340bfe955ed90dcc9fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1490 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?!r08w+0ekq%)-Uk(9qSy(#hP})zr<&)XmM& z&C$>Trq?AuximL5uLPzy1)4hbZ=6+Cv!6w_#HElf1n^*K5H*|KH)QY$ik#qMBkKC}D%zUupDSkATDr&m1RW4yom-tPGI zdh^fE|1m!*mUo4W!^et0HqZFF7D&I?R8s3Ce<9msvWH6D6j6=|49^s$+{9xK*)Kk> z!FeP8eq%%CfisKr`sc>E)H>9D=jE7DJVUkQ^oOez+Ez><=X4Dg%rwYkRF2~4{Slc#d9t16mzxa%H1q&%@=8ich^6a?Rm7;QF=jDYkv5{ z+s0>Ja(xMXxO>%y*x(-(X!z?Gwxn-nZyZr4Di?@&Ld-E2ViA&6liE@~H;`6>` zF2a_})--B-G(WS0-yzv5THx;0f0Cyn5Bw3Sz07%qX_EILZtexok9zmWiweEvv@&S; z*)i`GTQ>8_=kmr3T`%+Ed;Mh3cxN8{_9(-fx%jsCzXr#C_B+>?9Wo)7N6P3{7d}+L&L<&E57?(JO(OdJzf1=);T3K F0RVxFE1m!V diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music.png deleted file mode 100755 index 5a8f5cf4e2e899767663da154a0f8a4512462073..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1206 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?!qwQ)&D6lqz`)$h(9qS?$w_6Nw>eUB2MjsThND&Pa0;V1i6P|2=9C*S{%>$Eakt zaVzQ1|Nr)f6PSE>nt6Dv*f$C+Ua@3Ji>yZ}W1)-ycfiSa{tkN>I=ri^s_G^_QCN}u zX@!hLjYrzE$x^9>COu0niY`rH;FVQzD3VfQHhCnle!15oHD;55qmBpeu;{BcYR)gb zkXCKf$SlII#eQ}2s?05~Bqs7%u^cgT;92$lh{McMg<{DQhUXmqu%D{uJ+hZs(kaxV zPf{eXEN#P5MLU}!A?Ak*B4i%zagebP;LBo6D%a_Y diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photo.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photo.png deleted file mode 100755 index b2b0caaa531326f1d95350eba50670a02289d9b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1442 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?!r8^y*ucWV%)-Uk(9qSy(Z$@^(ap`p%+lG= z$;`kRrq?AuximL5uLPzy1)4yySlYfd_)c>y;aK9U@|fjNlyrQ@H_c| z$d(sUMkc4?dKmZ%Jp88n3$QctM6dgCAxP{}gW=(^x$xFj~%v%zJRBg@`Q@X;XBOVuNsXA*MzN)^uWB#L8{6;NBTV;w< zI6k`fz1DhkIi@zCZG!a4oTb0yeq8MM%k=w>)5}SUPnL+znEUBQW&vwW_=HHd^Cj(rzAaU+Cnw*_Vb$~{H_mW3L?%ssEvYtH;BLm( zoOQ|%*n%9RzFaX2*Z+VT;f+f&-4wntdOov z-P-bqSD-7CH?qOH!kXuWq}t}Ie>N}Fydq-s>6d5%L)EV7KYqQr`5jbhdb;|#taD0e F0sz*z4ub#y diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photobig.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photobig.png deleted file mode 100755 index ca397177e381b93d9bdcf0d578a75a15743d259b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1696 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 HlGOhJ4n>KO literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png new file mode 100644 index 0000000000000000000000000000000000000000..7b02d9e1cd609a327bbb1aba615f5f6babdcdd84 GIT binary patch literal 2163 zcmZWr3pCVe8=s5IG;YH%qp86ZQbtXr)u42-q@iLk4KWI{qRp6i36Z`!Z(op1Mh&-1>&_dL(X)c%OG3^TrMgo5nU7U&Tm5Cr+?k%QDrgEKkt&YH(iw#yj#AA%2Ss$-9^p2$-L zSKumZ>uQ4*lgGT;_YPCk8eR~_g%-2VzEJwJMc-CdmSn}9lM=OtUvQ7VGd@4r?qFUH zbO=wtisUHUp)TJ64-FFiGxv7}tmrr3Fa9?ObY`>JErrL@AM{L5mjaG->@F{2XO3k$ zPAa-(-13s=Ua1bSX0baxQG7#r`#qmJIw-7}!KyQ%p;ebwC82X`t1IIZt=v;_5yP)v z6Z`u55;pztv$XfATo9#}Pya#(CDLVfMP;RnRJvTbv@ql0CYhVCd$f4pyAg9dcfVs! z^2Gr311~rxxZB0M;j*h#@|Cx=wiI3{3foBW(`H%}%zb zmmF-2Tu!t0^y?n0uC7iq$lr>jIgT-{E{XNb3xe?~8=DNy8!*h9`E3)iYPxB&1WK$@ z6o{^Z>Yp}7M+_jq_wg4->ecxPfI7!ua2Eq+_*cke0RIz@mh!JkzHDFR zH-A9!ELjQrwUyS7K>N;zuN?~rIWQY## z+ROEPQ^+G#?WriMk^1mTi-?6FhhKd&i;|0qi+j(tNFQ9;+R>zu07Ouv+->c2H1o=z!-jf#j?yKtxJ756V_k;qB_M`@tUqsG}1F|c9uOtiwXr+&-K z1@N&42^y%*4<5Ou#0#b7BL?0OoI$4)VjP+?NiIJbqNr@#<*QgLSL%QN&mwN%Ljp|5 zCcAfJaMAZI*>5Qc@hod*s(C5)No#(LkO0Hb>2!yHk;PBLmToewO>U>ByI3X#Havh4 zVI{7hwgw~h+RDPr(8Gr0%y}c0w@=+qicnrHI_^$$-Mb<-oKu(!6eW00?u@V5 znlGxVLfOVV4UW^@zMvs)TO?Sf6A^lY!^4jEx!I92!r>bRf-@BagOG=iMwX zLg&b$lAGtyZ(KmR>E{n_p48%ZE|_`g-ZplKRmuSHd{3}N9M%)9EV4mn0IL)1-9(}P zsG%weMS>39F)>xDXTNj8VPc(K+(0r+JGkZffUmi~>@90>;Fs=#uNow%r8wL%cM1)# zn*RX&klOt|{l}ZjvJ^OWahJAXo_a^jXSP! zx|kU}Nt2lD#hpabT21t}G2qXhDyj;w#>U1GCA}3-^NEjj@5b4ez0D>(j>3*=@KxcM zSh~+Mgy2CYyq(&aV&mK3+@-_R;k8aptVCqz0x0BZ1L!RQlTDn z(}@odNaFDD-IE5d^>DX7zs~CiY>SLG-eUn&_bu;E zt5@tJ>lUI0`Cbi*#K_&q#xbTvzO-i5LVPQ0e zHOHasg^mh$pd!Ue6ozQyUwlDHq9Aa%_S@0pUQmvPJW^vh~bC#p%k~mt;oj4Tt?#K9zK)t_b;Y@=dci zhXwmUVCHzJ;VjRSt27#N;OO8cKRD&|_> g`r2J;Ze(U7tdn=!(2Ci`$;9{|8 zDwT@7G6`|OvFP31owS9M3MVSGO~1eoYTF4o0|A;ijRkNlwOY;0%*@0BXE|eCAOY7^ zgm{l+h%h9!@VQF`>Gp5Pf`4gq(q^)rr9jg74^E^>2CtB5`o7 zsIaFAWnA}YY)(pCMA9~unJ8Dm*2>F2x$sLuT4L6xADn}0Ud`+?5EtQ!KA23llpbVK zdFqK7-`?I13jSE$rm!~GRe12EtR3spkisBWNmztEZ$sKPS=p#^l@oB5o5C{?_B;;H zhV=BN$@ VCQuX4uPgun002ovPDHLkV1m#|_I>~W literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_back.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_back.png new file mode 100644 index 0000000000000000000000000000000000000000..8eb567adc3faa1a1982168a8585d88bde2a441cf GIT binary patch literal 1166 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+hnVDkc>}+i8Vq|7wXzAo)Xy|Hc;cDdUVr*_;;^gS+ z?B-+u)9aF-T$-DjR|38Iua(|ZvxVM|XtUeCb5$l&SX7*cWT z%?)e5Lk2u-57a`OWZH`jnA}euaIsErY~Ju;2eY}8!on*Pn~pqaTefww!qH3nQ-00b zvMxHYXJwIAWNH{|h(lzy&R(z6U8|tpaBlKhXTw0F4~D7k zCk6L5i;DiaQM}mgtD@hP7sp;WE|pBI4*0%OdCh_!Hy_Me&ggUc-pbR{vl&G%9C^he Z!4P?``^JKI#os_Bgr}>Y%Q~loCIIiDijx2U literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png new file mode 100644 index 0000000000000000000000000000000000000000..c65818124129bf8128cec66c80b8829fbf75f1cd GIT binary patch literal 1302 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_pause_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_pause_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..4ec1ead1a5f3eb1329c6d7b80e8310c34f127a4f GIT binary patch literal 1001 zcmaJ=&ui0A9FG=7hZDq$QwPsC(FtpQHrW~$ySC}pfElCfv?z#a^4i8Wc`R;Gfe8TTdk3r zc|*0a$6ARE8+!poGt7K04lKKk2&ki`>ud1qo3{|Sjs|bZCT|8s)N;$4AzIyBuG*Vz zJL|yQbub^Rl)yv8022lyr@w@WwV9vgh215%3tOibwvI4b W^VIhbYmeS1kIyJA>#qy<9{&bjr8rpt literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png new file mode 100644 index 0000000000000000000000000000000000000000..434039be98970733b1c6de19cd4d85cffda1da3f GIT binary patch literal 1342 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yN!3HFix4(7=Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07?@QuLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}+T7#d8#0MoBXEYLU9GXQxBrqI_HztY@Xxa#7Ppj3o=u^L<)Qdy9y zACy|0Us{w5jJPyqkW~d%&PAz-CHX}m`T04pPz=b(FUc>?$S+WE4mMNJ@J&q4%mWE% zf_3=%T6yLbmn7yTr+T{BDgn*V%gju%ax^nHH8pm2HMDfHG&FQIwQx0Zb}=?LFmZBp zb#`+yfa!I~PcF?(%`1WFO+n~&!>JdP7;+1MHoK%2WtOF;xE1B+Du6w0m5JLe&N$73 z>P^Az78jg)^?{Dj2SqJXRKtXT=?BDwCtM&0p7c}mfa$#mn6Rz+Z*E~=VBFy8;uunK z>&SI`jU$ON$3NbGxhtqmT4mblgro^c6O)8e6RnlIJ6sHZ1bbb2dS0PBNKDO8V~Ug7 z!jyvN_m3n@jc|``T+DR-#Wc;VYF0bLe#t%6^?MiFrAsTXoE|UDn)3Yn;|t$pDjelkUADD} z*Z$Bd>hr*K^3J#Ed|zZbZrkyuCYLU-oZbFA&>?PVV8~0o^DkeVQN15=cn9Cq`nh*+ zJ`1ToGw=33QTvySLGQ00HjZuN*Gah6_P!&I)_U6_dnqd|SQj=^t+# z*Y>unuWyi<>|GUGwYk#HyRkO*T}$`ull=_L44r>`QrD#f%mkHap00i_>zopr04g8h A*8l(j literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_play_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_play_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..836f92d592f56dfc3c3a0408e8811995fae54da8 GIT binary patch literal 1342 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yN!3HFix4(7=Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07?@QuLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}+T7#d8#0MoBXEYLU9GXQxBrqI_HztY@Xxa#7Ppj3o=u^L<)Qdy9y zACy|0Us{w5jJPyqkW~d%&PAz-CHX}m`T04pPz=b(FUc>?$S+WE4mMNJ@J&q4%mWE% zf_3=%T6yLbmn7yTr+T{BDgn*V%gju%ax^nHH8plIGPHEEG&FQIwQx0Zb}=?LFmZBp zb#`+yfa!I~PcF?(%`1WFO+n~2#;F&S7;+1MHoK%2WtOF;xE1B+Du6w0m5JLe1~|=w z>P^Az7DJqR^?{Dj2SqJXRKtXT=?BDwCtM&0p7c}mfa$#mn6NL$dZ#cjFmCX4aSW-r zb>zCe#*svs;~($GUY}}oM`5Ffp`izm=-jkn?nGCYMG}8BRVDvOrUafkq++fy#Yt^p zO2PB{M-l|tma0_Rf31DB>(JewcfbF3J4w4%fyeW0M^k3BkS0YZf1IWt_~gXvZOyPg}Te%wYHTn7BeD zST`Y9DgNZd8rN5>Ij>SD&pI3RWKqLk`_H@7o_yua7T?f$g2A|X%~e;%*+n^t?4o*H zH%uNgalh>Q8q;$}fUTfg?q~GY24BW$1x;?^tUeUY{+z$2|iICc%biV;GG4B zd%jM1u68uSIrl+_iXU$|cN z=Rbdyt0qbEafM%c-tU>Vmh6viEnj#u;%&yMClBjH4Ax)b&`O=2URshiS$|EEPur>e z=id1g>)5CHZ_Pi-U(|5r=hqJ<;SXd#&)E3*^8449^KVYb{$9Io*;RkmbA}zxZ{v@r z)s!uEd;IXEc0%7t*PVKMv*w*&c3_=O`Jtm{pF}q>GKeno={UJB@zDSP literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png new file mode 100644 index 0000000000000000000000000000000000000000..b9d6787256e3e267608336d82bbe61793f72eab1 GIT binary patch literal 1313 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL1|)l2v+e>Z$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~NwKI9VDvI~zM2S~@u!8oHWVxEeXT7@HfII61mH zyEz%a^t$9Hm*%GCmB93-AoRN6)C)=sxdlL*T~doO%TiO^it=+6z@E0s#NrlnOE+Uj zCt&pBbPGgp3Kq9O^%~*Ss}FRHJ}7FDq8cUyOg|tdJmCU4@T8xb2Tbopz=Z9f@$@VM z1LI^*7srr_TW@9=dLMQWIWDZd!{X}N?1i%*Etuf?BIxc_{{Z_2jXP`dTBS?M0@!6= z>sfK|ap^5;3Jx=$8^h)GhdpkAg-FlN-Jky0|M=*X8B}-Y>Al^H3#X+{JT{|a3foZ) zH^Z*Lo+OdQ5=Z~ZOis<)bZy(jTlRMMbU*7PpILE#rQ+5PbH(+Ol(q)9-r!iNc1d%G z#^*O1=X6bYrDWT1=)+N|mIA(I#i(}iT zoEFsnwMT_ZM9*F4#m$}C8%1 zJb^DJOZfC-(KQ~zHWyUFrZh2cV3=ppDf*E|>|ov1QvDx^eTHca+X{E;Tn=f!G2y|~ z9IM}}j<~#&UGsR8wyG0IXrsv2==*p7Ze`zjC2IEeZ$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~Nw~Te=xLI=ZRLsc3AbuGXHX)v}B!v*Q*0^{L%pA5N`%-jB1g-uahX?00b7u z)q=CWK1UgH0)%ZIsVwVnO5VT}XVLkxf_3$R+~0S&|0VnF50q)Fjahfu=&7QaT7|Ru z+}N-rmG6w(3U4k^Zfd_V_0V-wpr( literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png new file mode 100644 index 0000000000000000000000000000000000000000..492637b717bdb7d1cefe7b957d881c4608904657 GIT binary patch literal 1187 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+hnVDi`V&v*#VCv#zXzAo^Xy|Hc;cDdUVr*_;;^gS+ z?B-+u)9aF-T$-DjR|38Iua(|ZvxVV@Rm+QY!WDC+6r7*cWT z&5XOe%?bj?wJY0h=e>JwU_Tu-W>FBEQ_XuU98q#>N*K>&{^*&y0-LgMQW1nJo=szv`@J zd@Q<^z3p)A#Ka^U_L2uP6OAwb$w+J|TlltM|JR^XM{XokD}Da5!FI)zPD9%i?J1&< votEvq*1*+utMQU*!>#}Pt9LW*WtCufClxzua+cReP_g0Z>gTe~DWM4f?2wgB literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1_active.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1_active.png new file mode 100644 index 0000000000000000000000000000000000000000..4379bbd2cefc39a207430725dc59c9cf3af84560 GIT binary patch literal 1230 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+hnVDi`V&v*#VCv##XzAo^Xy|Hc;cDdUVr*_;;^gS+ z?B-+u)9aF-T$-DjR|3+bs}6y4munpn|0<~cmD#oH%%WQptvh3PdR_B6-@Q7esNjX&MVkjPi)U^mL=DLu6#^?9?2&FeYKY{fV6Iysfd zn7&C``*v*XY6OG;x=G7|E_-RM^3rtpc2N@)z4*}Q$iB}5@M#3 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat_active.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat_active.png new file mode 100644 index 0000000000000000000000000000000000000000..432f02870c8c4450cd0142f3b6e516778d709815 GIT binary patch literal 1195 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+hnVDi`V&v*#VCrISXzAo^Xy|Hc;cDdUVr*_;;^gS+ z?B-+u)9aF-T$-DjR|3bc;UFG5VmWMT%;e5HS6KnDB%P4joW=nd-57=_#X^7W$LFO$ap-Kk@yXvox2oxs$#o1FwYbA}6-1 zJ6f+!zHou3dG5C|cB6z@k0QgEj%jAG^R)j~I(TFUZ^lvMxu%!@WF)qfE&NiDU#*#z zv}S|tM9ZohLLq04NXT!J^y)5Dxg6u|Q0bcMuu{h1>;Lwv7aQ&|@i4fW#Cfi-h`S0Z OK0IChT-G@yGywpQ(U;l) literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png new file mode 100644 index 0000000000000000000000000000000000000000..0389f00b90c91cfa6bfa56f8ce16b3896d0c51f2 GIT binary patch literal 1366 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+hnVDi`W@=*O8Iua(|ZvxVW;`H-eh24JmKl$7*cWT z&2?X|!ww?s1;$;w1okveFL=m#Wv#S%-PWv}H*N(JgIVs}R{8pxX`8kGgImod`W(mp zYwLgDFg~dw*`2^9ciHFj$K+4XR6lOgiT>q%_O*lTi}=Px8oQjf_e!)SX6PO-eElL$ z@b|LX0y}^6by^1BI~uBTs<$b`yb-?3_-O4ro|TjSXQUOeJap@JnA+IZ5s~w|G%zE+ zW2UgcbDsr{N6j?eZ0>o-S@=`!JUw-eZGQ^Sk?b)B={X!r#ZFT ziuLNr#fMdwnRXcVcLa;i2wQOffC-yn+pAMEy?rh(xt1t&MB#YCeA#suwoCjj3tP!M zV7J9MnZ>e<0f7<@=^6j_?2W~mdLf@^`XuErw->mUXtds=pc)k zceKs#pzzf>M?52?m2XKUofdr|JJIy$hpbt*?x@`kkC^q!@!!*n48|+FU+#;s4q%UR c`7M~hz-A=$_#4ZS<)D(z)78&qol`;+0C1!6;{X5v literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle_active.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle_active.png new file mode 100644 index 0000000000000000000000000000000000000000..c1c5ab850eda91e53d28ed644c19528037064d6c GIT binary patch literal 1369 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+hnVDi`W@=*O8Iua(|ZvxVZU%%Wx>F}c-qs&F{I+w zo9TPKSPTV@-_^)c%*afADy{K@C9Ar(_rCn<)22BxaXAFHE!Lzz92!9 zW8MG8NDl8!C)3;o?=;%)Je#`NUTyM8l~bE?9_dG3VK8<0&y`X6rLHTDHEaJ?u{|e0 z-qV>SxFu7%`KMCw{-OgV3tFOV-1j;BxWPV4>`Tm5=T%SaKl$)E7Tmqxpv9c!Z2Q)7 z9T)5GmSai|GRB>ZtDZBr8cxo5w=h?e|K~9|ES3{cD=hMB3S-)V z_ZG=sm24|GUrFpTJ76P`kTmPC`i0Qe*x(ka&FV4pI={*+b3B=n6}L<~qvK>ex54gP z7p7cto!X*RRN`^y3R}_)>kNOUWnvfn53n#B@;sed>pA1X0<(i(7H*bdOTK2|9KYbb zw@z?$0-Kz{l=O3!m0I4FLHr)gmKzRk$aVbu=Xb}np!TF0?zhXAwIrUq`+v=V&{N=j7L-8~W@tM|^uE8^(9 z6+FQfzk^oBUVFM=4bS46JX=&)zc8gPG}tqH-lrK8cd-SY+$B}Pt994c(edt`80iIU e9tZZZN-(6h%bc4P;$a6W>^xolT-G@yGywqmrRVGb literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player.png b/TMessagesProj/src/main/res/drawable-hdpi/player.png new file mode 100644 index 0000000000000000000000000000000000000000..a62ef59b8ba9f2b4a639db6898c0c166964bd3b7 GIT binary patch literal 1415 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+hnVDkcY+~T*W^UqaWN2w_Xy|Hc>EvwT?CR>|Waj2% zXy9fF)9aF-T$-DjR|38Iua(|ZvxVb2bg`o+M&_|wzHF{I+w zl^KrSOpYSQqdA*6^yjvEiS)cl5v+L6{e|^aLS4(Iytpna_J=E@)kV4YH_Dyy6XcjG zTC!$x%Y%b+|1tYZxS6Myr%kK+V7=qqncwgCROY82OYAxOM|Jkq7t+kx39LF7Hs^of zk~`=w(G-**{-)u_lx?vAY~c$QziDjuX=GW^r1&}C`PJ-zkEUxKS!5a*FPqyPQ|y)W zxL~s*@!8vH$G)j{lxG-JU;7{=I&;GsnF8KTVw-t|ld%2t6&h+rJN$)qh?lmu*SUH>9D`c!7VhIB4Psy3|7#gNzI!7)RKDK2>s(0JvpWIIl zie+ejixgvZ)xA2?tn<|56ZdtjR`T66dYbz(qxsrq6%}T^1IwIl&$DoT-`1+rgTe~DWM4fWRe9G literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player1.png b/TMessagesProj/src/main/res/drawable-hdpi/player1.png deleted file mode 100755 index 6ec1a5d281f4a1ccf5986f08f79126ec9bef9278..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 687 zcmV;g0#N;lP)nA_7PX zO)C_KnxHb2hYHXMR1DK^!V-c$-UoF-%`ZGkZqGr#pkpUMfayl_5vr4f0@TLphqBOl zRe%7Z& z|Ekl)O$#rHmVHJX4Cl2AG2a`1ge%8qy`oz2Tke+xuO~UUuY;y6E%MA&&HPiCM=N_X zr0%CIs1GkXq5R5s{@-Z0JSRfdxQjbO`B3ZRv>Yh4ckDi>7Ug)kqYm3bGcVg%G)72}Cu zegv)Jpc0m#vRt4?nLbLk-y}yOCFu=NxCMsVGs3&S>;!oL7D_&~=nP-~S)_?|>cz7y#P! VxnE#JB>n&Z002ovPDHLkV1jlWF#7-i diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player1_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/player1_pressed.png deleted file mode 100755 index f5698eb118e03763c232b830be19d3a847dd8495..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1210 zcmV;r1V#IaP)Nh!Q4v(cKb4Bb4-x!O@S_z( zs-R#M7c5m#5$l2lam9ryYOGb8WoDk|#YuXTChbcz!3T$A-n^MPbKkw^-aC9zLpl4O z<4X18xMODq_bLG<10G;J5Cq-;9Y8Datv@$Smyk5)LZA{D(Z|}Cz*XQ9@WpOI(h@s> z(lp4AwXg}O2hN#Af%kS0+5)WWG0T~sanXj~u+YQ@&X|jtd>9kVhhItDOIEK1sS#beDBkyoC)CzKLg2U{Ezb*4>(pa!N*uY&4;pgM#(UX%qS5XewwyI== zDq*;_g=#UzNyoxL1Hg zMb9we%cRxR%qu>VqfwNQFJ?;4x|D8aBq0-hj=|?D8ks)JM+up6ndm=`D50O-R%E$K zSH|b2c!za}7RBf1k^g>5=q>Sq;fjje2=*;Wgzq90{;FE+^P%ME9S!?dvS^%g8Ym2I zg99&t&&>Q6_7K!OwM5K=jzZK;h1Ov^iv4y<=#!iTWW`s=yPU<)i4RIInICFG-P4q= zuYk}La@d+oshi2-`Pr3e1dgs%l9`*y2%RG#J%)S$5hl0Z{flu4_xl)RErmp+h9vO0^Epa(jy*?&O`W8oX#h)OTT>rrrp>0P4ur zEkP8`vx^MU&4z?1KB!VtHvpH3iL13Ap6ZOYPuFs_AMS0WC6c2SoyT3(HfSF(1ej)7 zY96w9iSQZ?s&dfnz^gtv>6~WGU0S>Dl#gq^Z}sF>eDpK7bfx$pU6UPgd&5rL;z=`usU$AIMPCk zh;vK#j0i!Xr{rix7+eQn_YMUgf(bDxT*^q1A_ctJ&8LG>R9@RpIXB8sS#A_{_dA>vDUb;s0|XF1h9Fc1 zH9&7r0!l$w(5rP10YdzF57YrQ{_v>ClsI$@omv3`Oecl`sG9M(1GPx?Lfg=7QGfs< z0)GhV_PDxD(1e7F839R{F&QhS**qe>yK9p6!$pAkZhbQT^nu`=E(~23N=*o=)dB*H zSjv8j#duKHLn46v77KD46wm?c`GsAgo0Vl)E>U%B*wbFpBt26YmFFEfv`Wns)$kH4 z?E`F>7|l^STNXYoMKknB5v0NbUHb#DK^HEYS4IXLlvznfAg~gJH-J?Fmq%P4v!WH)d=?ZWhPL96ED{qm1LeS zXbSNZ%BH;^UJKF&^X(_8+`gsIsROlWN_K%Z?Eu=zZ(&uH`p_~=M%5dsfJE#0U=b*$ zidCQDBp|+E$5IIpnYE|g4*@Ff*4=rqcPN@IonAUdK#?#~!6OPTW2szYaMj*DHJ?<{WYKu0R{l0x0VEb%Uj6+0000< KMNUMnLSTZPxFB5s diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player2_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/player2_pressed.png deleted file mode 100755 index 879278c30e36f4b656072ffc13c8b51372fe7db4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1250 zcmV<81ReW{P)C?@=zodEEozZk=UX|jTRaZFNqoxW7sppGmrHn86YwhF1zrZyzNvoF)uBaP#drvXa^b!?7aj0 z0{je2m75Tk#3#VoBFMLxcpvBmPFJt2epn7d9|8ydw<@rRD2XGu%ZRf0h#5@Lvw9t_ zL0ma;KiRz>=$v^la}=b0S}dVgfWts5S<6U@bU_Iy*L*Md#_~OA7>1CHBwMwlwh`nu zn9CyY1xU4k)Yti*74mo)C-W^}y8xtc#aHb+;|X~FF2?9mGpXiuJl$dF#%i)W2vXbx z*!69>G7udEEzsLau zgO^H)HG(8)I8d+Tk4E|)tphn9y<34&n7rKP~$e1zJ}h&yMC{%Zf(N~8*|KE*fbW9^!*@A{B*kPnE}g zVw_+*n94TcPDh%($m-aTo5yhI;Y>1fkff#@3ANceekRJoW0du|J0NOCXqz zv9DZ8XqFgv7;0;xgc@yzk~r;(%sAV_vd`3P4^ECt&5ePJ!V@xmkrE1$q?vR@DC0oJ z8Y+9+oy+C?R*(|XbGALlVG)YjnOZjjuAWp_{&eDTXV|C;LS!1DghmOWdRK&2uzn^v z{IJZF?CDL@?FZrZt`f02tJXk5HRf~@ z#r`BE^q4OKb$nAQnrifgeUDs`YG4ESJ5a2xs4?|5G97k`)b`2LxVp8HhRZ9;teR~n zOBbC8owil0>2IZD>4r)XN<2+$1}V#aB2d?PCqnmtTbAoXZ5{k1=42V z_2Q#$YU)1V91(G6Y$DcKiu$0UKy)J7OQ@8Wxo zfy}R^_V&CNziHOo9XW=|3H*0$S>X9N@V)u5Aycp-De{9AuUUBU#Y7GK;bi?M$F5OJ9EQ%Lm8KPpTSed@C!}SFAmfyTV2bD+?>LH(YkRZKYRcAhX$us zZ5Q!VO4q-)`rdMunteWpKSxB1thniXW?mSlip;`|8VNU?KlM5!2QHY{z@nnS$m!w0 zBs2letk>D_duvzmm!s2)zg&Ivrs(>j19ytH$8U+-u3@k}F8+`E>Ad>wl?+RM&v@uF TZK^&nco;lg{an^LB{Ts5E=z=! literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_audio.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music_big.png rename to TMessagesProj/src/main/res/drawable-mdpi/attach_audio.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_audio_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_audio_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..1ca2ee2b66840d042b1fb893c4fd276feb017ae2 GIT binary patch literal 2284 zcmaJ@eLRzEAKzwDqSFgI6165w?0v@82%EPuX{MK_(q_A{*zVglHl&tQR8NlTsGdYr zCsgPhIqA(>J?f#TROFyZ3wi6sNfC0kPCCyYPtX0i@B4RM*XR5F{$BsM_JoB7TAJIM z!(cGW;2<{FV110=^l66wS#g5SVCF0Q*D1omXoXTB17N-)FbY5iO9U|h7Z8Y&6Y2ma z3}%86^VTWWaY7hEP=Xg2F?f{(GO%GV=5iGz5XJ!tbQBOHmU>}cU%ie&i$z|TweB1u z2Vw!S;-C~65S|js6Q;xo=_1T>Z!}ZIFbGHhg#fLR#7pH2l^5o-F2k@k9uqL=&k#kN z7v`^^)^WnnEKmlZ-SHHhkVqn-X*4{E>Q1AP+|XnqiA*3GUK)->Ww_HAWDoS02V?Li z6Gbz)?0_%63_CAOtU>`X2n3~4iC0qape%+!qSNU{4Kf*LK;Y!bQiVW;lgb^Y6xe`V zC=){pF(^eF6$MdXqQVPfi1e=%B+yq`sr*Zs3o1Q3CQCmK_l0&+P2A1aZ2Mavaj z;O}_3<`L$Si~R)kUZ!VcQV=Ck47T-yZie4Q~jw_KTj5o z?m-Fgo#L`VVWI?(DyF!izqyoea*d-PfefD6fJ~eOhyrAw1pPT>hWOjD5WlJSg)91Y zETnI835H+@#>W0vqotI9b3cZ>)-=Y!?eo`V|}Hhv=at1+U`*2*Y`|wehZMMzsvZjaLGn(JS z?9r!1I@nlnm;N)8yYV6N=NUl>b&n&6VOL$613^SHtjff72ZFB|>2T!F_Ow*MC8Z41 z>0Q5#^&D1DKL}?cn6paF_B!?}O)}M>+QCPAXdz@@XO;xNkMM|l>4H)%d}A`K&D5G! z-B$0?rfTQ&vy0wNe&0M?^k700dp82fGa2-0*q1!G^Osj^)g9{M!LZnu1IRhBG;E*R zUT#%$9dVq6zGkCD@W=D9p2+jL`a`8=Ez{?=>S?C@afa1@Hu9Nw&7TFn>(yLRsfnM6 z#QQ*MuIsgdoAW|FyWvC)`%-n=zL>gB&57(dySFgxJyrsD;CZ{7-Ml-UGgwKf+Tt1f zabCzseY1((!)+$E{yN#L(?#d3S>0V7 zA#&SS4?vd+5I7F?_g0bFjJ2aari7Q_!|F|~w}m-i%NtCxv^uV}c6)$}CzMftz}I#5 zsCg~c4dbxPgB`Z!R_GmU2wWmO&?JK1A+plmq8hsd_H#$D)pn7y_ir*?s>rU? z*`J?`*;?3@YCAUWPHxMNjAPE+Mrr#oTS88G*!pQz;-{6&jhp}- z_wGpdgw=>(^S&Fn-7z0B`gR7btIQ!UI@|0hIA#uyxYIC-a(L#2`uOOblKZUX$itC^uzs%e94d;F37Q%~g2Gg%NqkS<; zOD-#_s3^Nv5dYY@@G>c+IK%D8VxR0+dq^I~Ew_@9s$r(KKLCNMjo&r6()LaFPDxU` z(}g+2sLY{(Bky;eA9S|GLgW3l_E)wq1Ipzu`Z`b6TiGP+9JH~J*N&{0*~zQ2#;vG*~n)ZlR)6ZR1y95VOwOWiB|lTRqJh;fXuFN<66> zrCj7DIq|3A^0z#6jz8ew(|)4KWzK_yJg2MWX@PYMPLzDV_(}5ZfkBI2Ue3qgUzxC+ zpJ1On-)i~q*R9>oCH;ZbsO*s~7S^M>k3S)gk1Yx$doP9i=^T$yE<9h--lII}WpxPl zHg~iOxukGfS~deBkHR}nw&bC2Z#UCd)eIGeY|~OO=qsC2*qiItAZmF0??&$4x-IXx zSd(jy>4%5hJdgEU_OW7SR!@Hs=cS%NKJ@dW7i?7XDg1`{sv1{-Qj;_NU%od@w2SaZ z|M>3Ys^w>RYwlSG{4jne8n?dptlY6Z>FAcjB`A10QWKM!URu-j$+S1uS1@r4f})FaECk3?Dy?l#KAeaURU~s99v9!m}h-s sENh1fInQCDH-7KRTs0N$f}b=e!p`aQ^wtZg<;MF*uzx7K+>f9BC$RCqr~m)} literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_camera.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo_big.png rename to TMessagesProj/src/main/res/drawable-mdpi/attach_camera.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_camera_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_camera_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..0acb5a3852f923a922bc28932d728716880ecb3e GIT binary patch literal 3929 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_file_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_file.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_file_big.png rename to TMessagesProj/src/main/res/drawable-mdpi/attach_file.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_file_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_file_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..4075c3baf89e59dd2261bd9db602bdd11426c4cf GIT binary patch literal 2057 zcmaJ?c~nzZ9)1BsSO&u;1feAaTM#56tB?{F6Lvx|ghjz6%Y(#_yhjpD0HF~bst78l zwjiJ~xYUY825<^9g9H#eVugYgEK4U)1gsW`G7Po0%!?H}e+=`^d++}4J>U2J)^qOB z#DpkY>y6d`0NBPvb9l%aX8J5GkpC5F&UeV-s*XrgCqbENjX((k;bKS#;$!53ERY8Z z#CbWl!C(L|CrJ5e>NIXVQv}J00uzR)mBR=d0D?ocus|dO)p#M8B~`EpPyg0Qz)Qs} zLMojbz=heML>is11e5X;_@aE7C`e2Q4Z#O%nTUWKR15H0dA35u)UpV#beV{4IwleD zuOMm}i||`eY1~9S8&ZOJI+5xx3Lum531OgfmvT97vQa2Nmj7uK0Iu;F?_1D9B;NGY3>k_k-d{B_zkcN|`BLI~Mwydat?S zwPRtd$t5AdkW7vJuSTyPA=6_r-;6D?c{BK+0-1ItGS;Y2`$7O%R~W+y=W9owq^D=c zZ+DuwH+VetWZie+em?h4I82?^(v0B|hi;}<+YyR>*boypRdMTakBb$d8yix+uz8ec zRgFIz;UwQ45qEu#pLJ`rJu3b}=FGS%bEf~yj@x~|R22*a6-*Q^wg3E8$og{wQO2@O zrK(NqqAl%a=junpmX5wigt%yG*Wlib53o-*7s=3}hpy>e4315nry`%q-JN!!%=A|M zsONh3fL+gi+PC1FX7)+(Tc0fI625jBH*3UT{8~REw%H%Rp0zk}uso$4Rj5B?aDz|O z8&`_Qe9dI~o_bQ8Rg=R3>-mM6k;yPD?3RXZ93HG=Ka8_OHMtN!)nD9hJyof_;%Uc- z$^dYo&Xs!X4M5)lzWqB2=8F^V^95V{8+%tp7QqQFBIpu zd~0w{{{H7S_f~nVHTUi53)A>thezkn?;4p{Ty9CN1Sa%cgF=e%G^I~uNBS(629$$~ zp8a+IZf9|bL-WIlo{3)A6+0KT z#3s3-G8j&EUz7p6OC4XnuXA=A9o^y;)?$lZe%C9k!xnwH!oIGr#4Nbd-tZ?|wAQ^D z_{W*{z{!i{W!H+i9$-sX1H+;2n|NkM{rTCytdFxy6h`VO6kqBoxHG&^b}UJZ{>CbO zdY!&@QlsJJE=2i_JsN%wn-~AU&`Z6)r-QHU`J8gNWn~O2eo&bHciVWIR{yu*^Bb|s z@F62^ebJZZt{!~gpl~ST^ajs`Dr^!vXkobY%O!R()Ys&F2ou z4q-;yhU)M6Ca5vJgKHq8IPi5C0svP>~ zk3Nk-xc6^$wjPjN33dHfN9WB}sl)D`4=-uWTRa`QZdL>`-DaaLPuk)8jp;fRASp|H UXh&-{GhNOx5eb~eZF`IV131?*jsO4v literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery_big.png rename to TMessagesProj/src/main/res/drawable-mdpi/attach_gallery.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..5dcdcf076a472bec3dd138b241f026ca114aaad5 GIT binary patch literal 2172 zcmaJ@YgAI{8r}+7Vwt9sT8(YdEK9BeDMf}NX$cuJlcQZk*d`@x1PsuQ8QH8;dFf*5 z7~U_LYcj{FRu@l#mQFKTI%8QmrRiC^x|o!fU}|U6WOII;&R%=(@3NlfdEfVYpC8}h z2=0b?m_-->0Oo~-vUte2-tx_{LH;%3q$kMWrVNQvM#Aw*l|T*wOc5LhfngHCE{F#S zM4F`A&{_aMVa5C?WfUizE`%j`fdzwCOJoQe0M-VoWdh+IND0P4yTnokcI0{^78HvZ z*sW9!ks}L+62ze?awsx|%NM5X5eA5`f$PAvYC0kyfs_JJElHFr=xPS`qb?npTeb;U z@FPUIhk^YosVGha7!1oHkc#)i35g^UNTcCN6e^8I@&(C65}80mUK)->p;Kve@@nwY zgGHjrMe%eVi~T7UvSMHplu8+$Kv1bvc$FU>mhU2v0s;ao8e}pKLEsb`sZyZENfn+m z3M@z=l#69bF)Rfwih?*eS;@d6nf_IRMD|%$s`zwF$bk{m0vUmXCt6CH0dhG1A1aZ2 zMk|y&=PJCQBfxa)vAVn@jy7*J1^U42jHw)AxAmII zUi007!12b*GXL;rnZ6qpBJ?kFjtxdhFKUZdMGL38gN(^CPZK5z7(CLbVJ?4w+N+iH z$$U?x$;XCoV(QSR5A+zO`tWtE`hBaTX5ZJojqNz$UI)A}c=omSMWf#4&Pl`AYpH$n z`>Ma`PIu9d=r_b(Vh((mU;AQJoy+8oi;$0%y>>Vjy4gTOtukPY9;VW4jD*eAMggNn ze_Qv^4s2RcH`6zx=!zXMu(Nr9Y}&0=)$cbj97-9|NT8+hV5`K=_3jEAxO8(&f4^0e zX>r`TXxqq!;U=d7&M4rzbLF2;cDMKy4c#csf%E&Vs?}e)t8o4AI`3z+8_{{v`6eIR z%;Fd)uDHd-9Fs9B*I|#J-^)Gxw2)bb_es!xHFHr#U8@_>{bs_zV_bGm=k>=^O(vPjF}8D z`Z~v$k*V!9UTd;{o9-^L9bOryA37p|Y zq;tsD&Xpy=Vi9^pDAVc<($;L%i1oC?A#K%-nw`r$*Ka#%Vv~=UD(B6Gnu(x!=4-~5$yeU zbI0JTuUf+ak#!4%cI`@A(@70^eBOQ0^MZ9`P` zOJKdIoaLZOpsvJCrzPd<>lFh1~&aw^{d!gUTi`V&1dvYPA z=wyZe_E$H;J)ThljvuNYRChDfHV?Yqv{y~7|h*REh5=GZD@z0*@({w g=X!QJr8UyZ25=;mE}w`Hd0XxSVIf>rZBVTCKm0w22LJ#7 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_hide_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_hide1.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_hide_big.png rename to TMessagesProj/src/main/res/drawable-mdpi/attach_hide1.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_hide1_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_hide1_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..8439f1f5e11e9da0e04102bf4b1eef4b4e6ad289 GIT binary patch literal 1841 zcmaJ?c~BE)9NmONh)@*}t5{eU5m3lQ2oQ+`k{}d<7!adUNK6)zl4N7DkRYjsLs}Fa ztTM^~8e4BH;!qT{2E>Aj6;bg(1;KLJqR?Um9jo1_VE-uH+1>A$_ulXPb_-%-mfI8N z5dZ+NkBs2(v5{qdY^<^OaoL70Y?zC31!x?Sf@(!-7zmXh>tQfbAxee$ut<`*;R+lK z02YueUVsXC(F`%7Ad1WwqE4a0*Z>e5qEm^)X)p?|hf`%rCNzAm9s*?&CbZh0N9L*6 zuv8YYQ4Pm!jENU-OcMu5ppa!?u#SNVC}30s>J)ONhM{9Z?{pd1+`LVKz;_TdjS0PX zO2CT+*@zkj{fU0QVlssS(&H82As!3U;=0lpWgpqV26^TM5n?sra@_7FbRVXIW8k7%z^!Go7 zHSw7$n8b%QNV-~#6)wfyY)Zvot6>p}sN)etK9R*(DS{#zDWU?|adgmYwM;2Nv>NYs zcpi@tsnnn%r5KLnFdP7OTwHX znG5@`LQiaA-D93kwk@`pYX^wQz3F~70SfaE{>Qf`_w!!MuJjdhN8W$r{7zKw<6P_Gvu)(Pz0 z+uz=>z2eN!o8R?S)`>Wx)j*EN>oddMbE@3*(_iFxFAXmpd**cl*d<(CJNMu$rPUIT zlPe4}E<6y<2&{xHds$9$i?QtKpWQnqaRoxM%e#X{Dk`%Y~|%3PbTOuo3lde>`W`!Y`-oSP`xMPC49m|V&Zb(Hjbc4o}7UBTQ21SVe-oh%*A zE1}T~Pc`qdG4upU_x<4=liIeg>XV)1#~GH1pBP3(0H)&e4oig)uG#K+I&BDF zc*SPq1`B5mTk2Ac03xx}VW9J;tr|*7_8sxCQ=39oyB3jL^ui)wY}L&kVy@*Nf0pr5 z(eA)2rpvYs*V`C&GmV<>2C`p5233+^c4DX%)4ATLc53C|iYvb$Q~`55vpj{Kc$*`6 zSBuvy%Wl^5{pYsqz;C>!_cGvrro8yc(KF6XHI2t+mDNula4A1{v94|LiN_Y5lm_wa zN3++ef+#ysX*2Ef3caJ6%FdPhAmr#UWfXzI3AUFJSu%XcLqO?9LL zr9elj>Xk5u;4ChSJ{Fu5HBv)4efwEc`K7B!{u`T$qi0JulV-l%MDt%E`0IRqW=G*j y^sVJ_XjjC`Qze|O`&;wpb8%bodGj}0eF`LXJWu%BBKe{DCl<+#;Z%kRbN&I)Ho_bL literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_hide_big_icon.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_hide2.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_hide_big_icon.png rename to TMessagesProj/src/main/res/drawable-mdpi/attach_hide2.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_location.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location_big.png rename to TMessagesProj/src/main/res/drawable-mdpi/attach_location.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_location_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_location_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..1c3917fe0df9c139cdc4b56677abd6cb54bc8281 GIT binary patch literal 2333 zcmaJ@X;c$w7A;m01Vn8%ZH-}*8OcIIFhK}Q!V(OGfCA!@kd!7uQZcEJ7&lN6Xu(EQ za1aDU5wNxCW)TsDR%sU&Sp`7}pd&~tnc4CV?KgOw3Ro`;%z3+bSy;G->7y&+p z`j+|t02uoDQkbgIUH$0ks@}!?-F>RT0;Yz+!O#v^#ukHs2N#M25q<*pPLK(*xqEis z2iF6D7Lp$l28Yo%kT{S4#a3fba)C(227vWsxroh)0%1fXxRWn*MULI5MI!iIS7fLY z9YYs+fjqviLJS5g0zx>7C=QW}B)cKj%SkE$0SL1ZazV6ELXx{8KkJfIbM-bFiTDhG zqg;`HnF^yb5MGcNL^z>v4jc>?iy#nCSiBQ~fL)7l#9$rK7}ZU1z~V_x1d^jO;>(3p zMH6#(keC$jFR@fBS0oRHMIVS=#A;rF z0!lbyz6j<+LWEk89SKQcSES16Uq=v#zRC(EU(%#X7+TI2p|L28`bhIYI{p7c1%j_= z3Csll_WM7DB_Vr6AesqEAgP$6D%=h$btnDRVZExtBBC{%U3Sk=}hge#u_K<9)X#Un)C^C}{0 z!xri?w}>9kJ#Td!nEK0#)63``nH^`Q5(IoambF~4;U`O^E&X7}Du>yD!)JIMYchGo z1X|~v9z3C-Fwb~d%0t>uJrsAAL8W`#Yt7MgFnrsM1GkUw0A&r$PbKeG?oj(24re=2VZ=>n3CO$SmTR_7 zx7uitI3{K#C&E8ABaR&RU~x*0{rM|9xxGL8ZVjT=ZOgSN9N*lfNaRJV%O=MrSdD5A z0PR5`TE>)nNjaJ;6RgVOvjOv3qxzw`9zErKQrun-Pf534?8Moi4qAelp`*25Wv+`x z+q42<^I!^Zw7XYlp<$H?@T@C;+VWms<-ki7ke!She*sik^3A{Srt!JCFR z&9r_u2-m89SY=!{Og=Jr)BK0sw3eZowf=yigLkVYw>~Vl%Xk^vKFljyBd|Vq!urEU z*cS)n*KQfD4Zn76dHW>KYcmS8L*>sL)wW!*s-WSxTNMwNwtrW0aA%=jA;#c+nfKuZ z>r#|eWr9*e3` z=14D1O0WC~g8g0?oODfiG+y(7418-9;4OQSCT0 zK5ti3VDp9Y`*Yv-nFKqWc3zpcKLu(ZNH;E2&SWSR^%mDeiy3-nHx)MmrdO5+znL8? z+I#atY5I2lgV&jJecZ7EyOg{9MyG+URhavV?=*$aTPma3nGYf1z7bv2%tztMQYJ3( zjJ>~U3H7P-<;AHDd95}+-9vrLa}OMfdz1XgXEH>OMSS^7^7c2J>Nr}caLRBXEtC;7 zvMWcqV74qTsBL4+p`;a-vvmGyEn{kEZ^~>UXnQeSZw`2 zv`f}wURjp6d^d!+LYvHH{CKs8P(wD?(XcRR*Q%JvFW=aeXy3AgbyhaFqK}-GmI`lu z=Hk=T@e(7E)|;AWHisX`Tlnr&K~&(|**ao(m&#d$99ew@`{}~I>~5O_xQ;u1v3~J@ z)uk6FYm_J2ovy-7t)rz+8frGi$NFbwW{*#g!Cg9AYg_xMhMTOMHRv8oW4pt%E|p7m zk)fHCo)tA7o%_r4kM>R*b#phR=>Ac;cY^uBuJlpSXi@&qxc7xkac=CPTpK-ldVid}aUVu^VWGQn=lAPQe~b+b zI&~*;BImd1HpVUXL8kY)=ZAS20gpo?ZQM~hSgo}|(bdBd{F2A3Y5sLl_Ki=ii!7`g zoA5;Rk~y=av`pi{JVx}e^9j4HPD~`MEa;q0)l0QblvKDr_uDdRoIl{%W##!Un&@7& zq~GRl9CGr)uf0*Z1L~{Rt>*(S~~<&e~^lHQq+N sziB{ZJJIz*{rO8=in+9KIwDpB5C^_bi+`WqqW)p=qXtl}da@4v32H#pg#Z8m literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_send_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_send1.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_send_big.png rename to TMessagesProj/src/main/res/drawable-mdpi/attach_send1.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_send1_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_send1_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..d8f4bed391f78a876413ac542da54926d3039bf6 GIT binary patch literal 1840 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png new file mode 100755 index 0000000000000000000000000000000000000000..df9cc8f14f474c02f6e386cc793f32520e101395 GIT binary patch literal 1552 zcmeAS@N?(olHy`uVBq!ia0vp^dLYcf1|-9GYMTQo$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`Esl5o8tgrvEOJiVQYVmY&45_$v zW!72mkU)uJ{nI&%redby`1firi#z`?(+&{sU$=SneM%x}m!)L+459bw~XQHaRhg=WIJz-#z*BMntFK zdxF@U8(bCB*6(L?JHY1AcwF&*P0#gx&mxp%cB?${KOj|c@?~LYXYm=+YdefSav3n% zHHZc8+OpvoOSYJ5+-dt|OElvrt%;Nli`jQbe!5jXeicXKd&{Jq`ymR}>n2*mFoJ;&@W%W;0 z&-=rQLi@%4#14y3KN~ca>7&-JdENZdwvykLd)U6zhE1VWqI31A|?K1DG=ym!irN3PI`V_D88okGh`ExDBKK3|$ z?CE%~EplJ{V`=N7*K++#Tb}Mdo@TPzBP!;(%O3$9Eg|vihq>g8zc-tE9brFmHNN3q zqcZCy_Y&Lp4Nvw|`84jZ__y!I)BQ}D?MpA0>?yIC`1DUU7$!V7bp@YM|B8SudSr119+P+5}W_ZS&IDb5!c2!fd;#KTp;?Ejwtoe2>}5jmQ2jwaGYSciR48jEK@t^%i?39)>5ubu&5d RG@b^P(Vnh;F6*2UngCc>Ob7q~ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png new file mode 100755 index 0000000000000000000000000000000000000000..b2352c30aa1e37402e2351f3ba4f0af8a6c4d491 GIT binary patch literal 2002 zcmeAS@N?(olHy`uVBq!ia0vp^dLYcf1|-9GYMTQo$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`vLFhHasTY(KatnYqyQCInmZhe+73JqDfW2&$iOVgPZmu}Z zgX&Gear1O> z45_$vWtOLpNT5L5>gp;n!5I^MC%XE^G<8)8OcYow#DDK=)2tmWi`Dh3J}hImtiJdl z&%@(L#n%T-yPbS`xQTR_om*T)$5HG?!NbX*{=A#sR4X< zC0V+)+`<=}zL+V4;v{W4^7&*ugF3szs;{qJ(0_+Fm9 zhA;CION4hZ#`g1dFs*3%ZhcYxqWp#F7pqnF?>V+{`i`}e?|fU+@ZNd*!t))FIh8e*FLj*wZq^0!A_eQSqbk#4%a?A)pS|8rdO|dXSn3|SRJl; zt#y5RO+SMLjZ-=s>|MkU{8`-)>C+fI^ES&j!HqFL<$uI|G2Ae}&nVifK+Ey^!F{{t z#i&g_=)d4|4$r*fJ)JtAmAaQbP~39f>vZ(AoeTCH;9Xtg7xBpRNs5X!mi5!64|?bXiWzO$Q7%%wAXkIs>-*yif4fI) z)0W?S?~1XX_SU&Zx>KL+d{7aow!~6Y;+JS+dn{vyEZ3vw8A-2vgA<+Cajy!iQcyq3 zxZlap;{GS$d;DJM{{`22aMozny)fTwH^a<1C99ySU7zpo7IlWN@6{4)Bz!CL+q_$w zmv%4QbV9h@{&R{*RlQg0Jh@c6y&bz#7lig$Y_hcF`^&RXf1jLji(2o)t=tv-cfAco zR%-=GE?=QFwOsGf=0ic^YtEJ(GOw}C+aqf(>;9eZ_u>tF$uCVOUom6SpV)b)?`m_& zeq(|9FKMpd@4f$W+&)}nSL#7;jy(Ztlf2|!&OM@VIr)p3N{GjUn?@7k)?5zxTs!wJj>#%Jc)Gk)lzNa;@ZR&$Z)W^Cl;!onWdX!;FoOpID677)emJ66wh278OwRv;Jl}1L+wGHA-@mf4PQ3PP z+lBC%XFqWG*}tpGR?bM8S*DY*Wzu@5?>8BC^+z7iu~;jiebM$a$KAs`hm{^IIsanq zi)ob&c@Ov5OUw1o&~SWev-#Xqz2f=*|2(~MCU2^jz~2R1_+6P000>X1^@s6#OZ}&0003ONklM`?*zKQgV2U@VRMTcNO;NcG9fenFo9%0cCwFH*7(6K zt>efScEB8)rYD=S5cRex@cb#}_#VHDb(4OIcx;abqugk(BC&ojWc}bv;=y^K@tRf? zE@FQtBm?;1PXQ>2{S8nZf{U*I01EkVYlYwe?z8}uN97suGKwg?bV5+Ej5@Boa5MvQ zd2CZcvOF*VLAwQncZJM?ttDK&Dwend?lzHROqFJWmK^+h)ecMl-(B zKXiI=Xs^OpJ@u3mxEt*!*tmkuexg8=Jwgw9J7Y_a9~unts2=}wTfuTI;$0?eB8?_; i?q=nD;BAE)l=TG?Aqra%;-qo_0000O=~G=WkJm z>*?YcVsSe8$9V^-6p5=FzS!Hh2?-on`SAb$_Wy4^E`Rv{|Nej3|B;>-8JN=lXHQrL zlvw}Y*z+<2Q}n;?iOUj=HKq3bJFjr|@~b5*+18o|e>H6BP`1qMd1moOfPqJ$V?tQy RCPkn{44$rjF6*2UngDVbP(%O# literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_action_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_pause.png new file mode 100755 index 0000000000000000000000000000000000000000..b4bdbb558816223029dd7cb3ada0af2c70b0b0e8 GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;Lb6AYF9SoB8UsT^3j@P1pisjL z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?b7_Mk^G4pGl&??a>Aa9y+WkF!G8?TgU#si*3Q4j5- dF84_^GvvGoVElAI_%%>JgQu&X%Q~loCICj*GUfmP literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_action_play.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_play.png new file mode 100755 index 0000000000000000000000000000000000000000..164385d047ab7a9a86438c8abed5c3d570e72bdc GIT binary patch literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k0wldT1B8K;Lb6AYF9SoB8UsT^3j@P1pisjL z28L1t28LG&3=CE?7#PG0=Ijcz0ZK3>dAqwX{BQ3+vmeOgEbxddW?vh&p4JS^Mgk1HXrU_zC{8jqT z{PTWxZf82vLCc4&|G2btGakEVIWQQ@vopOoDZ?SA#m*#gLY5;;N{E?B;_*TYc0vB5 zks4B6+7}Wv);Y~(^gVXfEGqeia;xBpTO3O^DRIXqXId|IQ(Jsv5r1v;&;9mqnHR|B YnruHl@yODzK-V#Ny85}Sb4q9e00~rBB>(^b literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_action_previous.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_previous.png new file mode 100755 index 0000000000000000000000000000000000000000..97970e08f11de79a9239aca0c828334987b6c5e5 GIT binary patch literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM0wlfaz7_*1g=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&_}|`tWO=~G=WkKR z=;`7ZVsSe8&v^%_1f{^g23J1JXEeU>LvmW;ipInLfxumKc-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>TKz1;cRGPU|?=$Xy|I{Xk=z$X=GvSYGz?+ z>1g2y)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GS+A>kPy);n|2$nBLn>}1 z{rUgjo>`Ysn7NnntZstivnf-iurRHZbkK2IR=K{>V(aqd>B@TY0ZA4d9ZVl}Y8+ME zS_1@?)%ofe3dICIGaA|pJZJdmKj|?8zXns=>k^fJAqh2xOfOGf@pARv(4o65%_vnR zs3(UzX=BIHU}L_jg^BwlUKLGv7<*+)gRIoT$(pB5vM{U&sbNm-4$$V?=UBWBasU7T diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery.png deleted file mode 100755 index a530569673d15792fa2f35861e37518400a7c0ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1131 zcmaJ=PfXKL94;V;Lv)FXpcrd4@lV*gj;*qW3Zoq|b<0u~LFHiAK3IkJmGhRz*&`c0z zl$P#B-H9Wd0(HOaV*HM7Vm3iEw>YM(^aDg@K%Zvt)aQp!C{j~-swUUDzi4-Y73y@)d zqfZGi49T*7CKP5_rhyCwm>?a%FY9AMT$ts8`^n{p!qF_Xmy^Wy zcrMYRddpn3crI;4xin6Ob{qRwqYGQuJ??bHws^5(d|+U=TiDj?zUC+Km3S8yqiN@D z=Eve*0AQa9T1llssjWwzbkJpcS#>TsPr*U&WkvgFh?;gb6Ox~KQ?bYFCz_sPwf{H)xw d`&B8is+Ra-OYsep^X2aKkH?bYy|$C*egQ2&ZWI6j diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location.png deleted file mode 100755 index 193306974c11fdb1a9e38200ccb4ed5ad78f4e44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1261 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`Y2@T$X5i>-X5nIDXy|IEh<( zWNGdQ)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GSzoH(^n!tbG11e-F{I*F z(x3nT?U{8Mg_(O9xfNMeRaGxJXo+{!Hbk&$)kt@2XZZMJ-n@C~KfV}0;#OMl@S;PO znn3a6fKRL)!Hv__DBNUP@vz%5i=#p)#X&^RdqWfh@3h$!F@1b?%p0XHOcFohR-`9( zIG*{Vi^4pXBl#DeR4lCO@N>0`;4x>}wSl4Ivty3Vv>y|a8o8wEB`-W!ZooI;FN=q+ zd+=hnF4q4S9(Q$A{BZAL-G1>$;DL_mj$SN93WiKoAJVqeI;?3wBF^~evqN*@K_;UZ ziEgMAiaF8r zi81IF`&4H)hwJvsyry!RY6x}wcPdmdY!iOVtTO*eqn5;ihm$+69=3QAEy}>i#xO0m W`tUI^D`3&Yz~JfX=d#Wzp$P!%Zmhxp diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music.png deleted file mode 100755 index 3440214d1790323c77be51ff46462ae611d4ecc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1102 zcmaJ=TSyd97@lplqBOSjq02*uG3Y`&m%WVc;AZR0rVFjC>qcr&&CVR%QD@FHb8JT+ z?PW~@@gWGJ+e6t)4?z$FNl}DP712w*2!%v1B}GJpc1B(8p>3F%bK(2G|3Cl#o$*XZ zTkV$JTPTXEO|{EeGVb)g%^S&ot{DGGhFv(>jk{1EE-E&p5*o@wkTR5hn1zZqa&8tj zQ5ctC&#PK1PBd-wTBVtq#Lychdp-D7b>l3r`vDH{)6{iarTO!LA zi$$gwW{};_^08RV(+Guv1QB#bOsu#;(`hIx$k0)3-NHIDfv2eC(J+qFB-5267}lDs z>8zHC6pVEhi{%;4J5m{#PX8Zj7;9(;XW@Fj{}gs|BNk+{&_TntN*dSK;Dxe8$%YC> zb`GJTauqWLgppG~7Ld9GaNwkFYN+TOT*jx4$zsj;&?IiRiLLMV`1g}5@iZkTa_+nQ z@1>;{f6!OwzvSD>j89EX9R*Q;>3MtPTQqRz$M^3;`#$>ZnoYh=a4mT}Fy0vm<*P1~ z0@OxdL+|9`i#@ZT`eFU+eN*GUXHBK~S)A#yHkE=mpA1M7O{MDFSL-rAI(vW4)$~?{ zJKt{zM;=EXTqtaR^>*Rtulm3#YN2)D)Qy^FZPQmSp6;3y&+JeWhXOP7o3FXCL{;!* zoIYwPE4eY`yV>3O5DcXH3X>-#W?PEb`lsfp{M#Zmk@=H2jAvO~VtdUos&v>IYw diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo.png deleted file mode 100755 index 9a70e6b581c41fdf9492cc3d7f8194e75c1a0297..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1227 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`;%08)WMpb;X5nIDXy|HU;o@xSVrJ}OY-r?Y z>S$&T)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GStlHIIn2PoXz%Ib7*cU7 z>DT}N_RPA5!pyyl+={HKs;a3DtAyK2BK`gS&F%jBu<-aFOSa%BVY;gFz_?jZ#4q45 zQ{xpL1+m2jA#u!wS{Kr#FV;Hn9(HsP=}1rHRx;E&wpJpruz}?o(?(r^VyBI=0_)Y? zlnup1m=7DXc*wIRu_{bsf28cNQ6WHU(UqpH4$Z$BI2}Y!?Bh6cz3~T|z%DO%p}!!CsPrkDtmve1*}1O>b9vbP0l+XkKpp%Ld diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photobig.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photobig.png deleted file mode 100755 index f4a9297d44b0c06454fd7f44af3dccace580149e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1376 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?)WFcy#l^zHz`)$X(9qS?(#6%q+04<{)Wpod z&A`wArq?AuximL5uLPzy1)k$J3;}uUA$B>F! zZ)W&H02tnq?c%+?jt*rZri zE~u5f@#tHe1#^41@m=ZSbQPNq2X-EwIrI9?=gDsF9D>qn(%rl>|8hHeFJL>Oe`1E~ z?WVK?swc9Jq-mDjdckM3($updJ26kxU}d%Z*9M!7JXVMH?Y*@3QC-t1r5f#G-o8ui zRtaWL4!vr!EMLggwaVLSow3}3^}Cr$FDyTGi|M3&eBepN*z6{u84>}SpKd5t819&t z9`yQ#ZNycLhp7eWS|?1}qY{`+GUhTLSMYzWWx?9N#ji1X!-Cn)%luayNh&{ZyinC`dl?Jm z6U1#U{$e1-sUOCUU)RO8>G#&j_I~L zymiS%9_E>;tG2FudG*D{(^*4+%pU_EsfP{BueM3o&{*4MKdNRcS)mm#OOw|&bjgd!tH}ml zyf{G*-Ua^y{{aso!e9qMufjm^D5wVy9+d5+Yda6t@bZ4~`Fy@V-;?V4>h#p*DT<<| zD{HDw){F5!d4|lNL**A)F5%?{-b5`N8a||o7HUFJaf~+9p<(UZKY)3PO3-$#fg9Q# z*+dRYmJi?}^d?E4-vkNh3!nW-y^!L|qXkc3kT^BW8^UAPeukHG9b9cRF?smd?XVA2Vw(6&bAxKkwW)%WwMX2IU4jKxU0}7PBpYDC?g*NkxeruF9<-ASRo@y zl5icQcp=5{WJrvVkwr;PWx?R1i8bG9$-25SutiP^-ND$CIW7!CHcYd~Z*xK}my0!0 zDTW}JV8_Kq#JE9nsG!2Y^lcB@$OW;Y(L_D0(8SY|5FBqL>jr}~k%V!P;c)`X#~}@Y zn)ZLFxpptU}*@0Id}tIiMf1Y>)RPGgfcFwZ{7*j^%R187?mD zUxglCk?x7NqqZf7QR73Gbh}U5x_ag7JMtv-idw8ipPIjqjtU88;zHut#Cv9|IJdC4 zIPv)I#>PxCb#?A${p^>S7c(ComL_NQtoQuf)a{=?uB{$+=AZ7r?N57qiT#haUd~dJ YJoRV3aPQ#T;raN*RhHM)SEa2-$IOW``Tzg` diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png new file mode 100644 index 0000000000000000000000000000000000000000..befe821c8de7f63b7ea14f7563b89b23ae59fad9 GIT binary patch literal 1063 zcmbVLO=#0l9M3i!qf&GZgegkMJSf;CFKx0mERN=*u3%>AI_yO>O$n z+wkDdg5dP-!IR)Y!PD?2oM)5DlxNb=tMzyI&||K6-DUQVY@r6`I@ zmlyOZS&xx#a$=nPM^n4oWSPcB9WS9K?ph(FiVkW(y6jmkScR6eetQSbQPf!5t<`be zydvAkW35DojlF=NDQa#$4lKI^G2MVI*H@VDuU<2>>nO}M(d5lQgKc+VBZNyEi#2Sl%3PzY&}&1P&K09uk* zkP{^dT%-ja2pmsdDFbq{D9OSsJ$M*mEp(c4RWA)}k(0u-F%D#o>vp?rH_M{1#eqVh zkZ=e>hG=A>bst-C#*b!(3_6VL&<(JQd^%yY8fXfwxgp0vSfCdSAPPDtsH75xm^TDX z&(88WwPP#6sRAs4nubhI;9YKbT7lQdw>W3j=Ya`{wHf3afVCU!v literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_play.png new file mode 100644 index 0000000000000000000000000000000000000000..6d2ad6b3fa78493fea00e28b1df6f4e39a949083 GIT binary patch literal 1131 zcmbVLO-K|`9G_G|EUBO(BW0S+P-u5%_G8=~c3pR7c5|W8ZCz^VQnNG9-9hKWnWwvo zK`IzVi9r_)j7U6ssY?`eunrv-Bcg-UAt>k;UA$?%ab4>m1`RXw-uu7*@AvOoIA4LC}hK@)gdQL+FQQ;ZzIlbVzVX&@=1LvKMC z!)gm^CJVFTB~~^xkL2ihN}7q#7#5C}Oi3O95YK_Usz-<)FJ2M2szivZ0g)0-9u(B> zF$?sK^2%pdnwvWQs`yew4V(ythWQ-c?e|9Qu^7nkl3+>P7$I2p~;eD zu~_sJeICQglXNH)ayYzRH_~w1qdJsIZryfO83bUm*} zs~wOk7|^f_hKcii4BjS6vZ_0RcBep#igL1(+${OGVdK0rq^W1-=AKi%>G4c2^8h-FIaxeuQ*KdVKX;ejGdA za(&{tT`)0%r_XZ(}#9$|&MG5H&aE^3Sb literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nocover.png b/TMessagesProj/src/main/res/drawable-mdpi/nocover.png new file mode 100644 index 0000000000000000000000000000000000000000..abbedfc21befe23bf2f1b3f1adbe0b18b0f716ae GIT binary patch literal 1705 zcmaJ?X;2eq7>)u3!9WTs3Ki4!C;~Y)kSN<6l8wn?5`+pmbWki* zu?m6*A_W}>+bWKTl{)Gm*dj`8BaVbA;DJ^Ip+o9HHwd&pN_Tem`@VOc=XuYa-5nLN zj_B;=Odt@5k}y#WzVd93(+BuFK80k#mnE1u0gFY`F@szO6ZlFr4JJ#}@(efzmMcwL z+h8_XKD11kpoQXLipZhrUB$h2&Uoy z?}JK^Mv;Z64kk0HffNND1j#HG6%1msSYQB|K?fN$I)1Y#U=YM)L5wxzsSCip>6GbE zj3{)<7k=UZnHZ*pXf%VtKs5wXQC$WN3=R&qX)qWR96`~WG??5-(dd^?D~MpdLWgKE z1l5pjit;ox8{+_Yr0-KuYiDFN`l&ME1)~||S{g{D+fteaN~Qk~RjX&vdMpP1C*J=Q z*2_#7It zWJsluM5D*#8U-v7aR6L{iXcje!J;$3V3rsR<_kek%v>vG2t|Qw=s^O$SQsjxPjf}6 zB3lh>uxYOHA8zQZT-z|HwYX;ytV6cJ%1|AuCQl{}A+yIKoK zkrpj34fPBwD*E#ATz+3;wTnx$#xLMfz&w`EcUO0Y7uEMTxwyFVz1&xbR_ePFGXWn- zW6^_e;?GWGxHdfErguai8LG7IPg&KZkLa?nI}FKX+NAhR*BM$;faBMxBxRftnA0BO z#diE;X={`9^~u6Fpf+T zT0y^O<;_TUfY%{<*Gw|i{L1x)O&|#MPb}lWmQgVJ`1~=y)}7$~en}3;=(Ngn-;iTo zue%xc=Q*As1pY|u`{|LNTUq*G^K<*@9Fs?Bq$&q|8d zTI*6N#+*=*89zl5F0@I$nUWbHD%FA~M(5M4x&B-KtpZo}|+vR(GR%8o1W`jq-Anw}Dsoa}VCVz;IC7w2IX&veBc((i9}aV>~T-Q)cD(4qr}Tk=_9hBw)F zvmg4z84G$#Mjn}k-YpkS5Z9fqQ6rlVbiOPbY*>v(?!D+cW_J5|$TQomwEfUC1A9K- zuKG8l!~Sc`Z|~R7Q+3uU+IGA(>)R~_7VCME)yKn{A?QC=elvvxSh9e~Q)ddB#^vWn z|5!D$-~r!1cDRp(2AwLe9DLH(Ep2~Lm{eBQdTl&zG~=byM}^~xF5aKQ{5gc0R~7bc Szu)KDejXBWgs4G~y7O;-5}C39 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png new file mode 100644 index 0000000000000000000000000000000000000000..017c16f16302e068a55681e0755d174846aa9016 GIT binary patch literal 1550 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 bNMmhd*u}@W`8D=)(!I}OVn|qxk6rr%*0^CA literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png new file mode 100644 index 0000000000000000000000000000000000000000..08df043ef20ffb6e1500ed1b8d0085ce87a747b4 GIT binary patch literal 1166 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+hnVDi`Vc_a&VQFk;XzAo)Xy|Hc;cDdUVr*_;;^gS+ z?B-+u)9aF-T$-DjR|38Iua(|ZvxVIN;&@Rfmqk-^i&F{I+w zn``^|4hD!EFU*ywU|4)pNl0w6_y;yw9<#8_Jx-I~^@=~>oS~}L&FAB``fO6jee0OX zEn(8`MSh>Wr~iIF`SR`AR-Tils7zg~z^dut_@9C6aKXXkN5B7>zGXX8n|Gk*`Q3`| zhf8gX5llr0MG$(_Kvq9H`3;mr@pn~hms3^!j*uwAiHWWq|RPKUJ~u}mkfHOM&f zE@|+Y$v4w)W?!gkL(WWN(dJiPj5ocOG$?&$EmA%nDX#IHW#|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+hnVDi`Vc_a&VQFk+XzAo)Xy|Hc;cDdUVr*_;;^gS+ z?B-+u)9aF-T$-DjR|3Q!gkn8Iua(|ZvxVQWW(>jE>yA5Ry@kcwML zfByfsKb*ki!_&;uW0i5maWS7%AzzZB+r(3C{N9Zr*XA-b_AiNIxWcVp+4xIxrKnS& zLk(xfj=Kq6MwSZq_)9|A1vc|dGhqpe=R2a_(056~r}Gv^$9X2%sg^T}B*g{%nXR(8 z1-f~c<-F%TGQF|ylbp{}0gV<1MOH4ua|c5Vnl4?jT(G!@J=*hc{RWE+DGhce?DKSurr5F)237qV1BvFSa8`9oo+3A?eb_=oB zavZsjPmprrZ?xchF~PZc;m?gc9bYrwN(dy#y!GmbdaYDIi-E&{VFiPSz0Vxa!=Tc^ M)78&qol`;+04M=@F8}}l literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png new file mode 100644 index 0000000000000000000000000000000000000000..1bf3d4abf148e07abea2c9bcbf8d60dfdb3cda03 GIT binary patch literal 975 zcmaJ=PiWIn91aR@&TXKFfu0_jh{Bq`Yu1LwE=|%cV8(1K){|z*TN}FM#pKmyMK3!| z5n&#@dGbCGZ;Gfl2Z~n_Po4w?&oTvHy0&^)4N2a6Kfdq#{e5>=SC*zG&P-4gHDxaA z6|$Zp-^}?D zE?xwML?!}0#5PF$jUbj2h3@IfWS^Q@8uTEzrO*dK)vZ;ap$LL3BW4_q=Yb?K{CrlD z_&FeOyufngl`{OioRwr@0rVf5c#GV1xuTc*zQ{?Tn;3^O%XT^)rXw;aYOs7hpHDRe zAwv+Ecr(Cuk_qD3fr1WWC-OqR?Q6auX( zf%BH_ctL8o&|_GZYz8s50|%PALK6+f^ITbwbiHh7WjY*Bx?oZX`Dy20tX8br^ZKpj(cR4|++<-XXDYIaLrvQ5~t*=ei?f(TtH? zmITA5t^KFf0~48_bUPeeau|+249L7kWUzC;CLWMWp_;l{OFn(S&refe^2pQb?{0DK z$?mz2dnX?*suc<}%_?t&d QbDz^IW*RH{Zt2F>9|@i^H~;_u literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_pause_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_pause_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..b8e61746fa31301c0bc8a719b3430de6977de8ac GIT binary patch literal 977 zcmaJ=KaA2)9PS0RroJtk z$YG2K!-S4U*c6q`g`Q#dAOl26N`Bnz8h`q0FiZ?)x`R+{=ECxz}}?8z)U91fXbia~ydPL0U6;#lfDPA#Wlf=p24mZnEJ&JGDrzY{Q^@mtQM_CfR4uj1r3?9@S}Jfe zu7=Ek16@4hTF2bIe(6{eEtK=gGOp=!E#j)@U^`=~FaV)|@E=z)8qt^b_ z>Y0hmPqdv6E;-CcAG&1TeKOd4ss0YR6lz(^H^NV?#?8auS7Nc)a_r)-rPq&6e_Xo$ zbGvzB-P`~C@XK!NVC}5f{cx~zuM|&+E06QJ=lh4Ro-98d-=$(y;>W44-@t>n(IqPv KE84Td?%p3Ai7@;C literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png new file mode 100644 index 0000000000000000000000000000000000000000..31fce9bc1a0174d3fbf722df672d58ac4cf61e30 GIT binary patch literal 1148 zcmeAS@N?(olHy`uVBq!ia0vp^qChOc!3JV=Zu0c-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`v0qS)!cQJQ$HMGE~7nB%s3xGDeq!wkCrKY$Q<>xAZJ#CeV z+bt$I&4cPq!QvLEKTL7z)dxC89~8AnQ4JFUrXLU!o^XL2c+yYJ1E%*PV8ZtO`H2&l zDc*UyIEGZ*S~Jy|@MQcnsbN6w8#*QyaRlRzVdzzg2FC3gc z$>ZRnpO61Pa8~-{v9D#v=4;!WI%D?RN@__U(JUE6?Fzs8ntB zdD|}S1r}cE`vTYO^kRMfDf!+57QP(`R$Di|VV?J(ZPUZ>l02*W)J13h-nPw(*->xJ zw|w&UrH8J}^t*RpLRCfh-oScOt?SZH=Tzk%7s=N&R;`ZKKKp6gl)wf?hQu1Xia2E% QP}#!Z>FVdQ&MBb@0DIzzl>h($ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_play_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_play_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..d8ca3eb74c9be5c9b61a37111f858c42b600f3ed GIT binary patch literal 1156 zcmeAS@N?(olHy`uVBq!ia0vp^qChOc!3JV=Zu0c-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`vLFjeHsTY(OatnYqyQCInmZhe+73JqDfIV%MiQ6rfIL(9V zO~LIJN1S@~fsWA!MJ-ZP!-Rn82gHOYTp$OY^i%VI>AeV;u=6bTh5|FiH%}MGkcwMd zruuRzYN9^TwQzpwD4YnSxEfeg#Hn4_oxbpnqQZ?a#S5u#F z^zt+L)FaOI7CCm-8J)CM1TvZv$9nTQ@4vAmrh@L?q1H)xO>Mwi6k(DEOPjJMWVYB PR4#bB`njxgN@xNAp!Jb> literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png new file mode 100644 index 0000000000000000000000000000000000000000..1b52aca086b032402f0a40d657cfb96a1a51996d GIT binary patch literal 1182 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+hnVDi`;bLLvWNzVNXzAo)Xy|Hc;cDdUVr*_;;^gS+ z?B-+u)9aF-T$-DjR|38Iua(|ZvxVV4-T9b{l&6!3I$45_&F zX1XocAqN4s-Xn)joikn{=qRmyFlukZJcWqm8@35HosPg$*JTn0{F+*q&0lz3u+h%bRp`-?`t2 zKP>aDkGo&MAofj*+e}vtMGw~5td6~(A6NMqux)c(dx+oEK&{M&X>w)@!^&jsEBZEX z8#xuuWhMr>b4<|M=J3q_^#$=6X4~A_rg+WuUOiKyW7X@nnNK=)o^IH+nDa8@rz0`z z9NunZyVbe#ZR4j424{B6p7D)&MQX*i7{k8;0pe?#pS{pr|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+hnVDi`Vc_a&VQK7WXzAo)Xy|Hc;cDdUVr*_;;^gS+ z?B-+u)9aF-T$-DjR|3U~_e{d2C&Ch8E*Fx7&S=f}%Gq`^VOzwS!zn?V9pewYYf?Ly z6l;_zFvne@$+2K|v3!NTOr80ijhj#Z{p?#DYp%FbRrt^>p&%!(7w=oX__I9~U;g}M zWk#y$e*K3(c@jV7sDG1mTIQ9r@b6YhE{#b_Y!^O%epuyV#AetW^rl-%a`Fw9i9cWQ zC{9vV3+S)Ct^9eyjn=80w$2?(It6Fg+qU03F{M*eBFOKRhu7HyPIGo`+df&xuv{`o z{Kci*2IXf(u34@k37XHgxu0rWw*B$Bq*MG$j@`Sp>F5<_kGGv%JP*|tIXJ)Ks@-L3 z(X~=yVwAA!jC!NE;Qg1pJUBHKRlnSN$Hc>+ChGD=>9sYmFkxWuboFyt=akR{05w3A A&;S4c literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png new file mode 100644 index 0000000000000000000000000000000000000000..c62fb6c859e40524f4c8176603b9c409de65612c GIT binary patch literal 1058 zcmaJ=TSyd97#=W0wu~NP}!zDr-XO24P%o%5n?W!2E zJ=g`rLI@v%>ZuR}L4@c*K@fZkdg=y&Mnr@?)>~&*S9@q1X6Bsp^L^icJ@>jguha$_ z0u)8nDjjl$tf&32rkeae=fz)SsmJLY?nVPRuep#)8mJ!v#nJ|025QFm=oW0HsH!G2 zo5MNvnxG?#(R>V3upGjssMbWm(ez=6K|dTcZIRx6y+#Am5b2(%%BhY7hs=%%7j{o{ zX7!0-J#Ns6HqcrSh=2vL1`5`Q?Fj{uF6jzn@0(c~lpuImr1yf#sa-%qE(B2~9Mn0U z2eBB#N20M9e+h&*KE!h5jRpCL5RD0;X0ZRz#G7jj2pPG3-xoQF^bp35z_R&#p2>$9 z0Sz!b0BMb`(+{p zV+)$Y@(kyvR0gW*|Dl$3fc9_(9>)7mVJ|!GKsEzCH0J80aRZIMD@TxAsA1%05gI91 zv1hX3#^T(=nzuRq#cU6zf=M*WxR6Z4tpt3~h-tld4k{BiF4#=_S5 z-Km?gogXiAmzSSN=awc{iq&V7_2NcNlQa6@wprKoX?Aj(eH-Zf`7||s1Tnvlw|!HF zS6{rkvv|LkZOAyiu&A`0bQZkXjMcP;>RwY-)SIg_3)`m>3IEnA=}vhm)mQuj;yzh9 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1_active.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1_active.png new file mode 100644 index 0000000000000000000000000000000000000000..0b1a47433efafd50a22b0f44fb56df354d6d3d3d GIT binary patch literal 1090 zcmaJ=TSyd97#>-Qw6w@5t*Bu%%4%nJc6Y|z$?>u?Yc4n@>sI>^;W%^DNoUS9b8J_s zup1N^*p)8QIY0mR{oj8%$C{fq z7ZxlpAPAx`(I6-BTH<~4=HmbRjQA5Tr6`_8EwCMBR0j}sI&1@E!c;pz5~zCb?q{Hi zAbjOUDvi=gqo6^PRy`j&YuXr15LGoAeGFT-Ign4MQWT^zJq65QE8=_l%NAh zjt=>?0Lzj*PqSf;=h=;9Fu(?x0DgHt8x}ZT2v(Al4~3&Sdb^O6>nCI3lSp+UWD5+F z$zGW&i}V=PHrRti3M-vR!L+An zEqAg^xL{0HwHcNUcq!!^73Ke~ra9&9q9mBsJ0r21>a_ur1TO4xG~BrMGB1=ZNDfdD zbW#v@=c?G;2@!NVp-oCHJh@I$HN)}@72^m+5fYY*R7(R1S)?!rZ5X=1Ns&;9=QuVR zlUX*-MdCq84pj!ivAVca9}DELGSqrZV4)mVpT_dDV!dH7Z5&w!jYwr*@5`F`!do9gRNK|XhA-iiGjgQw2J2gT&8 z+Pe+ykJjd+{IZiLf3LpuW%#Ra!Q=d2#EY{=xb%w34VBODZ>_m}^~r^WCAGsx z(>EXd+2>m{wl@B9uwwn656?F>emujJ=j}SoHTdZtjgcKYx11gtup±(gDlf!9k$ zmOVKaFCQf?Zdft=Y0lnz=gzD=K0j16x@}Hve;#owy=1>WR1)%Tbt2v*-;T8&{0k5? BVAucv literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat_active.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat_active.png new file mode 100644 index 0000000000000000000000000000000000000000..140c797bf0c8ff3fb4616b9f44cdb0699dbd204f GIT binary patch literal 1063 zcmaJ=O-K|`9G}Hn!V=jc+N8s4wA66tW509<$B&)a%`Hckb*c4I&dxmDLFdDnXFE!V ziV!?RbcpC?1e!q|g1STol9WXUi8^#ji0IbULtt;z)eddL%)Iyh{C>ax=bOzAoUN;E zs3i!ZF4HIG@EY{K1AhGfR^~VGavY@!XwV!%W!Z*AuWA+{$msGY%t2Y5nplOM1X0tZ zd1;Q?iGlT;0NKg6QmaEm;|Z2o&L{X7J>%m#;~nsXTcxCNYvFz>?NCZNtIo zfxI$3rX*Cdy9;!>92U?al7Xv_8xH643pjT>q7Tv?o8Lm8QN-ZaN6 zRm_%5WI83&0>WS%v`Dg|8J?kaiy=u|#&D2qC@>@PB-WrbP31b02}Tg2Q8tkjST+^w zNQDJ4(#}May(uA`WGY$3pbA&r{*1ib_J?w+tk5U(wtU3mT*4JaX%yW=H0Kw-faF*S-`nKii!i#$5(8B!wLS1uk^^Je++K=xKWZx2i%MTZ?H*^gzD=sg!&CRa| zCwdmwn^t@ubAe~{qdRNXm+aiRn+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;uyfLiA2Tp8>Ug?1hE&{o zGu57t(NW^)+7~X1HimR$>Aq_yW!GDHCphP@Zj3{>MdOd)7a12Xuibu9o6UH)vC|@h zlc(RzpLu`w``>A0YYljU@8?{*f8d4!N0ZntL6Z-)|JTgwC=4y(UZG@nT*iBkzxT7g zg?c8;OBNV0yl7a*EBjb!g5;Nlx>tOR9Ctg0D>E-s?MiT;Z0VEZ+2wW7`ozPgzFmSg zvrQyA*EZx^gw0x4;?w8fV?dUL(9)c&shF@Vd_1f(_FWlb!U}aNVnWKOM>y?sisH24(aY` zi)o7A=N-h%`0kkK6t#H?LD$wERN>UyA~VHY_tONy3aR<8cV<2PAOGyV#2r=%2L6m~ UvAQ>utw5!Tr>mdKI;Vst0JY1c@Bjb+ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle_active.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle_active.png new file mode 100644 index 0000000000000000000000000000000000000000..8e3888ddc70878fc42216c0c8e111bef595f2517 GIT binary patch literal 1220 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gjk|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`vLFjeFsTY(OatnYqyQCInmZhe+73JqDfIV%MiQ6saIL(9V zO~LIJ3!HlOfsWA!MJ-ZP!-Rn82gHOYTp$OY^i%VI>AeV;uxC6?yv@MCXy)nS7*cU7 z>CgZF_RPAB!pyw~FKlmMjde&p%pR*?%Gja&j)h~-v8945{1`oC8Imef3Kz(^IoZwN zIO6B9hd-l3Lyxd820Y}ykJB4d5W-{~Z+>*Mvig?tm7BljSs~;~|q|+d^PyTMff*su3uDDKO z{lUY&Y5OAe#Ef^x;zIRl0XS2)WXy58Xed&?o26LrkKho(0~aAz5~ z?QFTqq;h!c2Um?NLg^~rPda*=MO%2>nf5s7IAp0jcdC8h<5IX+e)?(8a~X?Ejm|PS bG%zx}el}|ri~GNDP`Tpi>gTe~DWM4fH;#~9 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player.png b/TMessagesProj/src/main/res/drawable-mdpi/player.png new file mode 100644 index 0000000000000000000000000000000000000000..1a26651ceb0e4d890c726de7b0a4a29cd9851f9d GIT binary patch literal 1249 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`Gjk|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-# zG;lM8>2=9ZF3nBND}m`vLFhHasTY(OatnYqyQCInmZhe+73JqDfIV%MiPJ46t~kwu z>P^Av785s|di8;h(Fa8>QdGl)fawRsgeP1e2cGm(^ML8S2$-?vwYmA`&6}SKT=bo_YpczEW?2Ka_y;U?2b=0&e~_wQ$zzhz zz|EI3J?b)RG%K7<_Tbm?pmi?ox!|flaJ=UWt(D(CdWJKHXd8K@%mA< z=Lau-2(vZdn|O4h?Rm*94(C3EX0i!I@dSqUJ+AI%k-}M^LdVn9 K&t;ucLK6V%BeRbH literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player1.png b/TMessagesProj/src/main/res/drawable-mdpi/player1.png deleted file mode 100755 index ff66a1aa59723eac72be41a18b395febdf4d50d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 516 zcmV+f0{i`mP)G7HQA(|{v>wSZ^f?r`VkQD=jy zascB~SXO|d!O0ik5=36#1TbE~QcV%U5I6cc@X)P6x1c4!2L8S}VDd+R zWzz|GLdS+EnlhX$>8fa6sT$D&{j}Hd6f?JdLM#?2cFq9}6~VZ|xN9}?`-COsN@!r+ z#-(77iAJ$qAeg1jmRv8G#Oo~rgUDFJFY67}4x z;kJ(nCG{UdQcJ$c#n&a7cV)RpCC9wD)Y?T@Heftvqe!wm{zQxrB|%L}@J-^gVt8aI zQy!kWvJViZ2P|(x^Z_4!AEt4Ap~{6pn!vSj7Qq94g7d%0>cjXMbi*{`n)k$#=uB-` zfGe4CEkPI2B$kS}aQL*0#D((&+{5tuKo`#crQeY+0R{kT!HiRYuJLUE0000K|xPmyol$DSZ{)e zMGHkwg*K8_FCJ2*Md`t6i%FZNo81||+02$D+59^2!OZTw?|bjfn>TcL;wbr_@&4-P zn*V7Xfga#2FbKqfcKLk`muXtZ@;zKpYyXx=&?uau#>9Cl`lZfspev(5R?H zm7MV$mD1~0&fm}?4t7N3z9I^ZEunnHbij+CL*CFWug)uOU0zFiZ)(>mVsn&1 zALmY)P6B_>xZ-q6+u!Ovpc}?Xh;(C`Mn6jX1;iD1a|(fxYG+ZCyrAwym%SpFZ-aV~ zXmktkV4srJZ&FL`YKlCsk761Drr`bSAOSJ%0Lz5a7|rSTXwFE~CC47L>@k@dk@x%c z9voA?X2Yc&{2MM$8f_$lHn0wH9j&4h1<{WKJptk#X*VUv;l0)9n=GEo%fO*JK`h93 z`Bf{Az8FLD(H9M|TVBlHl6V%xvo)WJ2F~zWhrx1O z1d7nH0g5KiAtzl`wBX2cP99~0r#AJp&(4NLa~?d~984IuG-On+WEazg=)Eo%nAsuo zfkAu9m?A>UcGP)yA(nrQOBBN*-?l6fjMzA6+q=bZQqQU%8XZu>EnUxl#g{!aYaP3) z(KoXME|OJO<_!f{C+FLcyctF6L$W#lqDP3;LDlHsyOjc&l}b#Rs`S*XeL$LSSY8I` z12z2K;>Pufl?%7LgY(!~#0gXcN8M!gVEmB1%_QSm^~93yOlMlanaQ}*L5HJhmZH9J t)U<5r3+E18WB9eN3+MmR|B){N1^~IqczM6>HpTz|002ovPDHLkV1fZN;!6Mk diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player2_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/player2_pressed.png deleted file mode 100755 index 946cf59d7efe46f6986c129d26ebfd08608a12a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 845 zcmV-T1G4;yP)wMO{AQUAOS0Mg_}~lkHZ$Kh^X9!b-0@dg@;|mQ z8Tb63Ya@^VE(4=L3Xs|NeP9Jx2Ie55bSuCE_kkN79AXFf0+E-U3LFET0Ve^I_wh@< zfbT~j99R=Xp-d;JWi?VO){%jxTcOc&J+I~4- zJ_WH!(==mne*yO(vhNIqZ6e!wgctbb$l=KIcI4DT(a@SaAV0;1HsKBf4;y1`+YAj0 z-Ff&>c$O15t#7Rr1Myp8TA?Ilo2-)|G6k8Y0z)cqYE>)3BlZcxtU}9no;O(zA+*V< znW&K*xzgeU1vWfr3#j%zwQeZQJHnxeCO{R}gMH$TzHS zE@r4klnt}aUDL)jRxMPMQe0YTS`{Qk#QZkdv(iro`FFSYQ$zbmIymbBv@4F`a?p;mV7a%f-VFvvu;}oDJZp9Q~nre9$ z9)^ZDpjOmd%>C@vi)f=;H4Ss9xLcf76*bxoIlAgyq^|^b9=reOCP3{0umzE1DOY+_ z%9hgY$mtvYj)L|z;nM*JQ*}I`rzat?$=elU#n=txX|+;POx?J zlpMRSb^0dL=kg|Sy3HY0*}MFqmq(x4ID7PILmXs!Z1&IsePAf{x2GolW>hXU#!^Ovk@{p zP9j0-g0XUU&#tl9z`47iWYc2p1<`+>#s#m_c{aUycEPRf@0p&iy2Q}flE)R$z$CJO zfmI`5Hq(898Fn65Jk1;&W~cltoWdt?!7cOaRhy@kbxho + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music_big.png rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_audio.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..4d058f53d09f81c5f761821c976e4ff96f0b35f9 GIT binary patch literal 3825 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 Qum4}h`sV0Ix~_5m2kF(v=>Px# literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_contact_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_contact_big.png rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_contact.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..bada4c2661280fd36ccaebf6de2f52c535efb60f GIT binary patch literal 3519 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 U*qq?IW$BNc;N_2Rz->wYFYRLp2LJ#7 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery_big.png rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..e9e735211b7debf5018de438606542a355a05f3a GIT binary patch literal 3424 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_hide_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_hide_big.png rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..1fabe1da50a595c139a91b422bb272cffa1c7a99 GIT binary patch literal 2806 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 a*&raPDZJ)D3AcCkDvYypwY_TNpY$J?is{?{ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_send_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send1.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_send_big.png rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_send1.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_send1_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send1_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..4a107c6b41a0633c15e274d030942f799e23a8ae GIT binary patch literal 2825 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 bLl-Orrm@AkO4GoJ`JYp752m}yH7w;XaDb`y literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_send_big_icon.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send2.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_send_big_icon.png rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_send2.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_video_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_video.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_video_big.png rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_video.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_video_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_video_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..d251fd69c1c12bc4be638dac19922c693c8b5ecf GIT binary patch literal 2866 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 xi8Fn`M|;)}~aPnGX_ z4{A>C{66o0i22Q6(FF{w8V9ToTsrWxldGTU>goe$1COh57ML1ed%|!dbM<5faplh{ z4B58JRStNbx8gi-=R&;Df^Vs_Su%WlVv8AaN@ON8q%+&g^Za@BEb5BH?5BD=uWdVR zdpUpc9e3{juBml-H)45oCpBK)bl&yZ6&3NB>~~XM9KSwola(0I>L2zG_~H{LF*Z&r RIR^9zgQu&X%Q~loCIFtSdU5~& literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_pause.png new file mode 100755 index 0000000000000000000000000000000000000000..72dfa9fa6ca284c97ddf67b8f79d895c7415017e GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw6p}rHd>I(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!t9$=lt9;eUJonf*W>XMsm#F#`j)FbFd;%$g$s z6!iCWaSX}0_x9XIUIqn*!yCT+U;L0sO~C2IOyeEO`JoCBus~(?%Jw=a2aQ@Fd*NsU c1k|znM*W_{DEU_~3TQNgr>mdKI;Vst0CxpC-~a#s literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_play.png new file mode 100755 index 0000000000000000000000000000000000000000..043acd808ec133c8353be75d77ce9afeea456c9b GIT binary patch literal 399 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw6p}rHd>I(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!t9$=lt9;eUJonf*W>XMsm#F#`j)FbFd;%$g&? zz`)4v>EalYaqsPoje<=M0<90{CmAXo=i0)$kt35S`vBJoQx(f%<-Xf{E0uSP));@d zcQ1DGg;{D2j9dW?Od<;ySYM>emFRdaI5OLq*^`~cpfD+n>ENlU+^hLG5|%w($pi(>HJTxmOdS z)&(8!_hqzyA!w%jpmd$1B;)t}8fk2Q9KthK9&c-EsBTyyx2B6ZkK2f2hwKTB2Vn|3 l+l!xbLVcj&@SpD&lWxp4#x1KBYXifH!PC{xWt~$(69D^8i*^72 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_previous.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_previous.png new file mode 100755 index 0000000000000000000000000000000000000000..2522877dfa95300a55123b35e1eab868965a82ec GIT binary patch literal 354 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}tg=CK)Uj~LMH3o);76yi2K%s^g z3=E|}g|8AA7_4S6Fo+k-*%fF5lweBoc6VX;-`;;_Kaj^+;1OBOz`!jG!i)^F=12eq zZ+W^nhD02Gd)=Oo(NX01$L+IoHlHo?iZZojf57HdY;={`16Y9rIehm$jjd z9jxEi?8|bPT^koKns7)o#GzUDeWWsalR;G5fw0c%%-*AXy2Mu96dW6 zBp1Bcp#8r_Ymck%Td|$a^R)PHEl3^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> zv$Sx5>2=9ZF3nBND}m`vLFhHbsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6qkIL(9V zO~LIJW1M>RfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tm_^KcQPu+45_&F zW~Q$RE)|FyaPT6_9wFYV~|OOMo8Js98WEm(bR z`l?lZk5u^%DLg33W1YYl=zDqInK?CSr!`dTS%2B)Jt-G35)RDfI4Y^KK7dc!@0r7l zivj%Bf&vLD3;gvKo2}t6JE-zPb=d*4A4R2-r3vQ~_)`AY)_Kb`1REUL$lj%P^8Z$L z1O9!MTpkfB@f)i*oDOuj)b?J{oiWmJ-zKTG*N^4?V6)_k5P9-?R>M=P=rSgqLXiv3 zvqLT@{S>}%wp56}S$c!()8_dzmIXc9HFNidj-W-Cgtc32gtvcRxQ|i0QT&73d-ekg zFP>;U5MFXnatBL)sFq*tQ%PpyglQkDbrsy(r;Gg9@Zl=!T|rK(O?nNc29LhUXk5}- zy!}O;?8$KBzcX#SHhLMx3Qk}b^u1i>u=1i}gM_`qePyMtkLlA27!ChCaNVq~e6(k$ zqJnBcs1KKT!?Y^Vse32ic)NY#%2l_nc$*%Xymi7%QHiHB%as%kdmPv)%ouodN6d#? zUz!T;Ze!Rb$l3TfDpsT7hK%O1w?602oK(+$wUj~Af$PJSI#vmWrnZvwW9EhjKt-Xa LtDnm{r-UW|iFNQ8 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery.png deleted file mode 100755 index 4227122dc62cb554a2a7a69e38d2c1292a0de216..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1335 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`vLFl!_sTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6q^IL(9V zO~LIJbDVnhfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tTQL7Ok-eRTXFL+-y}qv_p@hDtA7$6Fx_*7*NWE%9?X*m?O;sHkw;vWgcO#S2)>0r|!yn$!ifwZYc25i+2g!eSp7H-iKnC_y#{H%yf z)AK7k-6!&{RyEP@%-_IQrt;S6f!^a9`JCotX-SXiN5m}{65V!3D=Ks^JK?sH$#R&g|)#@F6)YV8$7C*+wxdiH%Lp<#sFV z-dSy}WHZcv_^;PbM(X+O&I1<|8yhl3^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`vLFjeCsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6rXIL(9V zO~LIJC!BiqfsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tox7n&0=6++U@D$7*cWT z%`9J!kU){+@1=7C+Y)AfJ0zg%&C0BMeQL_ZWlbXH+cp>V7~Pt7MMYOhsLO0Cr&G7m ztsi?QglK4p|J=AD*L4|p;gyf|vy``Fe7RHpzS7va_`&h&GuGelecu25?s;=ZtGQ;a zIflUx!bB!yYnPr?nCOvnk8J^?4D(h6KCK@&{SBCp9n3ah`d6|q#b{DX1zw7SHT=4f8QbS;*PKgLb*%D=jpc}>lVn`f{*zrYo*B;N3#|IsIzDVEzF2wCt7 zzE=`HaPWJx?7Uw|TqbRTiMkE(vpM-q|F566VpHwhq-h6(+iRBz*xbx}<*%W+%Dl=Tjp&SBPG#IWKnpeZ%yo8oo@94(^(FoHbQ8Q&V*pIPEa`@Nl!c z^MS0E)lWis8SPsh@8F;RUWzG=#cq1b;wxols}&#YJ@8!R#hpi%ZzZK{ftnHmUX;%c zUu9DHHYr1>hBc4#v&5wv6DKy@Ul8-4x`{J+|AB_@Vh3)e98I!(kW{Ooy>zQotwdu( z+*@8=Uzbp?gZ>M@t=@XRb(d)N|7E#N222?TzeOtk@K5|TV=KeGj1oB4Zxd_^gX+c%xe(qjXoOa?H}d~zmruGc6dH3-RIeaGHdUR z?}O|(Z`^6|P}`BMR&0^;$(P|~?7bZ+o9n(A{?uw%_Vsh*xAR}3yWf9pKNfz9^#aR3 zIXUs4+gqIk9L#vn%{s%rr}W*H%TlaUrEC|UUpf8fzuquK$B+AkTp9oGY~W>NW4Qc! V`x9%~J5HdY-P6_2Wt~$(69E0FU!?#5 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music.png deleted file mode 100755 index 12336bf80a1d477ece58bbe7780b80aef69090bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1272 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)ylsbTTkB zvote@>2=9ZF3nBND}m`vLFjeDsTY(KatnYqyQCInmZhe+73JqDfW2&$iQ6p}IL(9V zO~LIJOPqT3fsWA!MJ!T8!-RmT2gHOYTObFX@Kf`Esl5o8tP3?y-C|&1%<*(_45_&F zW~OfzlcPXu`jOuHCsJ_^1&bSRvVRo1$$osk^pO(+MS=%+h?(cbJYi6rF5r0mvGkgT zElQHXex=!>HZJZP_q|(Xp8N86;hUW@mghePFuXhw|7oEC&*};ZC&rMSMSam3d|wx7 z{4&%3l{tIHq8Up|XG9=ibHaOa~|NTQF!fF{G9%wte8Azd+M> zvd2@c?c153aV50Y>=nKr!T-n2$9i46C2If!>khx3g=`@TrVIVUbG9(=m0qvwaqazq zA1gi*voCY|+W=@7tIY^f(M2GrXw$?U;RSW7DtyYztl%%#}%<9C%ZuZ<^1t`iPhg zg(#U|)?%aOdMRvSKW>&v%iiEA{30$q$#>Q=m8k)@B6H3e%}>`<)SUmEQQ$-6J-Hq2 ihvzV99B_QYBEc~6PMF;W7p7uRS>);J=d#Wzp$P!SaJSe1 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photo.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photo.png deleted file mode 100755 index 25f0d3c8177eab985f937e2cfc5f0bebcfd02a81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1588 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 Zzo#4A$|T}zXScoX-ApAi(!JP)wLfzkMQi{7 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png new file mode 100644 index 0000000000000000000000000000000000000000..54f0f7bcdf2cf69e698cf1ec17d3d990b0597298 GIT binary patch literal 1119 zcmbVLPe>F|7@tbaM9EWFQ9MS9#CB)itUJyQjCBsEp6#wg zsRyZp5J6BKIuzk8s6${KIt59WvQu{IT0)nivVz{IYaPU(Vdnk$=KFr%@B4SPr~5>G z?SWc`Vd^toT8{3A>BrVo)3xi0P3X3t=>4P@kC39_BPMC#VFWUcF^Y1?u*&BbQ9Hxz zD%kmc(w{vko7jmOp-!~qc+{F<+B-|0VU8gJhS8|)D(t7H&sbnv3VSx5<+EN273{7_ zAN5Xl=grA6Ghwlv9iY7=Qve4M1C*R`H;_vTyM`;%b13Fmu%<%B6n33df3^ptu#Z4I z8jF}bgg_Ldur)4<@Hh~7C~!P|#RzPb1zGf0ToXL?Xlxgb3A$1Z9^PrHC6eRS+~3n7-{18@nJxG=}j6QCP}!Jp{+gW;cP| zU?Wj9Wn9VdI2h$Q#|h(F(+)@u{h_g?c91W7h|8e>PxvOS$4FDfnC5PKN1-BRBcJkZ zS`=ek!{&s8T$0fgmi~!awk3;_B&sQxR0V+-B?u*6im7om26a`}MXj}hv6XE)9Z!of zU4V&X8bUoT=|W12wehWLQctB-zG9nk17f%)s`$03Um>AtQUa#7wUtvoG6?qb7>`#v zpr?Qd4hq-K%*dDfuX(O%VK_V2*STkCYDabB=JM^3#QUdTEiTSh-D!D$GdA#WwQjEYN6Xw> aeQ;+T({c33?vDaw!;#PE-P!|nXy!N50cM{7 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png new file mode 100644 index 0000000000000000000000000000000000000000..718da7c4ec177a844602817ab8b83ea353ba4890 GIT binary patch literal 1266 zcmeAS@N?(olHy`uVBq!ia0vp^azL!a!3HEfIx+kcg59UmvUF{9L_6kQ%*;+ybC(1_m4Zih{)C?9>v4 zq}24xJX@vryZ0+8WTx0Eg`4^s_!c;)W@LI)6{QAO`Gq7`WhYyvDB0U7*i={n4aiL` zNmQuF&B-gas<2f8n`;GRgM{^!6u?SKvTcwn`GuBNuFf>#!Gt)CP zF*P$Y)KM@pFf`IP03tJ8LlY}gGb`4?pZBPB7%B|o_|H#M)s)5TT^D5IB>nPO#TVPWRv zZ0P7@WMp7wVQ6S!U}5ZJ>SS!_>g4Kb=3)Xf1DjqqH&Zt=V^=dnOGh_DLswG^S0iT^ zV{-!&Cr4LjHzxy_UeCPZlEl2^RG7V)KzpHjP4ViraxO|uEXgkl${F?;~O%CG$V(cKrm=|2-b89I6i(1pL{> z)KVdTGqZx~SET7uXdCcBcr>(IvfPK!w?MDqRa31kx zPBiotzP@0~4(X28$QK!kUXK>FAC1^7yjE9_E$W8*c?&ktnRj;REN$&y?%e#FC zOOJb0bWD%FN9IJJfy!HJZFr@ohih=E1?k*l+*%-PD#W@`Oq{t;-gL6Pu;E9KTz<^mwmR8QkAcI0K}J08Nc-!n=Acr@)78&qol`;+07i(L`Tzg` literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png b/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png new file mode 100644 index 0000000000000000000000000000000000000000..0e916f3761d64b09aa072ec95f98abb755075b93 GIT binary patch literal 2563 zcmaJ@dpuNI8=j7HQe=?|YnT;`Sl}qBwU41$n z<<`yDg-STOA;S?NBSbk=B)1ZpT+UYMe1Cj>`?vRAYrX4zp7&Yrde{E#lTMB_C4~(N z2n0gO)`sc=x8d*;v1}>)UcOc%0dCYFD|g71cNhw02tb4di+2b_*>V^@pbN-gg&e5^ zNeG0THhYgdz6bma$Yl`6_mdaxWazHM$h-LkQHU1%Xp%^%PI5HI!u!BIBwSdP#eOWZX{;?Lq z5Ba`fSwGf7{2>+#i@`2z?SF0cq6w~_h3@ylg$LhDALPRIE`SUB;*~xr0OdEAb~A>l=}* zU#iVV6CkrxuU)TOP8}hlKcFIm$5pQw%&+`tV;bYpr_f(=_3Bk?w-y>|C`EDLpP$}Z37xl5(i1D}?^Ie!*pi?6k#o=fG94R5ynW(KVNsINJ?o1>vFof``idMDS+CX^dQEY;ZZ3-IeMobExS0eMW&}Hd&u(JKho25?piV5ke(Ev z`@~JuG#J*p?i`f3Yq=9}9-<6Jw=7@G%U477`prpTD>AP9=SQj%N7gl}I_jp|b;k=P z&bhCwtewQNPe`_v=NVszPOsUpoO-fH?t|zOowI$XFHEJM&!el>(#9zLX-lH@BelBv zng&Q8gSE=nJE|v5Ku=cL4>|C+iEurQpT9Pxc|Vr#cjmwL~Q9EU;fw6ymw&82)}MBtrKvviG~z>kIn6}_SppUJ0Nx(yd5 zoy#{i3h#^>6jU(&$jduev6lc_{8BQJlU+x%EC)yKv^^k?+PNOnbC$94JN}w;q;bzd zQzV}wUQOs)=kidfv$ba3WZs%>UOBh_+9S{`(~$%&EseZHHRHsz%u)&tu)Qn97v@gq zUsS|NTH|N!&UyeE8ZA6jRmd3vSQy@!0oQLd;g5GLt9ISV+Z&FlUHFk>J+7c)k zBg1E9veURSvIz*aDpeX(htEvFt(+iyrc&+TB|>JU3d#($hV zuG0~4yXiEPohV%8Ka$?I@~-E63RQf`KfzD_VX%9s?tsOVcdxl^zA_knF$f)&fh;Os z#eU@6S&hnhRmY%Q^Whtvaari*`%5r0rp5{-&O?_x-ZZuTqPTyv?6)Q6 z>3_bOcw&Aeu4O~C64vq9%T)8U{)q?-J`vol3G1=s`Yf+Xz4~0gPL`Us)~@|zxU~3R z3|qHC6t*OtVS8q}b1sFN(3!j|UmuW*#)KC1Rc^U{bIxVt0kYG(bv5n6OS1dZIH&E+ zW2kQ3GaUo-sF~IKP)oba9TNGO^b?l3jw^!cZ@lH_r}wQevT$22uk~|?Qg4FNJ;}4= zo+==;CIUCJ+P)yTq|tLc>Xg4&cj%o;7yPAq!OX6-NE)LP^LZ9Q@Tq^o9kOZPSXNL} zs!HMxrO=y0q~ybovx}E@1h|&pj`7lOe!9P!4A8p6JWTbuv2B4huWjO`s#jLtjaR-S zhsoEM`9ZnVJak-$XPWP@>J^R-P25}Tk(;?%6>U0DvkY*KN}R~lM;7|14Ya+*vsCbM zWt%d!n_E-}(BAhYrSaWrFAR7`!ne%QjxIqwf2cg!SV75I_${-wa-?3Rcpv{8_w`|C literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png new file mode 100644 index 0000000000000000000000000000000000000000..7026a671f68545c671f2f568f7250550240a86f8 GIT binary patch literal 2822 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 OBE-|x&t;ucLK6V$l$U7$ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png new file mode 100644 index 0000000000000000000000000000000000000000..a9b7bb55925b59b339c469221553046c33374f1f GIT binary patch literal 1390 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`vLFhHcsTY(OatnYqyQCInmZhe+73JqDfIV%MiN!63E|#ul zu7;L4&4cPq!QvLEUPqjI^?{Dj2SqJXRKtXT=?BDwCtM&0p7c}mfa$#mn6PU!<<>JW zFh1~faSW-r_2%|kKjuJzwuic!Og^$gy^1PF7YN*FlXg%jxH5_N4x{SV7HN%ehFJm3 zZCyz#SUL|Uctq^W^vjT{nkI1TZt<+|-fE$LAD(CwuCLQk%du{;+76AtaMi3#` zz`(?z049vQN~83z)Y|?f4{F)uTx!hK9F;5^S6-NzXxx}B>h{nDzD{A zkS^1c`m@Pb_fELR@M-zFDuGLi4*zskpKC2y8pU{Ge%q@+58j498~HZ*ZR(3+Iw8MX z{cFn>&I$HqyY6znRQZy*?+kx>@uih#ee>#=P6*H5^E*$7{lw&1s~)dnyP*Gj&TFlP zPv0yfHdYRADxd`W#)8{b7k|J?OT>Hb7?6u+}-8MsW`-&TdX%`(2+j<$?P4P22%O~|N@N-M@$`A49 s3v)k%!zopr0O(8gqyPW_ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_next_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_next_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..adfa9150262a404895ee65605ce56f0759ce189d GIT binary patch literal 1394 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`vLFl!>sTY(OatnYqyQCInmZhe+73JqDfIV%MiQ6rvIL(9V zO~LIJGn{($fsWA!MJ-ZP!-Rn82gHOYTp$OY^i%VI>AeV;upfQ+>CC{u_{7u2F{I+w zn_C<8nG+?Be_U;_Vaw!;DH}SLh)q6t%fm{V$1Ilj5Bn>5f&UI?+0rhyy0%A|ygZbV zw9#YE{mXk4d-t{P*uC$1P5nvX$=kl4EdFliuX(gkMzG$CfssYP0YV5iFfef_fQd)CE*zVj!if`87Zce^}g6#P%Enzq`=!TwG0y44I`x1NXi zexJjnkvYFuUCzPt_ng^tL4rA4<(DlS<{c@y@M6!d=$zoMQ@+pkXYadQ=w9ESexcyr zUBmrmescn>UpQ`En`Nv~cYbA-s>qxPRww>VyH?=fsLHZHyWHD$(^>xKzNzsua$CBL z{T5VPFZ}iO)I{rzN)7vxvYkUM<|_5Pue58<;kqYy#^oK`#Lhll^zg|=$8GL! zIiIO$Wo%-RdJ}l)r7NqS*!COG+5mp&4Pn+rk)mJ|2l;s!3zxI i4hE!fuba=$$i@(&dS%rslNT(YQqa@Y&t;ucLK6TVPxNE} literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png new file mode 100644 index 0000000000000000000000000000000000000000..88901a49ee69954c2d1563497d01c57946883545 GIT binary patch literal 1012 zcmaJ=L1@!Z7>=9BoDLMcYzTW~J2+UAymn1ZSgdQ4x_}v@E!f@6lGinC$&1PBn(ZVC z122k`9Rxji6%j1a#M2Kt*KQD;J)lNrvei zb;=b|G0w^sb~!VS;Ud?kXoi{0M!sn+A_C^og5xRdrze{%aBPJ=mo@~$&!d_%y&9m> z>P*>MU9=>d&7K02kxU6(L`)F5OI|2P3fttBsU5p{7BoZ1qQdSKRWW8k9tQ}dxm3au zAOxbw!HKje!f}ukV3HT;5)*JjPK$Cf16m(TvjuilE~;S^NmJ>Yos_F zEbvg0q?jX_Owfo#xZ)8rN_gQ&n?XgP6*xX|um@sBa~{`;!qQ6jT5$aitrxbgiC!2V znLZCWA#SN1Xc+$wb=^*MNQ&rpz5gT*%PT(OizvkPz@mezj>M^aIUgXC;Gm50Qu`KX zYnb4$hJBDPiQt4`T8QcLF5 zR7RM{O=7gTia2#T0!MRb8DbM{jnv9t=Da`qb?k z8`7<@xt_I0>-zfA`|#tj;e*@9KVN$AW)U_G)e(wCGU$`4Uga7~l literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..95d5b12241c62a746b71759e85c06f25e08bc475 GIT binary patch literal 1004 zcmaJ=&ui0A9FLob7IzRtu%|~hn8KRmC2hLK#?dyJE0{9cg1soqlD9T&$&1OW&32OM zMLhX8%#(UWB19UE6u+d?dX0zI;EQ@8|pDJ(;iE8cQS- z48x3-=d>!_C+I(Q{#JSgD+fea_5ECE6w z%N$H+WEoBYQGg;Z&`(amw33k(F$;Q&rO^U=NvUeHy;$_7vMoYnPRS5b)Dfkhj)G#-cYl~RCAf`dB7EBz|Yw=ltB z3;Uo{lfgB^v>Y!sT<;3$HG_r;Q=K->31MGrs(uy-gOEIfubzO}4a>KP8 zW9=bYdRXyPEKkMoaclo+b>BqiCq51amtF>=k32f>0Uhk5`r-$D6!*$np&otuy8C+U zp>Xl+_T;0->qk3tm!`H8!boLwXY2E!yZ`3f$7j#K+}&;NeWU=BAf98T`Nd>X&MvR=_%6&Ke30)o#v+5i9m literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png new file mode 100644 index 0000000000000000000000000000000000000000..337bf8a37a914bf95e316b6274d2ca57c0c7430a GIT binary patch literal 1437 zcmeAS@N?(olHy`uVBq!ia0vp^T0m^b!3HGPT(V{cQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07?@QuLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}+T7#d8#0MoBXEYLU9GXQxBrqI_HztY@Xxa#7Ppj3o=u^L<)Qdy9y zACy|0Us{w5jJPyqkW~d%&PAz-CHX}m`T04pPz=b(FUc>?$S+WE4mMNJ@J&q4%mWE% zf_3=%T6yLbmn7yTr+T{BDgn*V%gju%GIn)!vv6@TGqiNFFf?>EwQx0Zb}=?LFmZBp zb#`+yfa!I~PcF?(%`1WFO+n~2$Eg>T7;+1MHoK%2WtOF;xE1B+Du6w0m5JLeCOFN5 z>P^Az7E_#h^?{Dj2SqJXRKtXT=?BDwCtM&0p7c}mfa$#mn6OpsVz?O?nD{+i978H@ zotfe5%@ioocHDahSJuqxg$H6ozI!|HGC-7PbXML&K0H>cNI?CbM4^NOZT(s_0M=IYKl zn#}U|JkCuyxL)-68>6l{n%t=~m(Q7c=*gKjjpsSdMcZUl(zm(%wX|M3$JYa-)$jS5 zpp{Ehy8rzwWxL7b;U)T1a={#1XEW`{Dd`c8Xs?Zeqyeg z#w&Td+P*gzT`d?Fd+k^ecQJIr^j(YWA8@?cx$gH$`3V|P%$6Mce#=i$S@pj5sba*` zTNlOV?l=1Hd2H_@xw+fB1aiu%ieeV^C&bR*T($G9gnQny7X~-J-iQi3cUJEQ*C#eJ zm+X?6uY=C}@LK7gZJTPMdTY_=K(-jyuge1CewF2ATz0Vv?0mKR^3J&OO=rE&@0@9- zDVgSKX>R@Cw%h%t4!23tlNa#{?df}+bJsU7=9I6_q`6^N7T?yttyUyFb;Z4dm6xq8 z&n$g@=ZwdsFY8x)y~84Sb!Q~A{G{_|_cQS@IGNS$kbM8(G^oJzboFyt=akR{0P}Gg A!vFvP literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_play_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_play_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..adc3c6fe0b76d9d35572a4ee92adc64e93ba0861 GIT binary patch literal 1449 zcmeAS@N?(olHy`uVBq!ia0vp^T0m^b!3HGPT(V{cQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07?@QuLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}+T7#d8#0MoBXEYLU9GXQxBrqI_HztY@Xxa#7Ppj3o=u^L<)Qdy9y zACy|0Us{w5jJPyqkW~d%&PAz-CHX}m`T04pPz=b(FUc>?$S+WE4mMNJ@J&q4%mWE% zf_3=%T6yLbmn7yTr+T{BDgn*V%gju%GIn)!vv6@TGPHEEFf?>EwQx0Zb}=?LFmZBp zb#`+yfa!I~PcF?(%`1WFO+n~2#;F&S7;+1MHoK%2WtOF;xE1B+Du6w0m5JLe1~|=w z>P^Az7DJqR^?{Dj2SqJXRKtXT=?BDwCtM&0p7c}mfa$#mn6OVAvcAl~z$ESI;uunK z>&%SZUd(|4ZRYHrq8Bb*VH3I3*)?6fqvD|W1*d9X0sW08O>A$1xL=ao1XqaeZ$Qb{ms?;-pq-(fAaXu#}=zQUb_Umi|JqgS;VN@ zMtQf#A;GAw_{S&If?S_XoDmWb>-j`tr(>H+^D8OWcN3YHgd44>%NMMCdQ@yW*Q)Mm zPwhT+q<|zH)=ex{QI!n2&ht9w{IYW)?eiD^ED}{Haj33TDgKUc0&5pk$fOjMQ1BVLXeBr58k{zh1Ms)vqLt8>mJ3+RcuXfc59{ zJkwWR-laeHs6m&Ba$VDJ7cLLZ7u!Sbcs zPP1jS>KBK;I`iby9urBCOClM~&lj5%NnV@YR{65N^l-P@6)x^6Wy?3eU6(R@dfe-@ zJ1Qv?`m*lkD94-qxyG5HvCEM2mC=Jxk^ejE-UVJdEA?7U=tLOM>Tjo~ao%lV_0qOT zuTo{-`6bF+c#^_i*{$nl`#E@;pFXks$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`vLFhHdsTY(OatnYqyQCInmZhe+73JqDfIV%MiQ6qEIL(9V zO~LIJQ=EGBfsWA!MJ-ZP!-Rn82gHOYTp$OY^i%VI>AeV;u=kbK>|kJEyyofR7*cWT z&FuYN&W19r(JPyS&5xgp4Y_diWz)J>+*|w=&WV?lZ7k9E)B9J+G}l#J-TK9%#eH{o zy$JYF<;2{y{oum0dp-a1$uPApd-ytYQhZ+2*-dMj?nE&#HZZU#FfejBFfa))3BWl{ z_N&gWTAa7t`eTNX@8wtW?`OX%zWV?DzgJmRReOD#K5Y;-^)J%i!7`O6E%59{&MRy7 zf4L=dAam8uDc5H%`Fv}-eC@$bOUKinX6`v`G=F;Irx=zwHyCthK8@bDjk7CT{z;_t zr`9_u>T~7qFZ>h0Hs^xyl?mscwnXWypLSPJJ(XW&3(M8FE_b+69TXY8-uSN)yrmMc z%}2IW>3$pA@-Hku*DYS;H{n6W`o)WUCL9n6b3Zy~L57~27@vmk<;Fef{aSVmPuNPc zp3k>yxHBQ{YR;|Hf7}j}O(*p~(f!HmkazcV_9xMXJ5r}|Un@4;G182h`kvv*wcUGS zCFN)IGMGfBrM|u~^&P82-q*MDRw|mN587{|gVy$%LQlq**%nI#3OdzIJNaaN^m_|y3F|1}(e!3qvkMQ9j=b3?tuUR literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..6979d0dd2a7c581aecf3379a318f50e09b5c8115 GIT binary patch literal 1384 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`vLFjeDsTY(OatnYqyQCInmZhe+73JqDfIV%MiQ6p}IL(9V zO~LIJOPqT3fsWA!MJ-ZP!-Rn82gHOYTp$OY^i%VI>AeV;upMP98WNeCi=98x%PvHg6mDwPjPHwf3;NdzlPf|pI!;!;Dph=)bfklu- z5zhHE`O*@;Ed@XAK3z-M9;f;5J=a%JpsN0aYnHfr(&SXTxh|)I#fqGSO{VMIe{?D&AmX}X z-)60IF1^|>zx;gL{oCfrk2uHBLM^4LjU`ggx-3rpcBxstVAISF>3wr1_%|tip1kUp z8RxUPOZu%u%=eu7u`MYdz4Mfv#WJ-UEZp)8J?Gp{NAbbzv`d6C@@?hq3Q?;WDrM*!|B3~ bpJE9NC2k4fKb4kD2bF!Eu6{1-oD!M<761F6 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png new file mode 100644 index 0000000000000000000000000000000000000000..f0ebf49875a343281868124b48963686bc3b9d30 GIT binary patch literal 1161 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~NxVnK`>zm>W17S~@uz8oHWVxEeXT7@HfII61mH zyEz%a^t$9Hm*%GCmB93-AoRN6)C)=sxdlL*T~doO%TiO^it=+6z@E0s#O)SGoaRCG zrr>sq6HdMQK*#8Vq82HtVM4(417gAxE|3FH`l)%q^j-u^*jKX;=mRswZ%-G;kcwMx zW*y{fQQ&b|dNcmn8r#noJ38acBDb;f250)mz1{A>~HHReNA+$$9Yt~YQol?rw%PAFFtbeUjP=xKIp)6Q+ykslhfRPS`U zZx7fkJblT-H1%^)A76+joV?hi)9uchaCTuIkY-M}eEg-@$Ktyu*45shdxNn?>!VN2 z{MIGedFRBkBr3?T zeJD5kwR-BidEB-co^Q)s^Gd(QPJb(`T~I~8(u6>X!@`HkYO_O8zvrxuBuYe TExAi4f(i#uS3j3^P6l3^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~Nvfx>&lJxf&W9S~@uy8oHWVxEeXT7@HfII61mH zyEz%a^t$9Hm*%GCmB93-AoQBx)C)=sxdlL*T~doO%TiO^it=+6z@E0s#O)SCoaRCG zrr>sq5l+4OK*#8Vq82HtVM4(417gAxE|3FH`l)%q^j-u^*t|#N-53}cH9cJ%Ln>~) zne~>JNs*_G{}BVRK}yz^_GPk&u_`}mLhZkyPji8@trY*Z8|ZeVSkbtHx3NpuIx!WC0* zBra{I>=*pzu{LPUV`g@yJgdTMgTSnZSsol`d%`U^=1wRH5Xh?0He|43ui!LbxV)@tlEB?1 Qe?Ucvr>mdKI;Vst05Q^>2mk;8 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat_active.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat_active.png new file mode 100644 index 0000000000000000000000000000000000000000..da9e63bc137bd04ffc3c2db74f2efc7fe1618054 GIT binary patch literal 1170 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~NxVnK`>zm>U`xS~@uz8oHWVxEeXT7@HfII61mH zyEz%a^t$9Hm*%GCmB93-0QDNWSh||Ig7rFK)eA}txdlL*T~doO%TiO^it=+6z@E0s z#OW3TSKMxa=uN@m7KlF#+;HmE2RcR{6tzfE4HE*U9}p9saDg0n(of9;ruQOX!cNnx zxy8W1$l~eZ7*cWT&8&mG%?3QKomUyHT-cM8Ke+K+QQYOoArzx!dV^EresArgrmym4 zpM<*wl4W$*d5;}tj5@y9>|plKkiGxq=DW|cv^_sf+aOoqTC@jm;|{hEffd~mJdJy} zI~AI)bOvtpJC8%aA|AP9T|IIi3Z94dZVfp5Z@oP)I#=O`j=Cq!LbH9)di>4PZr{k%**5(CG muI#LWf8sgWU&thgCNM0xR&u^DK(r53N_e{ZxvXl3^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~NxVnK`>zm>XCaS~@uz8oHWVxEeXT7@HfII61mH zyEz%a^t$9Hm*%GCmB93-AoN<|)C)=sxdlL*T~doO%TiO^it=+6z@E0s#O)R{oaRCG zrr>sqIZnO$K*#8Vq82HtVM4(417gAxE|3FH`l)%q^j-u^*fFkGJs21mA9=bshE&{o zGt=Aeuz^6^=M@jcbRxbBt+8NQB*@J-kyWUFi%v0@%A!?EcjryCVC(kM*}>W&ROj6% z;<|RDt(^K)n@bvJozHzgo?Lyb_w}wmzMGR?9MI+9U}|bmSP(D$(k5hDYS&@mnz_$^ zE-F6%Y%l8{$LEfF^wqvLw5)$H)8f&eLkHW1nU?Ky@~HXAW+gj|LzXf7$F@>C4Z%(~ z9=((w1)VnzWM7N)P+cS%XEyDmK<~}vfoy`jHMe$sJH3m~LS!TNKlg2hslpFDj@bS1 z-mFvo zj6;XRuT0;4%B{6yV}8Z;mtVH4{W&6PlWx19sa~?m@iFf_=Z5f#>r6fm`rFkGu>2GG z=XWOQY*v!@j~xC#(tlj^>duPX@#jwv4Lhh`-g0(z%XO`;g7pc)2^{)wxa$^2-+Xv0 zB>lP4N0$4()>D)|RJR?rJuRVdz)-Py#G#Qx!b=Zx9cj&lmuWizhl zQh)rY&ZT93#G&%)B)Q0UJ}M#=BFZ8^jvc#mTkCnx2jj_%+1d}H$~IFpm{-`SjxyYfBvq5d)j1yB?)O!~`dz;Gb*p{PhyUM;8$^mO%eS?83{1ORf^ B_&)#u literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle_active.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle_active.png new file mode 100644 index 0000000000000000000000000000000000000000..1cba5d2f563dfa0cdcf1aeebcbbe776f5f25b08b GIT binary patch literal 1395 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~NvfnYp;Qxw@DeS~@uz8oHWVxEeXT7@HfII61mH zyEz%a^t$9Hm*%GCmB93-AoN<`)C)=sxdlL*T~doO%TiO^it=+6z@E0s#O)SSoaRCG zrr>sq8BV?WK*#8Vq82HtVM4(417gAxE|3FH`l)%q^j-u^*tzUoAq)(RPd!~6Ln>~) znR(Xhu!F$y&w*cF30Da8*K+#D?d{~1tKm7=zr?QdLcl6pj=fxVZS7s`^AD^}>iypu z%ds%Fyu56ZNLhl%=Y!9_pFj8RT+ZWFs}|*MQ@K^d&D7MOpuq9s8k-uwtX=Igi#vzK z^VO?2AG4kQ{n>};$?PBZ&A7rWw67)oQODe4x0-kjg~?3?NX9^CeO z7UHjy`|x4$tJAfqi=B>a$gQ~l^2>I`KPSX((rp(s*T1QDyewtY-VpY%mU~0v{kO9j zq<=8~&^GMey1G;L;bz_s`X6d{{#dEGW47D@tu@W{5yEEYh3>7;IJ9?;Z-eTd4f;Qp zW~R1hx1K!bdP%6p`0a(R1Mdy_%yp6*801Zp_O02v(8a|_b!U>~5xEEdg$=i^?H5-1 zbBZxe-0#}azYQGrMJ@T?j+hkPndzbNLBmbs!>P7Ax3!Ml3^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~NwKx;dK|y1BX-8Csec8oHWVIyqZ7ySh3#nYlR` z8n~Il^t$9Hm*%GCmB93-AoRN8)C)=sxdlL*T~doO%TiO^it=+6z@E0s#O)R*oaRCG zrr>sqGfutwK*#8Vq82HtVM4(417gAxE|3FH`l)%q^j-u^*kT6UXBilnrhB?LhE&|T zGt1gv+EJvnT#!}Jg4gL~@&X4nmRB0#4mAo)ZM0O?hbA!y>`FzqRtB)MG2=fZB7Mzh|v}vOlo%XTOqNt)BRzn1)Kh z{m(*~d$`L@1fN~z&s3e1Aa7Ihq^X*B*TMB((VhN$Gu2gZ1iS9NVDO@J!`qjs`TsQ| zoa`(ZV!622G$tGH%1LlJ9j=t6J`5MYR0OU``O2 zBh6tbDb^76NU@hYw@Kv3f&G1Yyc@4CVz_eNJmcRspDCft)w*00%qrL}#)f4^HcV*^ zUbt?P*GZ-=kyi6xYpgblY!EvwzDy(asuK5vj+b1kgTgq)k861`ulnV1{JKo@$GQzC zWD891W?s}UNWJ+ZdBZ`~DQiA$4&TI(KCLHsu{m?mAN8<{Gj$x!1?`;kA=AX`_^ipS zC#<6Mj8an>Gr}rgC+uV?JssE0bYVg1-GfD(S&IuaWcKjY6mE#w6C{_qeM)=H^TkEp zl`Qve?^!yfH}u7^%B#h}iyiY5ix>7ZPwteRxjd+OZL@^5P2}qf%yn${S7={+)j`< jW7xRz+5E7d>IWFEFW%F1AyelvsNnW=^>bP0l+XkKO5sF? literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/player1.png b/TMessagesProj/src/main/res/drawable-xhdpi/player1.png deleted file mode 100755 index 2a11310e6a6bda35d49508a843c9891c1c868b91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 858 zcmV-g1Eu_lP)`6pHRCwC# zSvzkNK@h&ZJ3CI4_lrmf1tLfg&?JZ;AzJ8YC@3h>@jv(<5d|V89ij;}9iSA!!QmOi zBLoPLw|(bZz7cEb0NK8sTi?afjr7The7pC3J2ShpVEDxu>KbD@N1gf`x&j7S;}bJw>J4b_soCfLyILU_AT-bLqNA~4&*qO9Z`1XnvApY%r%C90!M(p z1>$&wXE+{kbp^D|O~0N1k2jlq7vY&z#>}3U02EQ4y2omn?5HkKkTeP)JoA7dV4ri4 z?Pv?=@|R^USg7;0FZ01X&I67IwmApcH=tizL~rH3wdWSG+uR5pWF-*4%RI=)HaP;m zs$$M!c%lg0Hk7BH>R@Px(Dz2Mm!N$>PD*V7YS7!1$rFdQIQIb>TuD*DCoJSPTYzeB zET=@C-d!}(RzYz$gO8&L3wVMBY}$5=TCgoye_DV^*=iK>kv$N);8SC(tHtC$g8VaM zeW8CuP?dVYGT#@inRb7a)7+)7qxSf?;e=g^8aA;6goN}fA#s{s^z!#W3FOPHE3ARv z$i`IrWmIERAhPSg8xY@#^L`Uet91pMYdF-7p?j=Qt4t;KmO2!_G^%aV5D<>znwZ2a k`<*xwkO^pW0lx(p0G=Zk>nRF?&j0`b07*qoM6N<$f-PEo4gdfE diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/player1_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/player1_pressed.png deleted file mode 100755 index e3ebd1b5e417967076f6afd7276708a7bce5417c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1470 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_music_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_music_big.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..28f865b7604b08522a05d1dee2814f0349143261 GIT binary patch literal 5237 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 Zdwx*Ps~ZOKtp9+3xv`Z|rGeY6{{gimM(Y3o literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo_big.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..b9e2a00882c1fe5d922692c14d7cd594d0aed2c8 GIT binary patch literal 6375 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_contact_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_contact_big.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..d8824727d59bcada519e804e3caa7ee025415fcd GIT binary patch literal 4959 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 BmmvTE literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_file_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_file_big.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_file.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..ff36de726e415e82aa4e83844014945e3743b77c GIT binary patch literal 4269 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 XYyQ{MlUrDu7YL5_E`)m9z~uh{wZ|Xp literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery_big.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..7ae2a56adf13b137a8645dc547a160befb4919c7 GIT binary patch literal 4444 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_hide_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_hide_big.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..4e3cc02a74c8e4de66a1b58bd638c368b78a9152 GIT binary patch literal 3648 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 MmJSwo&3t431)(#RV*mgE literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_send_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_send_big.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..750e47fc379e7498c4b40dcf30c52cd4a9bee697 GIT binary patch literal 3650 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_send_big_icon.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send2.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_send_big_icon.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_send2.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video_big.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_video.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video_pressed.png new file mode 100755 index 0000000000000000000000000000000000000000..292a0c3d5ec40db51a7206a6332e2aed95b506e1 GIT binary patch literal 3903 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 A=>Px# literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png new file mode 100755 index 0000000000000000000000000000000000000000..6a227efc217e44500391bc9c1e33aeb94407fbca GIT binary patch literal 3224 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 rpPf539O$ zUD3_EiVpKy4nC+1Hn@shyIi*Tik~;|=Xf99kI&)rG5@lny%fDVsp>GJG5E|oToV8W zRZYC-3BEUxa3+`j9#wPZ9hF&MLc-`F>npZ{?MV;k;=9TT{;%+q8(xYQN|#ES4$rWC z>EN6x*as8_54n*>%uqUIpdDzB6mYV-b(0&lIbtZC+C;lX24`x~KEwydmy$v0)B@TW zD;zCvomH8+A~_f#a|P{<1x_{xS9qh_$pF*RHrgF295rv<<_(z%1Jjg=_D2GTyXa}& zKsBLYnyO|QTpKDJO*bz~;HHP>?y)~Zfzud#VQWmlG_}>oAZ_<_*U9lp`}bl!+fE8;|!)He-CE+ue&h#kqS5re)_BvdBfokJWdIihIE+e3yzvMCK4Rz zg$NLhiQaISIhQgpP46`q2fMYEa94Fng+y=+VGcl+W7)SL>Z~h!K zk+~3XFc(cw_QstYJaEB*d4ke5*Lu~0!@u#7ptR|e8_pU5Y0sFt;rt>XZSH)h3CA8m zRfO!Sx#5sHT%m z9BX*LsXoW2KIi;<;}lhPg{kbKnn0>19lV;9>X7@cV29N)h4VdB1v~A1pj|WJ_gmqK z0OPRV3i}b|PCZB{7>I1AUdJBKV#2@_wLDy<-ND^jjcs>uhnruZedU3Hq7z9=cOn7W zCB<15r(fF#H60#FFq=2g4zx$gQ&3c9J?BQ2V}?@3b}zjBcQP^O=P0`QE$U6I*iJTI zI+oazml|j4I0p@dO&r$oJ@~%Fp1kCDVI~n%tqL>mi5Y)EoZ0o;ReDzvpYi(zybtfk j=OQ{`sV5wp)TPXSp;WhU$I(5=00000NkvXXu0mjfQ6I(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!t9$=lt9;eUJonf*W>XMsm#F#`j)FbFd;%$g&? zz`!Wr>EalYaqsO7YoUVy5^WF7Z;Th?m5Y~L$y{`T=hluThR6QT z{CSS;T=0`8f6sg7Wvo4-(9C0W0!%EZXVHC8{I8(>72C<}4(5GZZfZ0>@H*8I#Llu| zvFAFLrY1#WRe=Ltdg`hIb6#u;Vq!caQ4q-F=-0hgh{Nlc&yH6O3}#y_wHhDz%=h7B znQ--*9*0Zr+d~eeTe(^Gu8%c%v9;{sg6Fq98>W3JabRVB<|SX+y!YJ3`3Bc4zp-0+ z*}JVQ={Q>I>z@8cLvrFPo(xOhGArdbQx=|^pkKzjYMR#rt-legJ{)g*9@J`ge2;dh r#ENwxjtV=~_sZ+RJ)zKi#G(BAw>yj1{i~O>_%)r1c48n{Iv*t(u z1?PIYIEGZ*dV9x^uR(!_H6Y7k$DA0x14&W=ChyPdKH=5z^@@2q-;zrL4ctf%nq2!l z&D2@RvTpZfG5&dvdmBjxYyHa3uJYZre{EB1eBS|d5a-W6BbDQ3SP!>4(4h>Tu6{1- HoD!MO>_%)r1c48n{Iv*t)J zFfdN{ba4!+xb^n-S>MABBCZc7Pg}w1vdxpRg^R;hCA3A(hkXg-`psRUSqV1p)8)#o zeyF^bJ1vzjcg05fAd9e%0Xp$d`Az3awKwM`GHiRB&24m}IT?R957O&!9 z-m&3nlpvcqpG@SdgA8hMi)U~)!>NisoA@C2iAhl5gz(q0F%i0vFHEv20fei7{) zPg>XZIHcWJ#gWo(>aJkF#*iubfRvH}- zpc=n2t!&Qgy)6F=Zyawh<@wDqpKVr~t@WD98^(vjc&p`mOtb6hTn(0;>yb8 z%JgUa-cWtOsqL;*S-(_ScErv5YbME}haWgh*{t@zTx%h~SH-ad7;g-ou6{1-oD!M< D0~E;e literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_previous.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_previous.png new file mode 100755 index 0000000000000000000000000000000000000000..2c9310af9055f1440c988034ce2a31595c534fce GIT binary patch literal 447 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY0wn)GsXhaw6p}rHd>I(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!t9$=lt9;eUJonf*W>XMsm#F#`j)FbFd;%$g&? zz`$tk>EalYaqsPojeds$B#wTp_moI^d5mN6nH`6jA8>Q%GrW7Gv(A7?m}i3Baz1mG z2~AgT+)ggqw{!Yu?^{Lhaz8a*Q(==#ncxT^{<>dy>3ULsa?mxNQis~IEnRDR8CQKi z$GtTv`!sv$i5Ft=(Pl4ZT9(^KMystjIqhI&)YJv;W+wZWg|cRCNSHG{jQ2%j&+k85 zek_n$zbA12G%@KbY3}dCqGB#|sJ?u=rDDMpQ~&$Rk219`b7C&Z(c-+28O+&mZuY9A z3#q}9B|jGni&<^=`LvL4{okII=d$IO9gln7|1m&zHBc-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(gnVDkcVr*`1VrJ%KU|?=$Xy|HcY35{MVc=?EY-a9i zV&LQm)9aF-T$-DjR|3v4~Pj*wm=R%;iu*SQ+p9GS#R5LQHOzn>4~R{V@SoV zH*>5rL;^+H-go_Qc&i)J!r`P8^@A%*k!z7-fIx1H>k&0GEu*>DHqKPjE{~zc@v+%J9B*I?&o)`JvBXr z(l6Si&14czY4VxCY2>JOf<@FMExoc>#I^Y2CEjn%d>ahZuis>Feqi*X|M8B8)d?rJ zPimWE6!)%Ss-=I|^#$CM>^eCgomr_l!B}qn0V|JRs;2Cv+LN3&a>-1cvqYQg`F-X| zO;#dYQHq)wjZTiA*Ya(03f!--%JAK%mYZzP7_>B}H8ww}Tc?%zP=c*}=e}RY_Y6aR zmNjuN*y|zrr9pqsvyb#Ud(%* zdsSy%1LN7Ib!!9wjl1=HezlAkRonM(FuFLei`$BhMc%AlQl}W|YI{IGb`&n(6rET(8KTjyu_S-V` zwd32ENdAJ~1{MoBbT-d8<#XOrkyEPwZI5VIB@Z|Ne|i2=ui)R;@Lu@UyrT)4Gr~Q)Vho z7CNajNhGB7p^K@D<9(-%%{srb_RcU}{cG0MX+9SMMIza5>MnB#aDKS8--}BsOe4c1 z=z?f#lb$D+)oPvYxTfNyrhu83b`?&~k9y{C&TsyHvol|G+ZgS4l%#%G;{E-Ud$CIE zxvAHB`WpRWPN&~z_Wt(1a19?gY0Xps2h-8}kG3-~GaOEzXWz$cFAu5%JYD@<);T3K F0RSR_ZG`{; diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery.png deleted file mode 100755 index 4f8d40750cc4643fe7c56843faf3f5b6cd7544ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1552 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(gnVDkcVs7H<v4~Pj*wm=R%;iu*SQ+p9GSxqEuJopAr-gY z%<;|^4wN~nF2v=u&vCzFYgy`NNhfi!8eJ)YGfFF#?wE0H>4Mvig`q61U6EUE=&8Ot z+H0m{$}&CnM^x!zwPV*S^mZOKn0sRG%>QQ}f0Ow!G3{1jTHTpBJ2{JIb05Bt%=Vl` zG(dng5P~ik`r4h8|Gm$?b-I>Dvt+=G36I}2sjX=Is=%>pnf5au_e&Fud#5i?$UEfU zwS57Lr~DC?m&VVRG8ge}X7_Wx#J`enm6eKns#wfKotK-M|3*&}F?qaTLGYv|E>v+x^%*AOX?(QO?Vtj1K#X*@mahihG9P2pM9o1cAIoF?!UHG`5+zR zRiSqG!u0F^llJ!KaQ)&t*TnpHAM?3}ezw=EHoxtAShnWdL|@0#4@y&JR;|hoJS{b) zd_mH#i3%J*aa~7#)56N7$4v@B)o-}mna!j8S|{yuTZ0{aBd`#XJvURlq6wNgC6^flj&7s{TF+YfAR zdA;T9T;JaEI4t{+T(@4=O2rLjU&bH%d-3yx1}y0-V8 zk8SuTwmag&OP*Iu+XLi@Khc?S#>}Tg{Bp6)^Mj=uvZIQULr%Qv-X$7vWTQm=x6>c* mKQ54g#SJiqd}97_88BR5Hm}-s_l%{WGTPJC&t;ucLK6W0Dng+E diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_location.png deleted file mode 100755 index b6bd6ca9ae7a9f9213d51bc5cad4b35979054291..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1993 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 Dm|7&O diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo.png deleted file mode 100755 index ccf61d6965a8e50fddaf9aba59745995e569a886..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1949 zcmaJ?X;2eq7!F7bU=V=_3W(cKFrc|ZAb}`Hzyt`!a4JU)$wC4o8+TU|ylO=2QR|?9 zj)ImdMW|REK~SWER0Y&Qq^M{Cv7n_D#fuh@mToNA{wUqq-S_*xd7kGzcXqclYPpTI zvo#Kfvk{AgGR%rhkL6749s9g;IcDagp$TX-l!of%Fo+9MLa87i*2vRA87Nm~uWbPX zaJU&{bxZ=9Ac^EFAPr4!!q5yF9mdAt0+tzcaz!SH0;yoSS}PzAU8*MoYNdc2?;~MI zbRnQhE!qHs(Ho*-6dN)XJSBPAQXs&<#{@JWDhCXjEG@z}2*~es`PkZYOeX{HA!w$6 z{C7|Z5-AV@!64v6V^b9jCKKRtX-tj}m&;rNuoz4hoq^q4DwD(a;qqC&z~n{7yur#e zzDyW4=?mKl$SM@o@#%EEUQg4rX%L)FXYzPFlLm`L#Sl~^TZ_sKR4w8@r62?m1+3Pg zYDf#16y>SVI#fW$BK&f8za5 zVI(G72hwFA07c(qmu=@GB@ zc!`8B)*`4}s{qA90U1-Esntq;C?`zF;o)GBL^O9Lsi|r3CWF`# z+-2cu+)TUW7<%!X@VIV2iIxF^s)LT2ZD%FJ;m`9_hn1dl=Nc~_5H+`#rjqh7_+QtfV-rZDxDGKx0G$`z)DuVqRGJ=!h2q1e{7ddsRhN zOA`auyS_Dg>T)Iy68tM$ysx%2-i|)ob5b2er!-2JkV+~AVkDupx~ zclD!0!t4iD?V#C_mH7|sD87N_r>oti8CxyF?^I?dzYw*-%Zc1857zq+n9b;Q8j9%4 z3a}+@Td*cYYT=9@?&Xho@tzXi*eBs5g79U(smAPUX!nS5M!v&ZA=kY1<;CB}DQydN za|Zhk%I{w`%5>W|j|Br8as|DmIZMwNzf0NGA4)vl`Km!VVJ^kJ&W?-X5^Dnq1Z4mD zZA8b2RmLNd)ve?s4msYrTKkR84IT{7&K1TjE;Z68wVjk@b8t8W;k?)tymwZ^US`5toY*fE!%&QYjI#|zF3cO8H2&g%cj?S{XH z8Sh+X!G%#=N=Jzc?`c)|Z!2KyHoLDM$sFTbBKhsA9gFXl+WHUVt!`aFfAQ$l#RQhV z(ox)7ok7YSLQcKy@A>Xng)DMRwf*zqJNe08x6AvGh`PGRhPuL&cb;?n!0o5D{_wfe z*cTH{^!|Ahj&#!XUsC#NYjff@7@xKk>xS?4ty=aq=q^%__mSm*U&a)y9CDdUGPKulWYf-lD$Q^urW~MhU+SUbF2l D7A^eR diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photobig.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photobig.png deleted file mode 100755 index db8c53ae17e8f8520ccdbbac56c3749618df996e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2487 zcmaJ@c{r47A08)UjifA-8pBLFn2njtWUMnXg=Cbim@)GX6SFik_O>&1j_o5!XhA9> zlWcV;k)<3_QBkRU6eD{f64f`;N$30H>wB;F_dd&Y-}mo+p67Qx*PH0+u|-qOPz?kE zX;NHCUa~e^9xBSR?=hCoeOY55BKwM{JeDYmE&xD|OkOYmp>XISfEPe##_VeaY(b!9 zP`0Z2Z~ze<63q$c3JK9f=r>)0tS_HNLLuKEqA()# zZ&SYRo)BlA0Dxc-R+bDD8V$kW5NK;G4u`gYU{Gib5+!?amS}4N7DvErf_#6VvTOn- zi{M3a`JPKQB0@t&B0d3$jEagvL|Gwtf)FGckH^b3Fc?c2!crK+715(Dxk8gA1ri`+ z2-tiPo5zL773sme2oVt~bNcrZIQ$>7T;ca^l5H3=n$Aa}5h(eRmVoZ={~yZX{6Gsu zUcf(o|EI9fJBAM+y#OIELcow69Lq$WicfGB0CW*g;LYQOFYTgdC{M%_hVu9jXDSY2 z=ELSPc~QcR-|+741PWIuqH`Glg+zqP6cB7SlVF8H98 zlM|V2<>Z22;*xlb2oAs%EpeIuaBY6dm6rmCFUw2<1nfwF=_259Am5fuVE^0;_NRK^ zxy+w?!Tpqrl$k-w5B9$fdTB~lJ@W34vXu>f6h6R}Rl7h|)(;kg*MLCE<`j~ncXZF# zo&erXvTk6@*4ihKXL{>AS3TaPh)jqoLYIf;@9uHcxQP5P)u)bLiT$F)fWB)yQW)5w z19N<{r}%t-z8Sp8^w&(a#QgV4V2HOWxi}2Cy2_CHu-z_%H9K~z9y$NWIxdeWly0`F z?3Q3F&8bwX;=ppfd{u}(r~#y+EDr~iEXvr~Ew+tk)tXKG;ff{8d@%NmK)o`zjiXdc zu(;rMLA%zeKbfAh!O{i) zva)MvpLAL~oMqd#AKqyE2`?=S{o|bLYx*%vP|CC5lP)76b*c>svDuT&HVt2w9~!Nl z-M3C@)f*bD@>opV5<6;6&~UPts}|2Eh1rM0q!w4JDGqKQ zH(18^YE^AuxSqW(?qv1r29YV!@mHz$j98_t+$w(QmR}?Z19v6stF%j=m-~u=y~hJt z)stqhg*%un7Gloz>X0*x^2={&+-ud76x)(D&4inF4n(f05Hplpp&sdP^w|HcmhXD1-}3B3nSNy}n=Ut5 zAAO|8`ZT4!aZLGN_z^9f*N~Gsj$7S(+A+rs__Bl50M~e0Y2y@H zdZ#uZw#DGDL|UP31J&Tk@X`KHV;FT-l2r=J^HLC4BFt9`+qB!BiGEl!vFCzjcTI=b z67|Hf5#g*bS{ZQQ%2#LVbEOmb@WlSyafQ+88~vZgGv41_)R#1SG)4Foe8oEuSNP9J zA4tIF$_?G%(zZukj}=DV>z-rs>+&cPF!-?r1ttVPlThH(GILq@3UJ;>n$N2S_w-I^PuB3cu=H zab_K}ZY)%P40^LGcY}U*@&9-raS>lPV%Hr)3$LH_Lj;B|m-O_fqPWT#b zyzV`|FXv^8*J9trteMe&29{B zg;Q%!UlCo20kE$fw|JM;WXRkIkV?es|@cO zB%a)SfdTJi9_n5^3Pzwk!)6mI!wVN09>s?1j#f#Ew5HmflN^#)9IN=ftEHs4 zNA%$3>JCGTD%#G!@P_FvAC+rbd3tknPao8c=|?ItcE}xT`$js+%Pra?(F?F#m~r}t zfhel;aQmmKw3*?it*u~5;raW8>hVXeQ5P?Xvs}u~gEpkE(bU!uE1*?yiG@?Cl?WxU zb6ji-I!in*Z_BndM4ltwYPy{AxYm9Qd~c$!1v68+;;H!6?Zr$renvDiZKr`Brm`pL z%w0(q*~{;6jstk}>M+fMXPa`mwNCWq)_$1`tGafA?it(NYrTH&0P#V3foVuxn?iuj z>N-V3{m&A{uNnIKc~7U)e0wuiL>uZTe7}5AAhDw?6y)}_H4f9{0a837i)FR_K?=&C W4#phIk76eOlLAr59;8wyn)pA&K@Rr- diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video.png deleted file mode 100755 index 66843485ea8921aea39abc8295a1b6d792dfccaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1092 zcmaJ=(QDH{7|*sUb8IM+f%)3n{O_SRiy5zFtX0xIw zBEt4G1RwOxe_$^P3Uf@5%BF&Xh)e_p_n_h&`miTKFJ0UDU=2y`yYGI#-}l{j-_4Jt zhT2+=wNMn*mP`m~GA5j_c|ZA&ZQUCp!%-ZYz@umq7bFu>VFhI&NNUm)OhZYTn^}iJ zifW?O%mkhghj|%k9?8LYY|S8SiV6LGf2d6fpL5~9cbqE|GcFsCMp zCLArMGIB952NZhnGzi)}5zru(fUQmI7H@~>vMx_-$IZ~748i#jy_?j8I0B-`guw6V zb<19s1svyL`}`co_5h!k^)X)Za&ESd_jA0jA5d{E!k8JtRfvaic%KM;t)+T-Q9v_)MRz5 zQYKO`#+D3*^?02vRe_@Tf2gL_&=yX^y?p;EY-Q#Q$fTi#W=)wK++?Q{%HX3WlrSw2nbaB|>ZIFE($*y@)kCht!=w<-*zdl* z54Sw=wz?h9O*``wd&M)U) MCu1pLDRSZ3ADw(*_y7O^ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png new file mode 100644 index 0000000000000000000000000000000000000000..7bb5c4539f37e004c060e28868fbcf8d3a4f3da5 GIT binary patch literal 1073 zcmaJ=TSyd97@m|gO}h|udz!|e1b1$_ml<4bcV{=38k2Rw?Ls)toOK7COEbrIb`uI8 zf}VVcphA{zulZyTVUYzA(S!78WPwP82tihFVQ1FewFkFhX3l?p{_p$0|NQ^C)z^Ev zx$$TthGEU|9wC9&HuSN(>d^m0id#j?5g1Luej^RDk_E7kVhjO1u1Uin0VE}N7!`!#cYiQ<6sj#D~DJst1Yhv#$tTRf5ETSENNV0y1h( z-U9vk-lUu#kvWCv?!r4A9ua5&O1Ptq>Nf8Li6SqLY}ZW@crgTy1c^;iDX|Za7#6_2 zWV=VE83y~4*s;clT7Zw5>6JWSd zjA5eQK$MLL?S8r=9EwI_VY-YJ40%igIxJ(AEi6|R>kflvqRaxY)T=;=S%!uei{{np zT6|UcN?4`37JpSNg~U*9YyW9=*@foEH7kRQHkHu_I+}M24fe%PiyP=tJdO*Yr1NoY z@pbbXdY|xNe)-gH@)%s^A3UAe&&TT-i1|}zx>i=tH#GblxIe|-%PvS43J0G*o4WbA z`^)8rFIQR%tGT^Tei!mT(zOeP&cNMk=YqNRhWS7BYwwq)*52-+2j_0=sI6-{yuGn; zVEoYROaN;kz Cm|#r+ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png new file mode 100644 index 0000000000000000000000000000000000000000..3279b876b24ad0cd93dcf18819a4bfbd5100004f GIT binary patch literal 1318 zcmeAS@N?(olHy`uVBq!ia0vp^IzVj1!3HGNBP?G5DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49qH-ArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XRMoSU}&gdW~OIo zVrph)sH0$HU}&Uo07PcGh9*{~W>!Y#3Q(W~w5=#5%__*n4QdyVXRDM^Qc_^0uU}qX zu2*iXmtT~wZ)j<02{OaTNEfI=x41H|B(Xv_uUHvof=g;~a#3bMNoIbY0?5R~r2Ntn zTP2`NAzsKWfE$}v3=Jk=fazBx7U&!58GyV5Q|Rl9UukYGTy=3tP%6T`SPd=?sVqp< z4@xc0FD*(2MqHXQ$f^P>=c3falKi5O{QMkPC z!8&|>tvvIJOA_;vQ$1a5m4IgGWoD*W8Cg2HSXdgG7+N~I85+8pTDTfHyBM1rm^eAQ zI=eX;!1TK0Czs}?=9R$orXcj1;?xUD47mkBn_W_iGRsm^+=}vZ6~Lah%Eav!Bb??z z^`_u`wbu7y74}i`@qKg@=O05llw0AQM&q`{yX!uDD`i* zBN_Vs{(JI8dgis%&(f0R{YUdfD*T%6Z@2t2je&3HnTOj|3dHt%GpzqvyQRYaQ?-M7 zUp{O7p}ZB>OMd;hWcBcDOy&N}Tf*AHeV2cHR`uPzjY-BR|KRknhV8$47uaXlMb9Xh zBiOVtf@$4}$H$m9*o(Xocq6jIpIv6XY43r#_A-78mj`q6->rR<89v9&-<0WpmDk!} z`;6%f>sDO;f3N4#yl;(DXMNan_g`w?(K#*4EyYWvY^RposNQv)b$0QgNZY3@X& z?|5|Q*BriT|8~`cV0E2mnehpQ{=XT*mu|DWn)v=@quC9HJ2@3qO!e~f!=?DE)_oN= fsk}8+o{^0~F{9jQ5{HEhsO0i=^>bP0l+XkKkUiar literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png new file mode 100644 index 0000000000000000000000000000000000000000..61aab196af23147ccb534d0def6e40438e278379 GIT binary patch literal 3273 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 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png new file mode 100644 index 0000000000000000000000000000000000000000..012386f97bdebb543b64312f7217c533c4038afe GIT binary patch literal 1772 zcmZvdc{Ce{7RDo%*mVq1Rn!EbmZGs|h;7tRYweL(L+#4cUXqkbiyB)hcoW*{7)y&# zYHU-|CPC7gP!b)xC<#id#=MzI*Ta?%&_}5j@?UWh75Y0ssIRmkW;G z$2;qb#l?8U8CThjA(6=52M?eJZ{IGV&}h8kfrsVfbsaSWMH!Fb@xpyMmsI#v>aWoA)7)5mJ=@C~eUWTB3}pYSBDG z4iu_l6M->^Z*6Rzw6wI8L&Bq@A2e>IBA<45|5hqb$xJXh)cEuh?4zj)tWDmP{rq`R zTwGks+`H$|ebg+xJx)xsz$n|WCqy4zTU(nL8~f(m6uQf9N^yI8duA)f2s%D8f(7|o zu=2-VI%({Tk#dQ~{LM|q&@Ct&8K`Gx(v4-!qZS@7Qrww`R1OPnTa5mn?I05X6xZ&8+uW#nH0E$;^LVhJNj z`j&J>xCpCgcK_9@fWVT{(kBfK8nz>m)Q~t$Hx~J_(5R!aHc>A_oU99qixd`97K$-=2IO(_e3%#g*B>GoI2JBNoGdaA=f)sr!dQ6vgwC@LOc zpJmdg_V|rJ(4O?-sya{=5EEoFl#-dbQSp9`!^tHgb^GLYEOhb>Swi_e7rDlc}Os-YjJLl`Gz< zTp|J_M!G5NewVNco^@HkBGym9{$N~-EJ@?gz!P&pTK&@KcyX(<2=XlkxavrJ4(F>_vmFmC)U(|rW*;F zFuGdJNQyjkvJbHKkCFWF<@SW)#70~ulbR~Oc$robi55?zVnM@AzQ9s(`5<#OgCm2@ zmry9wmGEbd8N=YN=%2)ycCh=XH=*Qp#|=nzc#o79iJ^m?w2=Hghn-{lOXaRE>qqJj zUpla#gma%GPNiwC$fSLH)FdJ^*FJVsSLqt&S+_|$;aSt<& z>w4W>M$?$Ah?TbT!uGTo$FSAa)nC|SnwX^*0~TM}Y_)EXY5)4rTvj|)9O&%qJZRF{ z=^Zs&uB+r{kxF)y$x2DteYTL*>bsWN7**SWC){ewbEr(XEfEvc$wybO)%f=TCZg$4 zUU#4b@aG3)o zEr0~=UzepseX~?qH2=_T_Em3v*%D>Ivkwk0=#U)h#f$Gz7iqq2}iQ0+KaT1{-&!K!iwNpQn-(Gv|8s#v`!B34pYp1GU z_+ME38yTX2pnqV6ChH4T6n^ztW=iRzy8i;rGVn%Sl0@t=#Q-i&?vCyDp}4;RCpS{9 literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_back.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_back.png new file mode 100644 index 0000000000000000000000000000000000000000..10fcfc1734a506b633c1f2fcd6aacc8da5595340 GIT binary patch literal 1317 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`vLFhHYsTY(OatnYqyQCInmZhe+73JqDfIV%MiPJ3>ZaB?@ z>P^Az76Y7m^?{Dj2SqJXRKtXT=?BDwCtM&0p7c}mfa$#mn6Otj$2&7HFi!V$aSW-r z_2$m$TqZ*SwuG{yGr112Uh;UgfG=KAap%sCDNL;eKCGDu$?`iEq+UN&b?oyGcd0_> zYwG9M*~qyQ=g!Z>z{ugiz$DPXz@os?zz|}8&3nJXv4~>Z_x$rW3p!2U4Uv3q z($p#>ebAEeg=L?{k~ocXwtSlAagEOk@-*)U{i|ZpI{NctL{e5k6vN6x57~m+4|6UN zYUlRQ!9&Wm1Y%yL}x#&fpAqJ3929B)=$m znfzmhfMhVon3+H#vQ4LisH~Z@BcOANI4UfJ$aG_q4;LMfxVL<{KgP1l-TmJ8&GS6J z-~0ZayvH+)`vW#@+XO*SfL^CIfmrPMe0{+Gg#FL}2(R;+Y(9&&^Q9PzLuocT4~O+6 zmXDio%vN^zdprq(ymt}iY(CqNj#_C_gn2L`2gv|71SO?77|dFP^Kc%XPf!ZMlb&k= zn6N1XhvE!~fl=WFgsz;$v&xNTYk84XZWE*=!$}Sl2#`3B!49&R;!uY|u&9fIv1eH< zfEOWrkwUOkRJI`lR?#dD$BAO1t%yVd%VZ)+Y@AFc*#}DziByb$R~9XaMdM_sG#*}l z1Rxu0v!f=pb~zWADFg*P&!A#)X=$mbG)6?T`C^G&F863irO^Np&6QC+=7^@a@D&9$ z&RJQ4;R%|8J&IT!UBW8_pwgu+kj$zq#VsEbI54pTW5f~>;@Q#)&|vs)C`qoOIo^c7 ztoL7qIdd6mv8X|(Qp-6%%UKOWSN#x2{i9{2ZppmN7G4V*OGEJk>Dv=eg znzojZIK{7UZ7;d%HMt%$kPOJI##!PBZqu?f2`_FMCDyJbZB4ypu5ImFlxuRupct{I zwf|`K$`bI8XSixyFj=)eP65BOz}QzWc5o21&Y@SQnH|HE&7T^*GlMjj&iEoF^@G7m zlYhs$1JB>7g_*l_Z%bJFFM)lpRS9!@tD<~%>9+f*oYM32Iwn==y7@6zt3UZsgW|zR z<+F>V#bT-2Igzm5*Sp%w8RP>(m_G=rVAwzCeIykGtO^7t1Oh-nn6LN73omA`e>Xn; zZKxK{xmr=y`S`{o_pLA8Ki@GK?*Cvfto5;7PjgBYO|yr0obzsqkBxn?t>MkmTNA@} zzks6@Iwy;l^|VcKr!E(8#a!VX&GAp%a{)~~3%)wTQq!bU{6hj z@7|e_@%n+IY2o9_?7Yzl_Z0er*a58)_5$#TvD%;u{PB`q zo6~qe;Me0i+Z%Zg8xU3|3N2Z`jp7>J{VM|pGf(wyiHh7uo_|_zYZp%bWWOl%!WYf)E&ss&)P^)XE89AlMy<6S=yVqwC z{gr{i`bKqN@K{~cpm#@Pdgn&7vC$UT)`&a~1(Gw0mYOa^(c;`KF$X@9V_|Qlp7(3| zvkK3-*%7hv+Fv0k_EqRq*4Bm72Q8NE8@BwfMlU(ySjt0Hl^0aw#}Tj8Oiz1mX1&I! J?o{T!`!{b?I;8*r literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..fa5646ca3f3f70f5ed0f8a8ed77700321f2dbe61 GIT binary patch literal 1546 zcmeAS@N?(olHy`uVBq!ia0vp^IUvlz1|<8_!p{OJ$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~NvfSU8(Io4OhpS~{5+8oHWVxEeXT7@HfII61mH zyEz%a^t$9Hm*%GCmB93-AoLpI)C)=sxdlL*T~doO%TiO^it=+6z@E0s#OW3nSDfZS z^`_u-i;Ejhz4}1M=!2pbDXL*Y!1M!R!V@l#15f&?dBF5u1WeeSU9ToHFfi44x;TbZ z+x^MvjD%6U(os7ih_f@(cPk(zHWpmusAF{4S<+sPzKEHMSJprq{zD}GNRnTc?bZcAdZ#$z` zc9U=08GSmo;I!SOxp(AiM0R^!VeYQl5V_s*`J{+izFe_AC%a~B__B6po!GNU9*53- zQvEQoG-9jg{XWmDS2mSL3JR5FZw~A6PT-s(JZ)R}Ew4=>!rxLhCl)XI5x!#DhAoAb z>$SW+Z)6+Z+Yob>bF%BhNi*IBt~|51dxP1>IUBww#oWN@ ze#;q5GU${uIHVf5iao@CMhyRoIR+=?0t^!`*)E7W^rYHBG%>Ntq18KSh1`YWLr&is z;)Km!F}~m38@Tn!gZh7Mem7RI|Cz$Ne|gw6)$~R}(TtoP9{B$hNMLwiR^0PE;t3)v{0BrlC@3fe4|?)arHbHD4?+(@Z-O&vlX_?chy5}0=6&D$-n=(!Gt(3O zy@S0R$Mu&c^)mg-^v(Aiqu;YT7ud!bV$?_l&y$uFB5vHla|o0?YXOy!lvuRT_g956%lglBh zEKgVM<%X>|aO?`m#VRH65V1h)E&7ofYp~6$(m68=5VT!LLxa1bYUT_m;1Gc{pGw%G zBmr6GrO~u3OCumDN=ZSakDQQ3)wHZ8GhlB(8ZC6@)v{jPi$zx&tP>Kbg3xNU_*RO? z;esG3io!UO$prOCL`y!g;)EX!cNlaO*`XT{7yE!QT64HbG)R^1rr-r#T0h!5CVF5( zYz2bEi!7y%qiO!z)$_XE5h1;+;QW;6fE0ScSvqrL@ zr!wMbe%vS&^I`|9W4q}gpLDR!J~n$OmNkPH(8xLp-5ba$hS&q`q*eC-Eh)n&X7xPd z%O0#{7wa6ZMLtxEK*b2Gw11VlW1{`TrrpM+i*D;9pZ0r58~fbFb)Q~})sjA5jlcZ- zu+hH)P8b{aUOpXpwDRoj>&@d+TPGiyJue=NO>F=={~gYY+wCc8Gv^; u-z|O|SRXq5|6}Xs*3^%$YwP8m+>t&`YW979d}`7(LNabua4}tEQRak_k-MsY zs8g=sig87gQK~q$AD)LRM4l$UARmYR*@2}s`z_DfeTH4?YUxhVib~%8h z<+-x8T(?AYd~ z1yz<8MKR_`CKJRX5jH(+MhPz*=`d(8v;xP+4)Q?EXwIW0EYl>@{SsWiOY4R0VTNwaWss7ySi@IJH$nJkndlK!*bJyY!QZNDX>W67DnPwzN7}w#3(2uwAeYt zLJeUQ){qa>k^n9krsa6C;bIG67?SRV*z_!@YcfqZ7{{?CAw8K9#FWB|ipcZ%^khD% zYN-r2q2%)Fw8C|;8nTvL=;035KESFyv9TCjpG4MR;M|7xbbwsYDq3=S=OXsxYh&%+ zx#W6cS&|GJxAu=#cT7Y-@w6*kvgk@5dPMI55w>#u(lEIccXcgSj=t`0<%U+c6WVs- z>WjXIC%2y*9ViTpZmzEDd#`>zf4cE`?dBRf`(y9@_{UFUyT=c|{P1{ot2i}$>i@^i kot^$);(g=6qnVXH>f766U)IMqH{uJb=jXI%%8h%!0gK8$qW}N^ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png new file mode 100644 index 0000000000000000000000000000000000000000..41d57747cd3b66d0771773394f3d96e7f59a52b3 GIT binary patch literal 1759 zcmaJ?c~BE)6yF#HL?S4H5-Z(V@B+yJNidNpkWBz35F$z%xk9oeDxD9JVv@f!TwRYv%By6-u!;Q_ulv3&X!1G zA}G#OX8-^wQIW8eu%X1W(8+;#k9#IsA_`T` zii=1H0FZsrco{AeNAr}JmZq>{XeOyKJ@f-69l3vK9s-~ zGsJoUqCq2b4anl$n0RGwhLWp-7R(1jOgutBi{J{-q|MYBc_uzIsLLbPb~haY2O)R{ zANr7#Oe_Hfm;nLVw4eYbgUJLr92%3w=5UyEz(58wkj@}(P5_g|V{>?c!QjUWBBB{o z={zYc`WTDY@gWV4>v?o~c6K%`JBWrE)O047%e89+1_ls_0Ar30SC|5HMxP-C7%?gh zs2)c#9cWinq+wY&A0jgSP=Z!JEUPnqJSO76=q81p&ZIHyB@F?^;{S(gwZmv5E=4}& z`=7$b_#8b#mm)?i%b+A0m+oT^rRNC@hyuq9@femlbczxUhGRwzrUwO!Ip8d@LW%0^ zj@g3@v6vU7GvW%J5{ZKO5TQXsQ5BCX6beOLIGD)|=P;Q<_FQ4001gUfu)@QH0#P_) zhzn!NEG?qLhq$Uw+_@ui?Zcqe6Om!WfUZPTA_Jxc2aD#RBj>^%QST#HHF7ST5xI0C z8M?i-|7!J+iRN|Z-87j6_k^_gZv3wo7}r0 zPk35Hek2n=KQsTPGHbJIg#Xzk$;@?B%3&oNS^JiD{!iBFp7AkdTl{Xbs9=5ND-Vx* z>IXzn`K5VRn5_qFfKAS5R=aJbQZ}h;7S~1Tp~tev*QjFmt}*UgV_%`H(CcF^b)wYz z_UZ=B_QT$`yv`5GFvs~;)h>P4vE0+gbVwGm+RYmoF%K3 zFMWH8t2ty?dWG7h+WQMIZ)w@s6ICTQwtIx3Qyx83*d%QK>wfyFv75?Yr)B+t^maF@ zemjtko^+Iq#^y$6X;{_`H*onXS=zA~WH|m%!`b>%2|GwDH_7X4X4L)ex@BX$yFJ+N zf*Z!f6wJ;`YXwg|#jSAGq9vD8%ggS+k(aujbZn`t3tzP@Wx%L)iTcXQ*KZzpODQan zz)A0%OuMx6-kpK}E}&CM z?6~&+*?vmR+c127@U|Od)iIZt75R@Z9_jnyg_-N!RS@zpD526JgkcL{?D=wgWf5so zitB1Mt*F$u2Uw_k%eC;@`gi79>H2BaVn55NOsnzU?xp!{$>-UlHEFjUIB%}^&&{>E z(9tuEXLI%puxrxGh3iROpQX%<29~Ff@7LA(EsC90iXC-qc{b&9!*t7TG_=BX<_|L@ zH>QrlU4-9mKC$*rzuX}*f0y6oy11G~j}&^9=e{`>YG}_RvSoTh!;1tn30Rh1S@C<2 R`(O57PLwbPJ{X?5<{wTppKbsE literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..bc1b06969dfb3abb2419fecf178fab8c466585ed GIT binary patch literal 1759 zcmaJ?X;2eq7+wesR6wDE2o<{q97H7tB!L7X5H=~ONg)IXSiu|%Ss>Y%EE293u^!l> zI3gmnmVyVCLn~TQv;?gnQ3aKSixB9*bM^q2X<$7zwdkJeV+GukDV=# z7k=zI$7c=z0IqSdkO*I+@MpCX5q~>B6?Nc?H^!4-iD)L4FV(_8v;vjEV4O;t1&d&* zqF`em9033Xe?%<7B!abUIjSN{Z9ZhZN`s>TAR+B+dh=M~( zVF;)KO$@9=Vhgo!VxdqhFU*m%6r{*iV1%BH6R2QJ3hGt4Y8_k8Ax-kK@x9GVA%T-F zSPqBuMwCPl55}Nc7-Wz`g5*>h4P-LOG&+OHq^$&lskC4U6~CE5G&-BXWCw?WQx^%3 zrd4FJMG$`~7JlN8lo+OAQz-fQ`Q-c%GOEp@&{!;%jUzZX2=@rm6{s<(K1i+en`VGu zom`7(Fa%YDHb$uo&BHh(TRGJxDwQj0Rc)=)osfI!$Q*9|tI|>B<@2XPGc z)HXxlBtjry$EkIgR4s?&APx!VAR~x^9m3=B!=Pv$jl~V4(Rhq7UT_Q)5=y0Wqj@oW zE_E6Uq4GQxtj4CXinmz)JF&K5P-*bU5UfQu!3w?>Re_U9vyoY}uz0u_7R18&n6qnn zgH_C;WeOYpPAml%L$S5?KdqiN;qznL&I~Som>GRojnBIlA8Y~D+Jb*C32{)gSbyt5 zUAVF;+GA@Lyxxrj#qQ<0yDUiCQOPA-oI@(FfZPW}&P#?umX|eD$i8rMf4^zjpw%Gr zlQfzA7HoqY+&3DPr|Sbf*19`6B=iq=c^w&KbUuDvbD+q)<*wo6>#wigzk289KRfq) zJMSx6ufeM^-r11+#LlJcvX3k185L=Dn2>y)A}?+7z2kry3M+^^Zj_~%=Sq$k0nyx1 z`;WQU3GYe2#Z$EN4? z>l*DE_L<$=S2x;`9=?a3O*xfKH|#ReBS&?dhKzMTErj9XLi?F@u zv6&us>?E(z?t^9|BVnY3FRZg`IDG!MMTBpBT-{m;^NWebHX~3#WN)o?2>5lEiQH&B~u%_r|KAxIVsK2g* zw&Q>c=hNuE%_VJsXISzl+Fe(WkSKps3r$%4(B*`jaX{0#N8+32UbU@Ty?8-hQaiWR z{>&4H)Pt1d?dimf>uWNvWmi`h0lX)*m&A2^!l*=W)Un8wx)lUbUcaOv|c>&*0;lL186hL=Lewc<14(=N$j-s+|s*2*G7OZoBvFY9>Z z?>&{z9PbbUUUX%oggNmBF7Gbgf9uCfe+aOQW9`PCm-h%G2G4urg3!IYOFZuK*h*Q) z(AaIa`d20M24%9pOSVvmvBm2Ni+eBdFwRfuge=4ELlalpvON~H?lW_l^%ox%1XfUV zeWl)1VB5%-$G`IiE#qO<+KK&HD&X$ChQH2QS{8%Nux97|oRsQ{{szaZmW7f1@>ROS zh+#*$dNXU>*+h4#w-!1@)M) zr7J890bzAT9K5>udp9(wHDr_r@|H!z|IGEI literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png new file mode 100644 index 0000000000000000000000000000000000000000..6d45e33cad0208b201e06a28a0511e4bba57acfe GIT binary patch literal 1505 zcmaJ>eM}Q)7(ZyjH%vY@VUq2$ zy3Mh<3LA!O$;g6pc9^IEKa!%LqFWX+mAPb!n!yAyj6miG?meWqKkP1d&+mPoJip)b zyzlem_LNu)VxwM-f*>f?TxhfbY!JSPFktuBlwSdm!kg@TDO1BYV;l+P5==D-n<=c8 zw2>Imvi%~N1wkT-qs-3REyXC#P;yL&k-I1supuZb$HiiJJ;}q>WUYhNBh&q75!gZK zk#dbiX<-dyoukmrk)>{H8Sbvfbp(==4QIJfAV85k2D_*R+KIaK$f7O^)`DAsz>6V# zy&id1l-*JS8yJp+HS%;Bu2iXDtyZqe&}g+PDXdni)CwhdwK7!(s?nnAOnB)*KsJu3 zL2btTrCeaAN9uTI8q?cV)_42idv3#@;35$y)P7Y zmbI{?!bUooMh*v!s}T#SSk%Cg7|(EJ4AT&}#gaOPXPk8m3mZzc@LCIoJ7~eNZjoWJ zpk~_1V>C{hjd}!V$Q=#>)n(*nnhYA9N|%?RQkgUxOlpHMJyV&HmuoWQ=P3hRBZD_m zB+Uo7#B*+LP_8fx6bmvNNzTzk68RiM!Hb7R9l>kK463)pC4$$oAt+Y?ictuy{ZFd{ zE-*jBa(QsUW_k2U8q7Nf20LpZZXSX{OU=gIGS_dDoky$#CCR%shK6c(cMd|4$w`s+ zn_kpN)o&)lF)MZ{1;APX_#ptE5C9P(04u@(td0R-NRCiG>QY>#PwaavKZWp* zd%V_TqYX-IVbnJ(ZS)%dxLmQtTfd3wIe2be)h`@fL5|$&(hu+G=xz5^OYK(ajfQ(q zJ~z7`AkkP(dKYy~b`bNAor+7uu5hntlkZpg&%CxzG<>MMqWJo!lkUGV-ihgdy7|2I zYT0ZOaXuUS)%W9f>rYSEKcGBoeBE<{_|}9?Qz0F`i)&AZ6aKxozX5jeb`P*ShbmwC z&^NvPhNxHa$yguooY@&SuZI)8;t`P=tJYUtPD~pW4Zcx)Jp3cdd|)~R&)RKzy7Fd` zKg??w?!KFXp}%k0EL|Bf@-^e|%*J;cwB)dNm1p8X^=Q$|wr#D-*lcNmw{ckP=f~6j zsk|HK=Upczw>C+SMvUCL)O+AgraC??PmA@N7sQ>Jo(VSfC#n+AlbYI&_zoM}p_v`T z_ir7&FxRHap(UdQGw-(BU*F?P?Z{5R43dY1o{z`+_8YIypPUlM&uzRfIELN^0b?h} z#qrvdZ|B=0zUs6+D)c-#WP5l4^fJ}Gx;;qSUew?BLc2m^pgTTddgzN)hlQW6*<>~T IkXQBozff5rN&o-= literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..92baf19cdd4a556f8130c5e048df71810fdc5093 GIT binary patch literal 1509 zcmeAS@N?(olHy`uVBq!ia0vp^IUvlz1|<8_!p{OJ$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~NwKnmC%fI-8mrS~{5+8oHWVxEeXT7@HfII61mH zyEz%a^t$9Hm*%GCmB93-AoQBy)C)=sxdlL*T~doO%TiO^it=+6z@E0s#NrkM3ukj@ zQ&%IL=0WwQ;C71%PQCg-$LNEi7AdM>LcsI`V!{(HkONQpsd>QkUIa|o&sKzHGcYiP zd%8G=RNQ(qXSE-5por^o7M4{SDWXiwDhUC;2bef_)i6F}f53l=-$a9lzn8)Hz=9PF z%$#g0T~Y$R66aF#E}7_FP@1v1`nuP)JnPlZ&&{=+JMEH*uS2^bALAj0#0G;F5XHd^ zqy*T2lp+t1a+Xlw5oj}T08&5|4ibkP8b1E7**J6acE>vLI3cULRPV=`#aZ2)pZ%{E zrLWwm@+<97(Ds-pE#gi>~4{qn$Ee`27=Rcjwd!hG`lY}!c?bGbgQ}C?MV?C{3lv?-5=U22%A~xRXM1=DUbQu;B({rj@OKW z*W|a`DtIU9ud8+dnq0i&J>$#`GBf2Sa0OrB?OQqCYOag%LAj`yM(eu>AHI=}Wa zgbQ8U_9ik+=RC*dhqpE*Sh~*O(>)#L!JTN85^R>g(`g2u{zCc)xcuPqru@il zHVQuNX_M}U<^gH`(|xITKXn<%>gg1F)+q}oDy0Z-oA|{3P^J3}KK6%quDQ(M>rWJq z~t*E2@5=g4fg4&t;ucLK6TY3=V7n literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png new file mode 100644 index 0000000000000000000000000000000000000000..a0404007d1e600294bcd23e28606737680a0bf3b GIT binary patch literal 1263 zcmaJ>ZD<>19KWhqA?rCy#_maEo zk`|=3h_zPcR<$rt8EX}TZcsL+Q0myIjBTLU!NhHKbpt_I-G?fZ>A>f@rt^dGxVz_h z{``Kw|0~Z#s;6^n!?p$t!?q^6xHMY3tgqgV{<~I>b)u!ojP;qlYQI_Jb%=#UH48yP z=5sI&d2y(47PezptwYN6nSIG_R#0Vvw=hIW)({)R+CwFc7Y3jSvM?tp0sQ9tNgPOG z0DqoIQb{ce^HSHa4ts}tGQ#kH;1}^w5VV(ABp^eR2PJurVz8wEzOKuny=5kGunsW? z0{Gpa`jROSRdom$!s8Msng%`}L3je-WqA{Am}z(~-v1OfGD8|9)6h@{ zbpbW5zu9u7u~8lJrmAODbx);=sk~~cMqbrGwATk(lDr@(mchBsNG92YVwk)lzyue- zkp>}2B1=&*j-kD+v_ImZ=@`=%b4NK(E9H%ZW6^kos&F|~7?h!6R=DClZd+BZH4L(b zJabT&_ChhPt1?(mnw6@@!c^7U;EL5_@m1xLC>YXe?Y~-GF`@afwwr^C4x6J76*TWU z8tj%cPkf1CHa@|HGo?#6F7JGBjM_5JOMjmG5axp3?CDc^N^y-Ctfi{`55Y_nDUy){Jt006nsanCcU&#}hE1$+HJ>a_)I2kJ-M)Kg*X%b1 zn{&lmTVC^X~QUow-Jm zwwK`)6J(kk#_Wl@siGPTq%)zCpMb=%@|5bzoe% Sc-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`vLFl!_sTY(OatnYqyQCInmZhe+73JqDfIV%MiOnqrt}dpA zCN4npjIp}~qBjMbTOfK}aq86vIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1zt}ka{ zVqjpL<>}%WQgQ3e?Tdwn6?hsR&N|H?xu|-Ja>?QYZn6uTOFHr#JkRm(`!a`VQm)e9 zU5^#@%l^0?^RNg$_p>#kpMlYVfsy6Hj>1WD559hWeu4YPKMVc+-a7M@CAY{;*A{ZH zR*Ib4d}V@;|0OMtYx9$mRQUTV1t(1}4KSayyfsPul1gUz6k)sM^(tF+)NH3o`ObW@ zRcy7}q6k(GGk(?rx#O9O^$p*aZY_V?x2E&4ZgY_TdW{C=fJr5i%ocTxlicd7R2FQqg zcezITPXDc{TuULzBf4w?4lEA-;aMw=-a1rTcWaX4og}vgC5Qe(JqF8z7g;VH=$vbM z_k)9)u{&!D}4c?w4M%t2WG0%KX0MtYYT- qHE!RzUA=gj6dD+qGG_b`O<-{KnKD_mRKO8bc6qw`xvXc-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`vLFjeHsTY(OatnYqyQCInmZhe+73JqDfIV%MiQ6rfIL(9V zO~LIJN1S@~fsWA!MJ-ZP!-Rn82gHOYTp$OY^i%VI>AeV;uZJq%vWY{0@iw>QHqNue#F`I7Qirp7LhH~(bn*Q@I7X#BR)GfBPVvBf`u z(}@BMECLP;vgTFq+2^eP9-IH*TXogGX^B<#6C6(${&Z%_a9*+|IY1)lnWGhp=5L*6 zZb37i#d>JHUXZ4;v^7aM=y_(jPy7%0YSpD_hAShoLQ*GX>3%a6I;!QcukgfypE7^F z#4qNSZr6X?XDH;Z+wA4N{=@;s6&1UB*!uJWI$!upTU0ry7Ns9PAjs5pY+(dzM*0HH zrMq{&tEy#mVH0FvWV!I`V*0L`OZy(#+@9q4=g1@mUWVFZI~i1(ggK`OsdH)Q_DN^h zDNYnS&bp-GGS8Bx%PdP;f@8ZwALNvk6~48mdKI;Vst0AG{1PXGV_ literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png new file mode 100644 index 0000000000000000000000000000000000000000..59108a061e992345451a79096653fe1415de4cd4 GIT binary patch literal 1718 zcmaJ?Yfuwc6kZS#OgK^U+V z86J)fHKmH7j!^A56fL!*&}vbus6dCJfQYmzrS>7URqISQNN9g(ckbPL@0s&`=R4<~ zoqaD|o$Bkg%nJYjU!_8pNv{g~^l+o!IX`!$(#ujRC6CI&^C`2&gaS!Ad@~9v4VnTp z6V>QSi!Y(^0N@ghW#>_Os&~X%+`!V<*Cv^DQ-eRK8qWtWg`eE5U>y)Um!qMfE+f$f!XvB#34K}Um)hJ1Q#BN zj%L#3i!){Ng;?}S0u@peA%uO7;J)2E(E^NoAt{ z>U}9OnO#bta3)IPB_=I>arsg9P=r`&LNyd_%Es{`M-|fxaSA63aRQWP2|$KQqs5GN z19KjsQi+vDlF}Hps8S|@Xbu*J>BQWXh+HN|IEW~jgCHqGDrp3VatNqVaJ4|%{*td&~OCJ_nA2rhbZlW8zUiMx^XX2eho@^=W!mo02=@e+g6fJv0RmPJ$9t_WbyA3` z-xbUE2W=mDJUjc=6~)e+jIoPPFv&#s_^FSFjy1)eIOXrr0C+lvlHT1|d-M|AUtAWj zBfdJmA`F?uBRDnIb7R8{Fkb8P_QdUE+d~MO*DJV7|{*Q1S*W^A*hnT zjSt|tE7wWh0N-Vx!n>AqZRrSx)Qm*Qtf=o!H4wVCzRYmxPrp$o-DdtGlmmO8if-uNRg=yu3w@?>i7 zh-q>f?mj=7vGw)!&uhjy_YAxCzvjmcYHjF4sb(TFXrPa68qyAZTFYd1|1s*3Pz&T z;Y?3AMpf5?rOS^GHIR{e4~@84UF6oFj;^4X>zz&Tr^OFBQ*|4rhMnJUV=#p%c{l8f zZ;p-IoUnbX>V(BlcLzL-=mH1*GbWI`b#!67r+1qF>IsidbdHXpr(?`*9Eosp0}hb9 Ueq=rOd;6b6nWC1RNZz#TA7HC`4*&oF literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle_active.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle_active.png new file mode 100644 index 0000000000000000000000000000000000000000..1ca88b2e77bff44d3d0a280f1f6019fa45172943 GIT binary patch literal 1712 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 Z3;?8)3)kRq7FGZN002ovPDHLkV1nzVWkdh~ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/player2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/player2.png deleted file mode 100755 index 7a099f7cbc6b3b37f9fde3d8991ebc8dfd7f54c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1290 zcmV+l1@-!gP)xa#EWr`qimBzPd%svMh?QJK~W9kwB3^kwB3^ zkwBqEVXl9m`&lZ~0`&J3hRT8}!J@pfAQxZ(>c9k8A!{h#VJ*MGlpL4A32-4_1u6v_ z!FmxVX5*T2IabTD9b5y)!6|SWw8AdXKDn`GMWI`SE8qY)8b*QGjoQGYV1c3EDB~Of zwt^qQnXm}N)^f_jU|R)V61RH?CWBfBaa`#H&-j#yIKEv0_Xkm+B6*4}K4)c)d6&Va zAh{UVE*G-0j^E&zcTQYyz*m7#MRQiUDA^@wXcM>pcDb@++c@yiHr%u|C1W-()R6`#OThWlFKnWwuwD2^?={l`}R#wZxyU_ErL}l~<<>*rb zzg#O>&C;|WT`W^0&Co4aPx~(7RYItnG>m?)f$l**%?At;;A^Nz-mf}h* zErE2$Hwx0PjNPFap<1&%RT5}JRiJ8m@5&NlG>dD$E3RZiOQ58xX_ufvE_P8Jm(r6Q z-Sc0ps0h^GQ)p3U{6w=8>Pt5n_TBOe!t-P0I%r9AyJJapX>3JxsHFME_fE$B=*RBj zT z9-(dQ!m(CL(@Cm9FxQPat{%88fe?pQ(335yH?4nHu}%qkP2OS5?ukySl>?Hy^~$cTt^noJEm?2MEYf$Bx9 zi6_k)Q7miE88T+ z{Q{3z^#6m*7mATUkw6h5fg*t-fg*tdi9Z4i03sp*7@m4q%>V!Z07*qoM6N<$g1rk{ AZ~y=R diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/player2_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/player2_pressed.png deleted file mode 100755 index 8fb075f6f02e2a44448241afc99f5f22f5d2a99a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2436 zcmV-~348X5P)^Q05ILxH@;DEeGmWK_G^!jEkLV-(^Ik{pOn4wX~nBtlw?Wu zhP?0N-|4GQQsZieuIWK7t99r(y%Xp&bYrp2wR?fzqdilqhGz8UuWW7SfFFaTH%ndf=p7!{2;w>V z&w;)YE;H`&d!B9TXnI+6Y)}*G{PgAYdMImEsnfW!LDHd02~t|`*<4BcJ`MZ=SZd`) zAZA~>qL?Ix9XUg=-&!hK_5h*2xS;6;%qb7DT23^8%!jHZ75b6T}m|9l*!P z)Z8P#+|=Im8#L$?;*0Kjp5ph!0+GP0h*v{!J)Sf9iPJsozr-kcqy$N8-6CjzNcg!ZupGCsN?9#KJi^^)DAt1BgFrKzB4hM2Rbu&`_d zL-P6}Ty2>6>cL70`dX2CWN8qtb%HgZ@d6o2+Di!mD(WqlpbmCrdbChI&$0$K#G+Fc z0sEeE3A&$9&j`}_|F8x(Z@{~sIDBWh1g#*d=YO(UV95AS5F=U`ZnnZHL0)2x$3VsW zuh~ElANDP3wOh#90w?N$d;J%c`jl&}&Y@GrSU*0y%`O^36g=wI?J(q@P;=_7cF*mY zAf)T3TxqEe1)s+-tLBH=kCujb5)o%H=4X$Avb~~j>yP-~Q4^}crcc@S!OfI28y9GH zF4jlHpR>ZrnPiLDFxw4szQw3@GlNAy)K+$u?PLi@ivf;}=W!M}(NZTdsE3IB=Y^7! z#KVu{!FAT_KxG3g%68=4P-HBUC8~~GY)25E6l*UymK9#HUxI3k50{pmxMDARk9}1z zK^KX`AGaf@oyb5ZgsUgV?kf9tD!VTqvjiDNvT@>YmmNV7YTidEL6`G2p1Tzb$_9bR`5)%QTYU@k^Vb-xdvKPOe`_P@Ir< zP$)eL!fnM9JM4m}W*EBRBMzs^CdgohSc2xUBNj@v2^tveTiM$JlT_-t;&ud$5ejNC zG(+5rRv~1_o(i&KANvbhD{Q4!*Y$Sd@Q58j+y_q=_FX2C=@P1-I-Po^vraPUqLZ|YwooWRTt#i{;rxT!lXDn_>myKIRwzNbK|RwMCj=cUA}Fi% z2(QIjprFNUBV6ZkM!&flM_&IZyADJ)F`>z-npE2i!{{tHJb^-W*hw{ioRH&vp_GUiN6rxMv7C(ms~(4ZO3!ygi481vJy^fiG}pFJAW$X?jomz4-b@Actqo zQ2c`ymHQ6+T-M(B+w^Y}<;S|jrNpXwCI<;&Fg2cf2(Cr#V&r={k|GGoUyMxIQ`rsh z?Pc{kq{pN2hb%V08~{1bIje@8*+~nMJdp3Eh# zff-8#M-%<2$<$_^uUVY3*=~DOwFGhFYw7={zQ9mAfYEI$0^`z}24i%})Wxa$vdQcw zc4c+gik!pcUc1u$Vths5cdW!-G5!utpe69MugN#&S|CO)26tMMO=rKHf7yXHzQoKo z){*Zwxw)Z^o84|hL-xq8_`<#yM9w8~#UNQ-h1zf(pQ|cyDo;;-2y)I?onS{$wS_0& zj?H~~D?s_Z#N94EnI1s!Jg<0_*S#U{u}a?1=Q&MgD$|2fXC%PhTkE$uyDN*yvOFlsQWUNjRs6~b5zit3-`LxQ5vd!v-swPQ665HN zT(=eU0ZIH#iSL1^H6~G|S3wXj@ZkM?kqPd?5JNloX-#%5Vs-I8rJpl|8ZL+Zi?kmV5HgWLxkG}}q?7}^G6@C!-6L7&T<~=p&S&pz7 zpZID5e@S#v1=r$BKzw5TF#G6#f^pqyHGLX4RNy*3wT`P%hP;_9yCYG zn%hjxFOLE*G{St++<(zEM^JSpAyuDap@jWUfB^u%Ivn7*IAxju0000wy diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png new file mode 100644 index 0000000000000000000000000000000000000000..13c556455c54149e318f16170ac9032f96f9aaf3 GIT binary patch literal 703 zcmeAS@N?(olHy`uVBq!ia0vp^F(Ayr1|%Q9zZAj1z|`jH;uunK>+PM~>_-kFM?XgR zuH}!o+ZDCYKaxf8ZTC{0yYK%W++<$BroS*}vr3`)-2aWAx6S>1I^~M_WRt#PZJug~tgc3$9_mpA{zRk>f{ zGR^sA3O1gYSei38VtM=$;j<=1{Eu!O{4IO`*12!izudUB#LPF}i+X-7|5dEJ^fmkI zKE`J)uAQknzJ1f>zlM`udG>GVNOI(UeQDRGb!(+xZ+m<lu0=g*{(ACP(%Cilt#A1l+hi_Vn--Jxtl?e%bhm?t-|-#qIKFSYUDibF z*Y~P6$gN%8_icsbw^^E(d%mlFDcI8zd+$Y|(S>Z2YpX>!%-^~qsd4=^`D^B{{a^3? z8h-rOx~=;&r-h&0c6kls-!QSmmm>dVe(HL#^7dWsy-EF*DHr|XPb<9nv_+{RPIS-v zbMI!(D=1u-D%g}ht5&mnqIH-QJOA;MUh-}?`w0y;`P4m90&Pl)hc(d{QV$@w`TR`Hxi0JF3x?twy8Z|qx@I; zQT~?TmIvx*_f2*Ev5d*$K?5@%^@w}A1?%3Q(66p#7r*jk`tAj7+B42Q5Z~F<>3!_n zgRT0K-v5~9WPg#`;kKU3Lfm!U!R&aENYOusR|hDwtS=VLQvIOv^Kj~Z!KUjw-)uMf gkzTK|?Aob(6}ilw^?yvB0~02Lr>mdKI;Vst096ZB;Q#;t literal 0 HcmV?d00001 diff --git a/TMessagesProj/src/main/res/drawable/attach_audio_states.xml b/TMessagesProj/src/main/res/drawable/attach_audio_states.xml new file mode 100644 index 000000000..881a09d0d --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_audio_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/attach_camera_states.xml b/TMessagesProj/src/main/res/drawable/attach_camera_states.xml new file mode 100644 index 000000000..3b437c248 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_camera_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/attach_contact_states.xml b/TMessagesProj/src/main/res/drawable/attach_contact_states.xml new file mode 100644 index 000000000..f8dbdd4ef --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_contact_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/attach_file_states.xml b/TMessagesProj/src/main/res/drawable/attach_file_states.xml new file mode 100644 index 000000000..c5604e3a2 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_file_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/attach_gallery_states.xml b/TMessagesProj/src/main/res/drawable/attach_gallery_states.xml new file mode 100644 index 000000000..40a9cf0f5 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_gallery_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/attach_hide_states.xml b/TMessagesProj/src/main/res/drawable/attach_hide_states.xml new file mode 100644 index 000000000..6fb0453d7 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_hide_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/attach_location_states.xml b/TMessagesProj/src/main/res/drawable/attach_location_states.xml new file mode 100644 index 000000000..942b7063d --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_location_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/attach_send_states.xml b/TMessagesProj/src/main/res/drawable/attach_send_states.xml new file mode 100644 index 000000000..9377186e9 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_send_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/attach_video_states.xml b/TMessagesProj/src/main/res/drawable/attach_video_states.xml new file mode 100644 index 000000000..93eb90089 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/attach_video_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/bar_selector_audio.xml b/TMessagesProj/src/main/res/drawable/bar_selector_audio.xml new file mode 100644 index 000000000..f311824b8 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/bar_selector_audio.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/floating_states.xml b/TMessagesProj/src/main/res/drawable/floating_states.xml index c2c53d129..55cb84eb4 100644 --- a/TMessagesProj/src/main/res/drawable/floating_states.xml +++ b/TMessagesProj/src/main/res/drawable/floating_states.xml @@ -1,13 +1,4 @@ - - - diff --git a/TMessagesProj/src/main/res/drawable/player_next_states.xml b/TMessagesProj/src/main/res/drawable/player_next_states.xml new file mode 100644 index 000000000..b3fe03129 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/player_next_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/player_pause_states.xml b/TMessagesProj/src/main/res/drawable/player_pause_states.xml new file mode 100644 index 000000000..713cd0bc3 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/player_pause_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/player_play_states.xml b/TMessagesProj/src/main/res/drawable/player_play_states.xml new file mode 100644 index 000000000..92447f398 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/player_play_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/player_prev_states.xml b/TMessagesProj/src/main/res/drawable/player_prev_states.xml new file mode 100644 index 000000000..e34bbba26 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/player_prev_states.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/search_dark_states.xml b/TMessagesProj/src/main/res/drawable/search_dark_states.xml deleted file mode 100644 index d1d4b4594..000000000 --- a/TMessagesProj/src/main/res/drawable/search_dark_states.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/TMessagesProj/src/main/res/drawable/search_light_states.xml b/TMessagesProj/src/main/res/drawable/search_light_states.xml deleted file mode 100644 index d1d4b4594..000000000 --- a/TMessagesProj/src/main/res/drawable/search_light_states.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/TMessagesProj/src/main/res/layout/player_big_notification.xml b/TMessagesProj/src/main/res/layout/player_big_notification.xml new file mode 100755 index 000000000..98c7f0bd2 --- /dev/null +++ b/TMessagesProj/src/main/res/layout/player_big_notification.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/layout/player_small_notification.xml b/TMessagesProj/src/main/res/layout/player_small_notification.xml new file mode 100755 index 000000000..43c2b9d32 --- /dev/null +++ b/TMessagesProj/src/main/res/layout/player_small_notification.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 8cbb7ef3a..5562767b2 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -65,6 +65,11 @@ أنت قمت بإنشاء قائمة رسالة جماعية إضافة مستلم إزالة من قائمة الرسالة الجماعية + + فضلًا قم بإضافة ملفات لمكتبتك الموسيقية على جهازك لتتمكن من مشاهدتها هنا. + موسيقى + الفنان غير معروف + العنوان غير معروف اختر ملف متاح %1$s من %2$s @@ -121,6 +126,7 @@ حذف هذه الدردشة قم بالسحب للإلغاء حفظ في الجهاز + احفظ في الموسيقى مشاركة تطبيق ملف التعريب المرفق غير مدعوم @@ -347,6 +353,7 @@ إيقاف الأصوات داخل المحادثات افتراضي + تلقائي إشعارات ذكية تعطيل أعلى صوت %1$s خلال %2$s @@ -827,6 +834,6 @@ h:mm a %1$s الساعة %2$s - تيليجرام نسخة الأندرويد تم تحديثه. الجديد في نسخة ٣.٠:\n\n- أقسام مخصصة خاصة ومرتبة لكل لحزم الملصقات. يمكنك إضافة حزم الملصقات كهذه https://telegram.me/addstickers/Animals\n- واجهة برمجية خاصة جديدة بالبوت، مجانًا للجميع. إذا كنت مبرمج، اصنع البوت الخاص بك مثل @quiz_bot و @hot_or_bot باستخدام حساب @botfather. للإستزادة، فضلًا اطلع على https://telegram.org/blog/bot-revolution - 551 + تم تحديث تيليجرام نسخة الأندرويد. الجديد في النسخة رقم 3.1:\n\n- بحث عن الرسائل داخل محادثات محددة. \n- إعادة تصميم كاملة لشاشة ارفاق الملفات. إرسال جهات اتصال وملفات صوتية مباشرة من خيار المرفقات. \n- تطوير لتشغيل الوسائط داخل التطبيق (يوتيوب, ڤيميو, ساوندكلاود وغيرها.),.\n\nللاستزادة، اطلع هنا:\nhttps://telegram.org/blog/search-and-media + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index df5390eb6..d171f0ee5 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -65,6 +65,11 @@ Du hast eine Broadcast Liste erstellt Empfänger hinzufügen Aus Broadcast Liste entfernen + + Bitte füge Musikdateien einfach deiner Android Musikbibliothek hinzu, um sie hier zu sehen. + Musik + Unbekannter Künstler + Unbekannter Titel Datei auswählen Freier Speicher: %1$s von %2$s @@ -121,6 +126,7 @@ Diesen Chat löschen WISCHEN UM ABZUBRECHEN In Downloads speichern + Musik speichern Teilen Sprachdatei benutzen Nicht unterstützte Datei @@ -208,7 +214,7 @@ Geteilte Medien Einstellungen Mitglied hinzufügen - Gruppe löschen und verlassen + Löschen und Gruppe verlassen Mitteilungen Aus der Gruppe entfernen @@ -347,6 +353,7 @@ Aus In-Chat-Töne Standard + Standard Intelligente Benachrichtigungen Deaktiviert Höchstens %1$s innerhalb von %2$s @@ -827,6 +834,6 @@ h:mm a %1$s um %2$s - Telegram für Android wurde aktualisiert. Neu in Version 3.0:\n\n- Neue Tabs im Sticker Panel für alle deine eigenen Sticker-Pakete. Füge neue Sticker wie beispielsweise https://telegram.me/addstickers/Animals hinzu.\n- Neue Bot API, für alle kostenlos verfügbar. Kannst du programmieren? Erstelle deine eigenen Bots für Spiele, Dienste oder Integrationen. Mehr dazu unter https://telegram.org/blog/bot-revolution - 551 + Telegram für Android wurde aktualisiert. Neu in Version 3.1:\n\n- Direkte Suche in Chats.\n- In Chats versteckt sich ein komplett neues Menü hinter der Büroklammer. Nun kann man dort auch Musik und Kontakte versenden.\n- In-App Medienwiedergabe für YouTube, Vimeo, SoundCloud, etc. optimiert und neuer Player für Audiodateien.\n\nMehr dazu unter:\nhttps://telegram.org/blog/search-and-media + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 8cc0c49f4..3c328ef1b 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -65,6 +65,11 @@ Creaste una lista de difusión Añadir destinatario Quitar de la lista de difusión + + Por favor, añade archivos a la carpeta de música en tu dispositivo para verlos aquí. + Música + Artista desconocido + Título desconocido Elegir archivo %1$s de %2$s libres @@ -121,6 +126,7 @@ Eliminar este chat DESLIZA PARA CANCELAR Guardar en descargas + Guardar en música Compartir Aplicar traducción Adjunto no soportado @@ -347,6 +353,7 @@ Apagado Sonidos en el chat Por defecto + Por defecto Notificaciones inteligentes Desactivadas Sonar como máximo %1$s en %2$s @@ -827,6 +834,6 @@ h:mm a %1$s a las %2$s - Telegram para Android fue actualizada. Novedades en la versión 3.0:\n\n- Pestañas dedicadas para cada uno de tus packs de stickers personalizados en el panel de stickers. Añade stickers personalizados como: https://telegram.me/addstickers/Animals\n- Nueva API para bots, gratis para todos. Si eres un ingeniero, crea tus propios bots para juegos, servicios o integraciones. Conoce más en: https://telegram.org/blog/bot-revolution - 551 + Telegram para Android fue actualizada. Novedades en la versión 3.1:\n\n- Busca mensajes dentro de un chat en específico.\n- Menú para adjuntar completamente rediseñado. Envía contactos y archivos de audio directamente desde el menú para adjuntar.\n- Reproducción de multimedia dentro de la aplicación mejorada (YouTube, Vimeo, SoundCloud etc.), nuevo reproductor para archivos de audio largos.\n\nMás sobre esta actualización:\nhttps://telegram.org/blog/search-and-media + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 8b5e8022f..d826f248b 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -65,6 +65,11 @@ Hai creato una lista broadcast Aggiungi destinatario Rimuovi dalla lista broadcast + + Aggiungi file nella libreria musicale del tuo dispositivo per vederli qui. + Musica + Artista sconosciuto + Titolo sconosciuto Seleziona file Liberi %1$s di %2$s @@ -121,6 +126,7 @@ Elimina questa chat ANNULLA Salva nei download + Salva nella musica Condividi Applica traduzione Allegato non supportato @@ -284,7 +290,7 @@ Utenti bloccati Disconnetti Nessun suono - Predefinita + Predefinite Supporto Solo se silenzioso Sfondo chat @@ -295,7 +301,7 @@ Un contatto si è unito a Telegram PEBBLE Lingua - Nota che il supporto di Telegram è fornito da volontari. Proviamo a rispondere non appena possibile, ma potrebbe volerci un pò.
]]>Dai un\'occhiata alle FAQdi Telegram
]]>: troverai risposte alla maggior parte delle domande e suggerimenti importanti per l\'individuazione del problema]]>
+ Nota che il supporto di Telegram è fornito da volontari. Proviamo a rispondere non appena possibile, ma potrebbe volerci un pò.
]]>Dai un\'occhiata alle FAQ di Telegram]]>: troverai risposte alla maggior parte delle domande e suggerimenti importanti per l\'individuazione del problema]]>
Chiedi a un volontario FAQ di Telegram https://telegram.org/faq/it @@ -347,6 +353,7 @@ No Suoni in-chat Predefinito + Predefinita Notifiche intelligenti Disabilitate Suona al massimo %1$s in %2$s @@ -452,12 +459,12 @@ Reinserisci la tua password E-mail di recupero La tua e-mail - Per favore inserisci un\'e-mail valida. È l\'unico modo di recuperare una password dimenticata. + Inserisci un\'e-mail valida. È l\'unico modo di recuperare una password dimenticata. Salta Attenzione No, seriamente.\n\nSe dimentichi la tua password, perderai l\'accesso al tuo account Telegram. Non ci sarà modo di ripristinarlo. Ci siamo quasi! - Per favore controlla la tua e-mail (anche lo spam) per completare la configurazione della verifica in due passaggi. + Controlla la tua e-mail (anche lo spam) per completare la configurazione della verifica in due passaggi. Fatto! La password per la verifica in due passaggi è ora attiva. Cambia password @@ -466,16 +473,16 @@ Cambia e-mail di recupero Sei sicuro di voler disabilitare la tua password? Suggerimento password - Per favore crea un suggerimento per la tua password + Crea un suggerimento per la tua password Le password non corrispondono Annulla configurazione della verifica in due passaggi - Per favore segui questi step per completare la configurazione della verifica in due passaggi:\n\n1. Controlla la tua e-mail (anche lo spam)\n%1$s\n\n2. Clicca sul link di conferma. + Segui questi step per completare la configurazione della verifica in due passaggi:\n\n1. Controlla la tua e-mail (anche lo spam)\n%1$s\n\n2. Clicca sul link di conferma. Il suggerimento deve essere diverso dalla password E-mail non valida Scusa Siccome non hai fornito un\'email di recupero quando hai impostato la tua password, non ti resta che ricordarti la password o ripristinare il tuo account. Abbiamo inviato un codice di ripristino alla e-mail che ci hai fornito:\n\n%1$s - Per favore controlla la tua e-mail e inserisci il codice a 6 cifre che ti abbiamo inviato. + Controlla la tua e-mail e inserisci il codice a 6 cifre che ti abbiamo inviato. Hai problemi ad accedere alla tua e-mail %1$s? Se non puoi ripristinare l\'accesso alla tua e-mail, non ti resta che ricordarti la password o ripristinare il tuo account. RIPRISTINA IL MIO ACCOUNT @@ -508,10 +515,10 @@ Se lontano per Se non ti connetti almeno una volta in questo periodo, il tuo account verrà eliminato insieme a tutti i gruppi, messaggi e contatti. Eliminare il tuo account? - Cambia chi può vedere il tuo Ultimo Accesso. - Chi può vedere il tuo Ultimo Accesso? + Cambia chi può vedere il tuo ultimo accesso. + Chi può vedere il tuo ultimo accesso? Aggiungi eccezioni - Importante: non sarai in grado di vedere l\'Ultimo Accesso delle persone con le quali non condividi l\'Ultimo Accesso. Verrà mostrato un orario approssimativo (di recente, entro una settimana, entro un mese). + Importante: non sarai in grado di vedere l\'ultimo accesso delle persone con le quali non condividi l\'ultimo accesso. Verrà mostrato un orario approssimativo (di recente, entro una settimana, entro un mese). Condividi con Non condividere con Queste impostazioni annulleranno i valori precedenti. @@ -519,7 +526,7 @@ Condividi con gli utenti... Non condividere Non condividere con gli utenti... - Aggiungi Utenti + Aggiungi utenti Ci spiace, troppe richieste. Impossibile cambiare le impostazioni di privacy ora, attendi. Disconnette tutti i dispositivi tranne questo. Tieni premuto sull\'utente per eliminarlo. @@ -682,12 +689,12 @@ %1$d oggetti %1$d oggetti %1$d oggetti - in nessuna chat - in %1$d chat - in %1$d chat - in %1$d chat - in %1$d chat - in %1$d chat + da nessuna chat + da %1$d chat + da %1$d chat + da %1$d chat + da %1$d chat + da %1$d chat %1$d secondi %1$d secondo %1$d secondi @@ -827,6 +834,6 @@ h:mm a %1$s alle %2$s - Telegram per Android è stato aggiornato. Nuovo nella versione 3.0:\n\n- Pagine dedicate per ognuno dei tuoi pacchetti sticker nel pannello sticker. Aggiunti sticker personalizzati come https://telegram.me/addstickers/Animals\n- Nuova API per i bot, gratis per tutti. Se sei un ingegnere, crea i tuoi bot per giochi, servizi o integrazioni. Scopri di più su https://telegram.org/blog/bot-revolution - 551 + Telegram per Android si è aggiornato. Nuovo nella versione 3.1:\n\n- Cerca messaggi all\'interno di una specifica chat.\n- Menu degli allegati completamente ridisegnato. Invia contatti e audio direttamente dal menu degli allegati.\n- Riproduzione in-app migliorata (YouTube, Vimeo, SoundCloud etc.), nuovo player per i file audio.\n\nMaggiori informazioni su questo aggiornamento:\nhttps://telegram.org/blog/search-and-media + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index f4eec4eeb..f2fc30ddf 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -65,6 +65,11 @@ 단체 메시지 리스트를 만들었습니다 받는 사람 추가 리스트에서 제외 + + 음악 라이브러리에 파일을 추가하셔야지만 볼 수 있습니다. + 음악 + 알수 없는 아티스트 + 알 수 없는 제목 파일 선택 %2$s 중 %1$s 남음 @@ -121,6 +126,7 @@ 이 채팅방 삭제 밀어서 취소 다운로드 폴더에 저장 + 음악으로 저장 공유 언어 파일 적용 지원하지 않는 형식입니다 @@ -347,6 +353,7 @@ 채팅중 소리 설정 기본값 + 기본값 스마트 알림 비활성화됨 최대 %1$s번, %2$s번 이내 알림 @@ -827,6 +834,6 @@ a h:mm %1$s %2$s - 텔레그램 안드로이드 버전이 업데이트 되었습니다. 새로운 버전은 3.0 입니다:\n\n- 스티커 패널에 커스텀 스티커별 탭 지원. https://telegram.me/addstickers/Animals 와 같은 커스텀 스티커 추가 기능\n- 신규 봇 API를 무료로 공개합니다. 개발자라면 누구나 게임, 서비스나 통합 봇등 개발이 가능합니다. https://telegram.org/blog/bot-revolution 에서 자세한 사항을 알아보세요. - 551 + 텔레그램 안드로이드 버전이 업데이트 되었습니다. 새로운 버전은 3.1 입니다:\n\n- 특정 대화창에서 검색. \n- 첨부 메뉴 개선. 해당 메뉴에서 바로 연락처, 오디오를 전송 가능. \n- 인앱 미디어 재생 기능 향상 (YouTube, Vimeo, SoundCloud etc). 대용량 오디오 파일 별도 플레이어 기능. \n\nhttps://telegram.org/blog/search-and-media에서 자세한 사항을 알아보세요. + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index 49562999d..487122018 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -65,6 +65,11 @@ Je hebt een verzendlijst gemaakt Ontvanger toevoegen Verwijder van verzendlijst + + Voeg bestanden toe aan de muziekbibliotheek op je apparaat om ze hier te zien. + Muziek + Onbekende artiest + Onbekende titel Kies een bestand Vrij: %1$s van %2$s @@ -121,6 +126,7 @@ Chat verwijderen SLEEP OM TE ANNULEREN Opslaan in Downloads + Opslaan in muziek Delen Vertaling toepassen Bestandstype niet ondersteund @@ -347,6 +353,7 @@ Uit Chatgeluiden Standaard + Standaard Slimme meldingen Uitgeschakeld Geluid maximaal %1$s per %2$s @@ -827,6 +834,6 @@ h:mm a %1$s om %2$s - Telegram voor Android is geüpdatet. Nieuw in versie 3.0:\n\n- Tabbladen voor al je eigen stickerbundels in het stickerpaneel. Voeg stickerbundels zoals: https://telegram.me/addstickers/Animals toe.\n- Nieuwe bot-API, gratis voor iedereen. Handig met programmeren? Maak dan je eigen bots voor spelletjes, diensten of integraties. Meer weten? kijk op: https://telegram.org/blog/bot-revolution - 551 + Telegram voor Android is bijgewerkt. Nieuw in versie 3.1:\n\n- Zoek naar berichten in een specifieke chat.\n- Volledig opnieuw ontworpen bijlagemenu. Verstuur contacten en audiobestanden rechtstreeks vanuit het bijlagemenu.\n- Afspelen van media in de app verbeterd (YouTube, Vimeo, SoundCloud, etc.), nieuwe speler voor grote audiobestanden.\n\nMeer weten? Kijk op:\nhttps://telegram.org/blog/search-and-media + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index 4b4e6d254..d9e826d5b 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -65,6 +65,11 @@ Você criou uma lista de transmissão Adicionar destinatário Remover da lista de transmissão + + Por favor, adicione arquivos à biblioteca de música de seu dispositivo para vê-los aqui. + Música + Artista desconhecido + Título desconhecido Selecione um Arquivo Disponível %1$s de %2$s @@ -121,6 +126,7 @@ Apagar este chat DESLIZE PARA CANCELAR Salvar em downloads + Salvar em músicas Compartilhar Aplicar arquivo de localização Anexo não suportado @@ -347,6 +353,7 @@ Desativado Sons no Chat Padrão + Padrão Notificações Inteligentes Desativado Tocar no máximo %1$s a cada %2$s @@ -827,6 +834,6 @@ h:mm a %1$s às %2$s - Seu Telegram para Android acaba de ser atualizado. Novo na versão 3.0:\n\n- Abas dedicadas para cada um dos pacotes customizados de stickers no painel de stickers. Adicione stickers customizados como https://telegram.me/addstickers/Animals\n- Nova API de bots, gratuita para todos. Se você for um engenheiro, crie seus próprios bots como @quiz_bot ou @hot_or_bot usando o @botfather. Leia mais em https://telegram.org/blog/bot-revolution - 551 + Telegram para Android foi atualizado. Novo na versão 3.1:\n\n- Busca por mensagens dentro de um chat específico.\n-Menu de anexo totalmente redesenhado. Envie contatos e arquivos de áudio diretamente do menu de anexo.\n- Reprodução melhorada de mídia dentro do aplicativo (YouTube, Vimeo, SoundCloud, etc.), novo player para grandes arquivos de áudio.\n\nMais sobre a atualização:\nhttps://telegram.org/blog/search-and-media + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml index a544d799b..02883ee2d 100644 --- a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml @@ -65,6 +65,11 @@ Você criou uma lista de transmissão Adicionar destinatário Remover da lista de transmissão + + Por favor, adicione arquivos à biblioteca de música de seu dispositivo para vê-los aqui. + Música + Artista desconhecido + Título desconhecido Selecione um Arquivo Disponível %1$s de %2$s @@ -121,6 +126,7 @@ Apagar este chat DESLIZE PARA CANCELAR Salvar em downloads + Salvar em músicas Compartilhar Aplicar arquivo de localização Anexo não suportado @@ -347,6 +353,7 @@ Desativado Sons no Chat Padrão + Padrão Notificações Inteligentes Desativado Tocar no máximo %1$s a cada %2$s @@ -827,6 +834,6 @@ h:mm a %1$s às %2$s - Seu Telegram para Android acaba de ser atualizado. Novo na versão 3.0:\n\n- Abas dedicadas para cada um dos pacotes customizados de stickers no painel de stickers. Adicione stickers customizados como https://telegram.me/addstickers/Animals\n- Nova API de bots, gratuita para todos. Se você for um engenheiro, crie seus próprios bots como @quiz_bot ou @hot_or_bot usando o @botfather. Leia mais em https://telegram.org/blog/bot-revolution - 551 + Telegram para Android foi atualizado. Novo na versão 3.1:\n\n- Busca por mensagens dentro de um chat específico.\n-Menu de anexo totalmente redesenhado. Envie contatos e arquivos de áudio diretamente do menu de anexo.\n- Reprodução melhorada de mídia dentro do aplicativo (YouTube, Vimeo, SoundCloud, etc.), novo player para grandes arquivos de áudio.\n\nMais sobre a atualização:\nhttps://telegram.org/blog/search-and-media + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 903c5d2cd..782c27627 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -1,6 +1,7 @@ + Telegram English @@ -64,6 +65,11 @@ You created a broadcast list Add recipient Remove from broadcast list + + Please add files to the music library on your device to see them here. + Music + Unknown artist + Unknown title Select File Free %1$s of %2$s @@ -120,6 +126,7 @@ Delete this chat SLIDE TO CANCEL Save to downloads + Save to music Share Apply localization file Unsupported attachment @@ -346,6 +353,7 @@ Off In-Chat Sounds Default + Default Smart Notifications Disabled Sound at most %1$s within %2$s @@ -826,6 +834,6 @@ h:mm a %1$s at %2$s - Telegram for Android has been updated. New in version 3.0:\n\n- Dedicated tabs for each one of your custom sticker sets in the sticker panel. Add custom stickers like https://telegram.me/addstickers/Animals\n- New bot API, free for everyone. If you\'re an engineer, create your own bots for games, services or integrations. Learn more at https://telegram.org/blog/bot-revolution - 551 + Telegram for Android has been updated. New in version 3.1:\n\n- Search for messages inside a specific chat.\n- Fully redesigned attachment menu. Send contacts and audio files straight from the attachment menu.\n- Improved in-app media playback (YouTube, Vimeo, SoundCloud etc.), new player for large audio files.\n\nMore about this update:\nhttps://telegram.org/blog/search-and-media + 577 \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values/styles.xml b/TMessagesProj/src/main/res/values/styles.xml index 56449ed43..444570aed 100644 --- a/TMessagesProj/src/main/res/values/styles.xml +++ b/TMessagesProj/src/main/res/values/styles.xml @@ -73,8 +73,8 @@ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 27fd29715..89ecdcf96 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip